mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-02-01 15:57:48 +00:00
Compare commits
806 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7467a2a2eb | ||
|
|
2459a53350 | ||
|
|
7093e9c0d4 | ||
|
|
4bc49978d1 | ||
|
|
96bac9c149 | ||
|
|
8dcc15f4d3 | ||
|
|
8183740c04 | ||
|
|
25e4231d7b | ||
|
|
3ed9e0e905 | ||
|
|
45bec0c440 | ||
|
|
5133e39d45 | ||
|
|
cb3b4e446e | ||
|
|
9829a2f3b4 | ||
|
|
7eadf11145 | ||
|
|
2a2bc44f43 | ||
|
|
9ccfa5cec9 | ||
|
|
02687f3c78 | ||
|
|
7ea7a6cbb1 | ||
|
|
a15a28fe5b | ||
|
|
265dedfae1 | ||
|
|
5ddbb8bc56 | ||
|
|
4101b8e937 | ||
|
|
56b6d50479 | ||
|
|
506f585d78 | ||
|
|
577dfb7220 | ||
|
|
7e4286adde | ||
|
|
1090228628 | ||
|
|
aeea861b73 | ||
|
|
997c43bbdd | ||
|
|
958d4dbd2e | ||
|
|
f2b350eb62 | ||
|
|
a3464780a1 | ||
|
|
fe1eb92196 | ||
|
|
0b2d26ec92 | ||
|
|
8024a25f2b | ||
|
|
d287ecbb34 | ||
|
|
d9c95e7730 | ||
|
|
c3b1af31ce | ||
|
|
465576b5cb | ||
|
|
9ecbcd0075 | ||
|
|
c1f62d72ae | ||
|
|
1b27834c41 | ||
|
|
77804907b6 | ||
|
|
9dfa2609be | ||
|
|
8ffb3ab3c4 | ||
|
|
65e1da34fa | ||
|
|
282110807c | ||
|
|
25e5f43d1c | ||
|
|
ce0441694d | ||
|
|
db29699927 | ||
|
|
9a4e2d7617 | ||
|
|
fbf64585b7 | ||
|
|
6d1c6dfd16 | ||
|
|
e78df4d981 | ||
|
|
a757b4d5dc | ||
|
|
d28036ee91 | ||
|
|
d2ba0d4e7a | ||
|
|
5787436177 | ||
|
|
f5ab24b8d2 | ||
|
|
05c0f32a24 | ||
|
|
7b918f77a9 | ||
|
|
d87929d61c | ||
|
|
a926829c33 | ||
|
|
d58e366c40 | ||
|
|
0fb4f7e1c4 | ||
|
|
6ee606e3e2 | ||
|
|
22d4a7690f | ||
|
|
f3a2f5018a | ||
|
|
d2a7589f7c | ||
|
|
f87b4e04f1 | ||
|
|
b5aa4c1f0c | ||
|
|
0c1eb6d288 | ||
|
|
8a03c5f998 | ||
|
|
60aa50ae45 | ||
|
|
aae6bbbb66 | ||
|
|
5ca903c428 | ||
|
|
e86b07f760 | ||
|
|
d7fea5dc78 | ||
|
|
c1eff5aebb | ||
|
|
f2dc490d6f | ||
|
|
b296e1b340 | ||
|
|
8adb060edb | ||
|
|
c3b984fea7 | ||
|
|
afbb2c338b | ||
|
|
6632241ab5 | ||
|
|
be50df81db | ||
|
|
9763b6e2cf | ||
|
|
812b848daf | ||
|
|
4907a7389f | ||
|
|
17dff36b65 | ||
|
|
904921d8c4 | ||
|
|
ac4c075d32 | ||
|
|
ddde64ece9 | ||
|
|
91c097e88d | ||
|
|
894658a3f5 | ||
|
|
a4454ea5f9 | ||
|
|
8ea8fa3a8a | ||
|
|
7480603295 | ||
|
|
079b749d5d | ||
|
|
4815600e85 | ||
|
|
1c63e2d295 | ||
|
|
cf13eca58c | ||
|
|
3cf4607870 | ||
|
|
23c3ba6ad7 | ||
|
|
17fc3c2317 | ||
|
|
af234cbe54 | ||
|
|
c8517c0ec9 | ||
|
|
20b226454b | ||
|
|
98eccf223a | ||
|
|
0fc2ab4d41 | ||
|
|
641b6efe7f | ||
|
|
4c83435b4b | ||
|
|
9f7319cff4 | ||
|
|
dd9baa1502 | ||
|
|
41b4d0daa1 | ||
|
|
e41b181163 | ||
|
|
288ac115d0 | ||
|
|
6774d46a6f | ||
|
|
607abf89f7 | ||
|
|
27f1e5e2f2 | ||
|
|
a457675ce1 | ||
|
|
82049096e6 | ||
|
|
6c965e0223 | ||
|
|
8b4d952929 | ||
|
|
873cc63f94 | ||
|
|
39fc839ff2 | ||
|
|
4edef4c959 | ||
|
|
1d9ced8037 | ||
|
|
4cb77d1429 | ||
|
|
b52d9d1bdd | ||
|
|
5fe7ca5e70 | ||
|
|
62fb440de2 | ||
|
|
96fbd7c7ba | ||
|
|
c9bec8e636 | ||
|
|
769e03e7f2 | ||
|
|
ab83f2d5e2 | ||
|
|
b60d0cdb17 | ||
|
|
677503dbf1 | ||
|
|
25efa29470 | ||
|
|
21a90f8f8f | ||
|
|
64e8d6ae99 | ||
|
|
16a204335e | ||
|
|
0a53f762fe | ||
|
|
6ba4778c1b | ||
|
|
0404c2266c | ||
|
|
e5e914282f | ||
|
|
9867d4bdc3 | ||
|
|
e4cb7112cf | ||
|
|
2d202e90b7 | ||
|
|
016391e442 | ||
|
|
1eff48a429 | ||
|
|
ce33af6bb5 | ||
|
|
fb9d4303f1 | ||
|
|
4e631c9e8f | ||
|
|
766d67d80d | ||
|
|
e2c2a37221 | ||
|
|
2b23020695 | ||
|
|
8d43c6b1a8 | ||
|
|
7362dd1a7c | ||
|
|
316caf7e8c | ||
|
|
87dc6631ee | ||
|
|
62246d7d43 | ||
|
|
a14be3a42c | ||
|
|
7fdf00d5e9 | ||
|
|
99e02f30fb | ||
|
|
716a5b9b5a | ||
|
|
87f880ca52 | ||
|
|
8ec7b84a78 | ||
|
|
05cf5bc8db | ||
|
|
ac25e21a0c | ||
|
|
cc1e0daaa4 | ||
|
|
f4120a9c8c | ||
|
|
e3b80a5e09 | ||
|
|
ef7cb26b01 | ||
|
|
408a5c168f | ||
|
|
0ad6ac95b2 | ||
|
|
bda4747e9c | ||
|
|
bd8f882c94 | ||
|
|
32b5b5b1c4 | ||
|
|
c1e543c9fe | ||
|
|
3908fa5c57 | ||
|
|
1b347fc185 | ||
|
|
282a5e0b01 | ||
|
|
e9d23cc1ea | ||
|
|
34173fd60f | ||
|
|
d0d3c8ef57 | ||
|
|
11912008dd | ||
|
|
c122007e17 | ||
|
|
69dfa1a175 | ||
|
|
bfea443e55 | ||
|
|
680798c28f | ||
|
|
9f0cc45c45 | ||
|
|
0ac97f467f | ||
|
|
647746ea72 | ||
|
|
7bea30b2e6 | ||
|
|
12bc852c89 | ||
|
|
0d42e84045 | ||
|
|
897b85b607 | ||
|
|
5c55cf0efb | ||
|
|
eccd6463f6 | ||
|
|
4a0897c734 | ||
|
|
c86a16df7f | ||
|
|
2ae0e9d902 | ||
|
|
bba18cd56b | ||
|
|
2f20781e16 | ||
|
|
3bee212876 | ||
|
|
6c8893a550 | ||
|
|
9c52ecc19b | ||
|
|
692c884ca2 | ||
|
|
3ef51d7fae | ||
|
|
73d95de122 | ||
|
|
04a568ac9b | ||
|
|
a45499cf04 | ||
|
|
b847d672ab | ||
|
|
3ffefdf6b5 | ||
|
|
cca4c4be80 | ||
|
|
cb9e044cb3 | ||
|
|
fd25dd83bd | ||
|
|
584bb00cfc | ||
|
|
5b9369d344 | ||
|
|
a64506a0de | ||
|
|
2fc83ef80b | ||
|
|
8bee3ebd65 | ||
|
|
99686fdd73 | ||
|
|
33bc3d6a1e | ||
|
|
90597530a4 | ||
|
|
b2af8da9a2 | ||
|
|
05dbf41fdc | ||
|
|
c56bb56708 | ||
|
|
4def1ea1dc | ||
|
|
0ba05e4de0 | ||
|
|
24fce89155 | ||
|
|
1a3c20f91d | ||
|
|
fe3e78cc1c | ||
|
|
749f49b1a0 | ||
|
|
f14010a09d | ||
|
|
0b48b9c7d4 | ||
|
|
13d62b01d1 | ||
|
|
4e7b71db1d | ||
|
|
069fc1f97b | ||
|
|
8684f75254 | ||
|
|
11cd924ce1 | ||
|
|
e2fd0cfc4e | ||
|
|
5eb3106706 | ||
|
|
1831efbe9d | ||
|
|
38edbadca5 | ||
|
|
6fcd80b979 | ||
|
|
cf5e5dbe55 | ||
|
|
a451861bf1 | ||
|
|
7313dd74a6 | ||
|
|
32b9de05f2 | ||
|
|
c79bed22f8 | ||
|
|
cdeb50132d | ||
|
|
090fb09955 | ||
|
|
54b862bd79 | ||
|
|
e37e1c109a | ||
|
|
939123785b | ||
|
|
221b347bd9 | ||
|
|
af9bf3e852 | ||
|
|
ed8746df77 | ||
|
|
bb187db49d | ||
|
|
081e72b3ea | ||
|
|
6188c38053 | ||
|
|
12b0186f5a | ||
|
|
9bccc9c53c | ||
|
|
351b2b320e | ||
|
|
94258feb09 | ||
|
|
8b0f033a78 | ||
|
|
f58f255fc8 | ||
|
|
e3eabcf648 | ||
|
|
9aa506cbd7 | ||
|
|
d8cff7b90f | ||
|
|
07e7bca9eb | ||
|
|
e1f442be90 | ||
|
|
c5d579e0e3 | ||
|
|
5271c2e08f | ||
|
|
9010a7ddbc | ||
|
|
bb95fb7d07 | ||
|
|
2edb11376d | ||
|
|
e7f5ebf912 | ||
|
|
da9758c2f3 | ||
|
|
3e11d58d73 | ||
|
|
6b35c097d6 | ||
|
|
619ba13265 | ||
|
|
529c5b8abf | ||
|
|
3a5ed6e800 | ||
|
|
52cddc015b | ||
|
|
4a01f4f65f | ||
|
|
f9768cb5a3 | ||
|
|
221e0e550c | ||
|
|
d2d1d42d0f | ||
|
|
faf018a097 | ||
|
|
a2a71a107e | ||
|
|
fc9c937e67 | ||
|
|
b4f2e9b442 | ||
|
|
1672645e73 | ||
|
|
4a42c44101 | ||
|
|
383b1a5769 | ||
|
|
77bac4cf9e | ||
|
|
e2b8e530c9 | ||
|
|
e9f752bd67 | ||
|
|
4b31921eb4 | ||
|
|
3df9fc6225 | ||
|
|
b57fe466ce | ||
|
|
bd4bff3b6b | ||
|
|
9d4618a223 | ||
|
|
93636180df | ||
|
|
fcceaa168f | ||
|
|
2639cc6138 | ||
|
|
4a99c2e928 | ||
|
|
7d5af3df05 | ||
|
|
c88b80d2a0 | ||
|
|
819d4abaa2 | ||
|
|
20630aeb47 | ||
|
|
0c0db3babb | ||
|
|
e7761f7e57 | ||
|
|
064fd497ae | ||
|
|
49c60b6b75 | ||
|
|
ca7f36506c | ||
|
|
155f0a9736 | ||
|
|
25e1eb3ce9 | ||
|
|
f2f980928b | ||
|
|
1d121a97a7 | ||
|
|
211d13da09 | ||
|
|
11343d469e | ||
|
|
d7c8041aa1 | ||
|
|
9587e30af8 | ||
|
|
76fa7affaf | ||
|
|
2971dd8672 | ||
|
|
2a33fe3564 | ||
|
|
46cdf5da70 | ||
|
|
28c801bfd4 | ||
|
|
c22cd40293 | ||
|
|
56bd430983 | ||
|
|
d873890e46 | ||
|
|
d29b8eca3c | ||
|
|
6f258000fe | ||
|
|
255211cd07 | ||
|
|
f6d28a90e3 | ||
|
|
ed66ff88a1 | ||
|
|
82e58f2bf9 | ||
|
|
797a87ca26 | ||
|
|
ec6a709393 | ||
|
|
07cbfdb424 | ||
|
|
3b9bd944fb | ||
|
|
934e585cb3 | ||
|
|
3a68f4cf54 | ||
|
|
bd00fcb875 | ||
|
|
905dd5a70f | ||
|
|
c65250ec39 | ||
|
|
607eec6ff0 | ||
|
|
14fb3bde60 | ||
|
|
6782bc8ca2 | ||
|
|
3db6841305 | ||
|
|
f478fa8029 | ||
|
|
d255f8400f | ||
|
|
a1545c60d6 | ||
|
|
ed48603ab5 | ||
|
|
23a0507439 | ||
|
|
482e013887 | ||
|
|
265727c30f | ||
|
|
4d3f4e096b | ||
|
|
7629bca62d | ||
|
|
2712f17262 | ||
|
|
86a37559ba | ||
|
|
b504a557f4 | ||
|
|
e849b46f6b | ||
|
|
738dc50a6f | ||
|
|
3138523b5b | ||
|
|
537643a4c3 | ||
|
|
04bfe098ed | ||
|
|
c507887bdd | ||
|
|
ee261313ac | ||
|
|
c9c152bc8a | ||
|
|
6c8e19a321 | ||
|
|
218e3b66f2 | ||
|
|
1d3488fa8e | ||
|
|
f4c1682592 | ||
|
|
28ac6623c7 | ||
|
|
16ab179e1d | ||
|
|
a8ff5385dc | ||
|
|
9dc33c6086 | ||
|
|
b17c576705 | ||
|
|
96f8f2891b | ||
|
|
581d73afe0 | ||
|
|
1baefebe8f | ||
|
|
39fb05033f | ||
|
|
c6093c084c | ||
|
|
dfec6d9a6d | ||
|
|
08b1261c75 | ||
|
|
2ad6faae3a | ||
|
|
4eff301db3 | ||
|
|
447e43e8f4 | ||
|
|
7457001275 | ||
|
|
fcabd5e79e | ||
|
|
594002316c | ||
|
|
eccf92ebaf | ||
|
|
ad9ddc5621 | ||
|
|
1825dd916e | ||
|
|
dfcde8171e | ||
|
|
b0361183df | ||
|
|
71fe13b249 | ||
|
|
442f51224d | ||
|
|
974678f500 | ||
|
|
8329409c03 | ||
|
|
06c2ac2724 | ||
|
|
04e9e8f9d8 | ||
|
|
7a3330cb8c | ||
|
|
cae29941ea | ||
|
|
15cf2ad076 | ||
|
|
2f16f6dc23 | ||
|
|
528aebffe4 | ||
|
|
e82b2f0cbe | ||
|
|
73e64f3e4a | ||
|
|
15f5b1f830 | ||
|
|
1b0a77f9a8 | ||
|
|
0f82ae3644 | ||
|
|
de3b01b54b | ||
|
|
c17e3646d5 | ||
|
|
26aed3e89e | ||
|
|
74caea8f8f | ||
|
|
2cf07fa072 | ||
|
|
1181cd2fd7 | ||
|
|
850d55ab45 | ||
|
|
a0c91b8754 | ||
|
|
937bdc05c8 | ||
|
|
453755bfa1 | ||
|
|
400b6fbb61 | ||
|
|
8c4e882fa3 | ||
|
|
84eec23793 | ||
|
|
7dfe69f6a5 | ||
|
|
ada6115073 | ||
|
|
e1643566f9 | ||
|
|
053a9a6317 | ||
|
|
425b976cc0 | ||
|
|
5f5f1b1e09 | ||
|
|
e6f4935c7b | ||
|
|
6452e5976b | ||
|
|
2383dff317 | ||
|
|
de3e5042fb | ||
|
|
0dcc35152c | ||
|
|
8eecfcbfaf | ||
|
|
efa3e60f89 | ||
|
|
782df659bc | ||
|
|
0aa158824f | ||
|
|
da7fb44e5d | ||
|
|
4b59ef802e | ||
|
|
be5789cd56 | ||
|
|
9adf0e5d59 | ||
|
|
e2de22470e | ||
|
|
3b7ab2e553 | ||
|
|
8617dedc46 | ||
|
|
0b8f1a9a58 | ||
|
|
16748c0920 | ||
|
|
01ec585a44 | ||
|
|
b5f2295f37 | ||
|
|
d6ca0199b7 | ||
|
|
2257c5e547 | ||
|
|
b5a3d39799 | ||
|
|
a26c3e9d3c | ||
|
|
98a09532eb | ||
|
|
d736789bbc | ||
|
|
82a6cfc03a | ||
|
|
62e9c7c75a | ||
|
|
eb32bd45e7 | ||
|
|
4b95f07923 | ||
|
|
dea8ad4c49 | ||
|
|
96553b217c | ||
|
|
3f79ed5d91 | ||
|
|
1e4283aad3 | ||
|
|
1dda31a28c | ||
|
|
10c87012be | ||
|
|
bda00bf512 | ||
|
|
c8f871ff2a | ||
|
|
58dc0b1aef | ||
|
|
4cd4d8f31a | ||
|
|
b751fd738d | ||
|
|
f97c6fb94c | ||
|
|
219138ade6 | ||
|
|
9086d189b9 | ||
|
|
d1178defe0 | ||
|
|
691a561a95 | ||
|
|
aaaac93bd0 | ||
|
|
fd790566b2 | ||
|
|
db3b429784 | ||
|
|
40ed3278d4 | ||
|
|
d174b13111 | ||
|
|
1708663b32 | ||
|
|
6fdce4ad0d | ||
|
|
fff8d5f07d | ||
|
|
9c8e1f4706 | ||
|
|
0a1036c78f | ||
|
|
0e881a7972 | ||
|
|
839e52ba30 | ||
|
|
8f7d5dcb4d | ||
|
|
1104b28bc1 | ||
|
|
48521cb1e4 | ||
|
|
17e113dafb | ||
|
|
c33825a904 | ||
|
|
b07ef98c8f | ||
|
|
b3d68893df | ||
|
|
1329599987 | ||
|
|
2adf3f364c | ||
|
|
436ee34a02 | ||
|
|
4a6e17b214 | ||
|
|
6e9cbccde6 | ||
|
|
a0cb8ec124 | ||
|
|
21217dfda3 | ||
|
|
25ba18e570 | ||
|
|
a210377f35 | ||
|
|
07b9ca457f | ||
|
|
5f1372d39c | ||
|
|
01b84c79f0 | ||
|
|
4017443b1e | ||
|
|
fd2a17d244 | ||
|
|
126804f7c3 | ||
|
|
5167bbf59e | ||
|
|
8bcdfa2793 | ||
|
|
2f9cb6a91e | ||
|
|
662be14535 | ||
|
|
d6d065cd61 | ||
|
|
ac7f045708 | ||
|
|
ffe02ad7bf | ||
|
|
db1a87d10c | ||
|
|
4bae41ffd8 | ||
|
|
be36fb979f | ||
|
|
0f66d763e0 | ||
|
|
06f4743f51 | ||
|
|
9cc11b8774 | ||
|
|
de821e55ae | ||
|
|
463b5c6e49 | ||
|
|
65ab5fdb34 | ||
|
|
d2f7a035b3 | ||
|
|
bc0b924283 | ||
|
|
56ad6af5b2 | ||
|
|
c50bb3a5a9 | ||
|
|
d993a62263 | ||
|
|
82bc52b909 | ||
|
|
f31598f916 | ||
|
|
6a9efd8ac6 | ||
|
|
a9dddb6066 | ||
|
|
40cf5c99ef | ||
|
|
42f58cbbb3 | ||
|
|
fd9c780015 | ||
|
|
383b92b207 | ||
|
|
7036ed5e2f | ||
|
|
30666aa111 | ||
|
|
9614d68baa | ||
|
|
c25fb4c743 | ||
|
|
09d5222b1f | ||
|
|
426ca78bf7 | ||
|
|
a77a0945fe | ||
|
|
5311a0f903 | ||
|
|
d421656be8 | ||
|
|
04459eaa50 | ||
|
|
3beda8eea0 | ||
|
|
5e894be06b | ||
|
|
bc8f93b596 | ||
|
|
2fb93bac99 | ||
|
|
d0c94c1aef | ||
|
|
77242bfb95 | ||
|
|
5d2d86bffc | ||
|
|
8492c13e72 | ||
|
|
e4eb5dadda | ||
|
|
8532dc4b75 | ||
|
|
1ca26ce676 | ||
|
|
d8e3e823a7 | ||
|
|
473dd7660b | ||
|
|
5afeed56ef | ||
|
|
b91b04f652 | ||
|
|
25de44a23d | ||
|
|
00cfb95971 | ||
|
|
f4ba0e1191 | ||
|
|
6499643769 | ||
|
|
f85287a444 | ||
|
|
483bc9ad87 | ||
|
|
93b89a93c1 | ||
|
|
10064c046c | ||
|
|
a5aecb9d0e | ||
|
|
de1e889f1d | ||
|
|
16f89b40c3 | ||
|
|
0e387d2cda | ||
|
|
837c15e4f9 | ||
|
|
ae7e353169 | ||
|
|
6c1bbd2344 | ||
|
|
27247e8e56 | ||
|
|
08249d78ea | ||
|
|
827091e522 | ||
|
|
13d901bf8d | ||
|
|
e69bdabc99 | ||
|
|
e8d19265e4 | ||
|
|
49e3a49dc5 | ||
|
|
82a7c01898 | ||
|
|
c0d7dbf639 | ||
|
|
569caa0bf2 | ||
|
|
f88ea1ee7d | ||
|
|
d5a8fa0b97 | ||
|
|
3f8f96edea | ||
|
|
04fb4aff28 | ||
|
|
83c6fb089e | ||
|
|
9d8d17b964 | ||
|
|
39d4842ff5 | ||
|
|
cad8473986 | ||
|
|
5f085ccb52 | ||
|
|
b406246689 | ||
|
|
cbe46afdff | ||
|
|
a59d6dc3c7 | ||
|
|
2afb2dd5fd | ||
|
|
4fc3c969d3 | ||
|
|
1796ce324b | ||
|
|
5e04c7f827 | ||
|
|
20fcede440 | ||
|
|
012c1833f2 | ||
|
|
32e8e03256 | ||
|
|
dca653cb92 | ||
|
|
0805eca979 | ||
|
|
17935a78ff | ||
|
|
e16918ee32 | ||
|
|
78471b4595 | ||
|
|
c30bcdd515 | ||
|
|
ac78c5f4e5 | ||
|
|
57a990ce25 | ||
|
|
24825b42a2 | ||
|
|
4f7323f7fc | ||
|
|
a228be85e2 | ||
|
|
fa565bdbdf | ||
|
|
2dc53223e5 | ||
|
|
958ac72805 | ||
|
|
f7297b84e7 | ||
|
|
9a7d9e7bb8 | ||
|
|
fa9df75cf7 | ||
|
|
e3ec76418b | ||
|
|
102d6d8c84 | ||
|
|
a742b5f3e2 | ||
|
|
a2a3bb291f | ||
|
|
b7c0ac7d67 | ||
|
|
13b1fc6b44 | ||
|
|
3939fcf6e7 | ||
|
|
13abbb81af | ||
|
|
019f0153c8 | ||
|
|
8abc2925e0 | ||
|
|
996c9a032a | ||
|
|
22d3794d22 | ||
|
|
ba948a38e9 | ||
|
|
e8a522c4df | ||
|
|
c60f3da32e | ||
|
|
0c92d3cbb2 | ||
|
|
e4fc8dd6fe | ||
|
|
1a849e2de0 | ||
|
|
ffdd79f86b | ||
|
|
e87e46b1b6 | ||
|
|
3ca81a4ff7 | ||
|
|
5477d3c292 | ||
|
|
08300183b3 | ||
|
|
095c77f22c | ||
|
|
09926e63a3 | ||
|
|
87d70f29a1 | ||
|
|
3a7661b111 | ||
|
|
ec976953cd | ||
|
|
1837562b50 | ||
|
|
f3bec4fc37 | ||
|
|
c2117ef4fd | ||
|
|
910804ecd1 | ||
|
|
ce5ae1dfdd | ||
|
|
2c31411ffb | ||
|
|
84d69fa2a1 | ||
|
|
2aea296d19 | ||
|
|
2b0bffc362 | ||
|
|
83356142c1 | ||
|
|
24dcc6947c | ||
|
|
a7e3136a0b | ||
|
|
71639cfea7 | ||
|
|
8c2d39fb82 | ||
|
|
e060d29337 | ||
|
|
79e9156d2f | ||
|
|
9100db55b0 | ||
|
|
141c10f6fe | ||
|
|
4613ab9dc3 | ||
|
|
061ad41b51 | ||
|
|
3a0007cd18 | ||
|
|
0044917943 | ||
|
|
0337c04278 | ||
|
|
4585acf70b | ||
|
|
2ad9bbae25 | ||
|
|
cf075df7d1 | ||
|
|
11cd9905c4 | ||
|
|
cf462542e9 | ||
|
|
b63f25a1ae | ||
|
|
7de69a21c5 | ||
|
|
21783e4ea0 | ||
|
|
53e5a756d7 | ||
|
|
8c911a2fd0 | ||
|
|
ce440e9f43 | ||
|
|
6465f8d8e6 | ||
|
|
4bdf28059a | ||
|
|
21010c6540 | ||
|
|
a5a6cabac6 | ||
|
|
f460c77f2c | ||
|
|
1c69d9213e | ||
|
|
c02c2d3b2c | ||
|
|
7adf5e763b | ||
|
|
0e4afefc7f | ||
|
|
c7f290f42e | ||
|
|
bb553b8a6a | ||
|
|
21eda2a1a3 | ||
|
|
48c13c990f | ||
|
|
a2665529f6 | ||
|
|
8d35d78eff | ||
|
|
a82a364c22 | ||
|
|
cc150ff9d2 | ||
|
|
feeb38293d | ||
|
|
5b9271ccfe | ||
|
|
e60bbc2fb7 | ||
|
|
387cc184e6 | ||
|
|
a830ddcb43 | ||
|
|
35fea30191 | ||
|
|
24b672b968 | ||
|
|
de6a3c5ab1 | ||
|
|
260ff6de3e | ||
|
|
7cb37411c9 | ||
|
|
e4e41e5ef8 | ||
|
|
985f4aafca | ||
|
|
0c25dd44b3 | ||
|
|
285f0bc6dd | ||
|
|
07a370fd24 | ||
|
|
95f07ea38a | ||
|
|
2890b92b21 | ||
|
|
8b80c5d0b5 | ||
|
|
04425786a1 | ||
|
|
15b14e12e2 | ||
|
|
b328972c4d | ||
|
|
da3156047f | ||
|
|
f9f08ba54f | ||
|
|
b43684262f | ||
|
|
2120f78bd7 | ||
|
|
2d896f22d6 | ||
|
|
9fa0aebfe9 | ||
|
|
2ddc3af5ff | ||
|
|
fd80e096ea | ||
|
|
fab2d69fce | ||
|
|
83d08e3aba | ||
|
|
bfea6bcacf | ||
|
|
feff34b021 | ||
|
|
79fbade92a | ||
|
|
bf508e453e | ||
|
|
47b51c22fa | ||
|
|
ebd16105f2 | ||
|
|
01fb1a5775 | ||
|
|
b8c2a05db9 | ||
|
|
4087dc5fe4 | ||
|
|
408029e6e0 | ||
|
|
23ff403529 | ||
|
|
be4f81f584 | ||
|
|
361c91e610 | ||
|
|
2aa2ea9675 | ||
|
|
e084225edf | ||
|
|
9ce342205b | ||
|
|
0edf50e00e | ||
|
|
1ea19daad9 | ||
|
|
32b302314e | ||
|
|
ee197e02a2 | ||
|
|
7cd6ffec2a | ||
|
|
0077580838 | ||
|
|
4d85a79fd1 | ||
|
|
a35139bb61 | ||
|
|
f72b833724 | ||
|
|
0e16bac6e2 | ||
|
|
e17564b362 | ||
|
|
90b66eddf5 | ||
|
|
2862a5849f | ||
|
|
7e839231ed | ||
|
|
fa56a4bb73 | ||
|
|
dff950748c | ||
|
|
b7374e3f8e | ||
|
|
4244b92b08 | ||
|
|
4f688028ad | ||
|
|
5a9a18501d | ||
|
|
896b8f7cf1 | ||
|
|
95bd1b014f | ||
|
|
dbdf8642bb | ||
|
|
c3cd9007d2 | ||
|
|
8079fb5bc5 | ||
|
|
80d0b5d4ed | ||
|
|
86bd847bf9 | ||
|
|
943004844a | ||
|
|
4ff12e0426 | ||
|
|
0d7bdb6fa8 | ||
|
|
6d488b6a81 | ||
|
|
f1d0263ffa | ||
|
|
24035caadb | ||
|
|
ed89a3e0f8 | ||
|
|
7088ab89f1 | ||
|
|
d4688bd76b | ||
|
|
befe0fccaf | ||
|
|
a192410498 | ||
|
|
d43ede3a11 | ||
|
|
9848ffb77f | ||
|
|
7487497d1f | ||
|
|
be11c848f4 | ||
|
|
9836b274b9 | ||
|
|
a96d14566f | ||
|
|
1c8cd8c168 | ||
|
|
5f5806a98e | ||
|
|
624b045ac0 | ||
|
|
0f8bae950e | ||
|
|
fcede42903 |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
* text=auto
|
||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
*.custom.*
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
dist/
|
*.custom.*
|
||||||
node_modules/
|
node_modules/
|
||||||
|
vendor/closure-compiler/
|
||||||
|
vendor/uglifyjs/
|
||||||
|
|||||||
12
.jamignore
Normal file
12
.jamignore
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
.*
|
||||||
|
*.custom.*
|
||||||
|
*.md
|
||||||
|
*.txt
|
||||||
|
build.js
|
||||||
|
index.js
|
||||||
|
build/
|
||||||
|
doc/
|
||||||
|
node_modules/
|
||||||
|
perf/
|
||||||
|
test/
|
||||||
|
vendor/
|
||||||
21
.npmignore
21
.npmignore
@@ -1,17 +1,26 @@
|
|||||||
*.custom.*
|
|
||||||
*.min.*
|
|
||||||
.*
|
.*
|
||||||
dist/
|
*.custom.*
|
||||||
|
*.d.ts
|
||||||
|
CONTRIBUTING.md
|
||||||
doc/*.php
|
doc/*.php
|
||||||
node_modules/
|
node_modules/
|
||||||
perf/*.html
|
perf/*.html
|
||||||
|
perf/*-ui.js
|
||||||
perf/*.sh
|
perf/*.sh
|
||||||
test/*.html
|
test/*.html
|
||||||
test/*-ui.js
|
test/*-ui.js
|
||||||
test/*.sh
|
test/*.sh
|
||||||
|
vendor/*.gz
|
||||||
vendor/backbone/
|
vendor/backbone/
|
||||||
|
vendor/benchmark.js/*.jar
|
||||||
|
vendor/closure-compiler/
|
||||||
vendor/docdown/
|
vendor/docdown/
|
||||||
vendor/qunit/qunit/*.css
|
|
||||||
vendor/underscore/
|
|
||||||
vendor/requirejs/
|
|
||||||
vendor/firebug-lite/
|
vendor/firebug-lite/
|
||||||
|
vendor/json3/
|
||||||
|
vendor/jquery/
|
||||||
|
vendor/qunit/qunit/*.css
|
||||||
|
vendor/qunit/qunit/*-1.8.0.js
|
||||||
|
vendor/requirejs/
|
||||||
|
vendor/underscore/*-min.js
|
||||||
|
vendor/uglifyjs/
|
||||||
|
vendor/underscore/test/
|
||||||
|
|||||||
20
.travis.yml
Normal file
20
.travis.yml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
language: node_js
|
||||||
|
node_js:
|
||||||
|
- 0.6
|
||||||
|
- 0.9
|
||||||
|
env:
|
||||||
|
- TEST_COMMAND="phantomjs ./test/test.js ../dist/lodash.compat.js"
|
||||||
|
- TEST_COMMAND="phantomjs ./test/test.js ../dist/lodash.compat.min.js"
|
||||||
|
- TEST_COMMAND="node ./test/test.js ../dist/lodash.js"
|
||||||
|
- TEST_COMMAND="node ./test/test.js ../dist/lodash.min.js"
|
||||||
|
- TEST_COMMAND="node ./test/test-build.js --time-limit 49m40s"
|
||||||
|
git:
|
||||||
|
depth: 1
|
||||||
|
branches:
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
before_script:
|
||||||
|
- "tar -xzvf vendor/closure-compiler.tar.gz -C vendor"
|
||||||
|
- "tar -xzvf vendor/uglifyjs.tar.gz -C vendor"
|
||||||
|
script:
|
||||||
|
$TEST_COMMAND
|
||||||
35
CONTRIBUTING.md
Normal file
35
CONTRIBUTING.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Contributing to Lo-Dash
|
||||||
|
|
||||||
|
If you’d like to contribute a feature or bug fix, you can [fork](https://help.github.com/articles/fork-a-repo) Lo-Dash, commit your changes, and [send a pull request](https://help.github.com/articles/using-pull-requests).
|
||||||
|
Please make sure to [search the issue tracker](https://github.com/bestiejs/lodash/issues) first; your issue may have already been discussed or fixed in `master`.
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
Include updated unit tests in the `test` directory as part of your pull request.
|
||||||
|
You can run the tests from the command line via `npm test`, or open `test/index.html` in a web browser.
|
||||||
|
The `test/run-test.sh` script attempts to run the tests in [Rhino](https://developer.mozilla.org/en-US/docs/Rhino), [Narwhal](https://github.com/280north/narwhal), [RingoJS](http://ringojs.org/), [PhantomJS](http://phantomjs.org/), and [Node](http://nodejs.org/), before running them in your default browser.
|
||||||
|
The [Backbone](http://backbonejs.org/) and [Underscore](http://http://underscorejs.org/) test suites are included as well.
|
||||||
|
|
||||||
|
## Contributor License Agreement
|
||||||
|
|
||||||
|
Lo-Dash is a member of the [Dojo Foundation](http://dojofoundation.org/).
|
||||||
|
As such, we request that all contributors sign the Dojo Foundation [contributor license agreement](http://dojofoundation.org/about/claForm).
|
||||||
|
|
||||||
|
For more information about CLAs, please check out Alex Russell’s excellent post, ["Why Do I Need to Sign This?"](http://infrequently.org/2008/06/why-do-i-need-to-sign-this/).
|
||||||
|
|
||||||
|
## Coding Guidelines
|
||||||
|
|
||||||
|
In addition to the following guidelines, please follow the conventions already established in the code.
|
||||||
|
|
||||||
|
- **Spacing**:<br>
|
||||||
|
Use two spaces for indentation. No tabs.
|
||||||
|
|
||||||
|
- **Naming**:<br>
|
||||||
|
Keep variable and method names concise and descriptive.<br>
|
||||||
|
Variable names `index`, `collection`, and `callback` are preferable to `i`, `arr`, and `fn`.
|
||||||
|
|
||||||
|
- **Quotes**:<br>
|
||||||
|
Single-quoted strings are preferred to double-quoted strings; however, please use a double-quoted string if the value contains a single-quote character to avoid unnecessary escaping.
|
||||||
|
|
||||||
|
- **Comments**:<br>
|
||||||
|
Please use single-line comments to annotate significant additions, and [JSDoc-style](http://www.2ality.com/2011/08/jsdoc-intro.html) comments for new methods.
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
Copyright 2012 John-David Dalton <http://allyoucanleet.com/>
|
Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
|
||||||
Based on Underscore.js 1.3.3, copyright 2009-2012 Jeremy Ashkenas,
|
Based on Underscore.js 1.4.3, copyright 2009-2013 Jeremy Ashkenas,
|
||||||
DocumentCloud Inc. <http://documentcloud.github.com/underscore>
|
DocumentCloud Inc. <http://underscorejs.org/>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
|
|||||||
315
README.md
315
README.md
@@ -1,144 +1,80 @@
|
|||||||
# Lo-Dash <sup>v0.4.2</sup>
|
# Lo-Dash v1.0.2
|
||||||
|
|
||||||
A drop-in replacement<sup>[*](https://github.com/bestiejs/lodash/wiki/Drop-in-Disclaimer)</sup> for Underscore.js, from the devs behind [jsPerf.com](http://jsperf.com), that delivers [performance improvements](http://lodash.com/benchmarks), [bug fixes](https://github.com/bestiejs/lodash#closed-underscorejs-issues), and [additional features](https://github.com/bestiejs/lodash#features).
|
A utility library delivering consistency, [customization](https://lodash.com/custom-builds), [performance](https://lodash.com/benchmarks), & [extras](https://lodash.com/#features).
|
||||||
|
|
||||||
Lo-Dash’s 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.
|
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
|
|
||||||
* [Development source](https://raw.github.com/bestiejs/lodash/v0.4.2/lodash.js)
|
* Lo-Dash builds (for modern environments):<br>
|
||||||
* [Production source](https://raw.github.com/bestiejs/lodash/v0.4.2/lodash.min.js)
|
[Development](https://raw.github.com/lodash/lodash/1.0.2/dist/lodash.js) and
|
||||||
* CDN copies of ≤ [v0.4.1](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.4.1/lodash.min.js) are available on [cdnjs](http://cdnjs.com/) thanks to [CloudFlare](http://www.cloudflare.com/)
|
[Production](https://raw.github.com/lodash/lodash/1.0.2/dist/lodash.min.js)
|
||||||
* For optimal performance, [create a custom build](https://github.com/bestiejs/lodash#custom-builds) with only the features you need
|
|
||||||
|
* Lo-Dash compatibility builds (for legacy and modern environments):<br>
|
||||||
|
[Development](https://raw.github.com/lodash/lodash/1.0.2/dist/lodash.compat.js) and
|
||||||
|
[Production](https://raw.github.com/lodash/lodash/1.0.2/dist/lodash.compat.min.js)
|
||||||
|
|
||||||
|
* Underscore compatibility builds:<br>
|
||||||
|
[Development](https://raw.github.com/lodash/lodash/1.0.2/dist/lodash.underscore.js) and
|
||||||
|
[Production](https://raw.github.com/lodash/lodash/1.0.2/dist/lodash.underscore.min.js)
|
||||||
|
|
||||||
|
* For optimal file size, [create a custom build](https://lodash.com/custom-builds) with only the features you need
|
||||||
|
|
||||||
## Dive in
|
## Dive in
|
||||||
|
|
||||||
We’ve got [API docs](http://lodash.com/docs), [benchmarks](http://lodash.com/benchmarks), and [unit tests](http://lodash.com/tests).
|
We’ve got [API docs](https://lodash.com/docs), [benchmarks](https://lodash.com/benchmarks), and [unit tests](https://lodash.com/tests).
|
||||||
|
|
||||||
Create your own benchmarks at [jsPerf](http://jsperf.com), or [search](http://jsperf.com/search?q=lodash) for existing ones.
|
For a list of upcoming features, check out our [roadmap](https://github.com/lodash/lodash/wiki/Roadmap).
|
||||||
|
|
||||||
For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/lodash/wiki/Roadmap).
|
The full changelog is available [here](https://github.com/lodash/lodash/wiki/Changelog).
|
||||||
|
|
||||||
## Screencasts
|
|
||||||
|
|
||||||
For more information check out these screencasts over Lo-Dash:
|
|
||||||
|
|
||||||
* [Introducing Lo-Dash](https://vimeo.com/44154599)
|
|
||||||
* [Optimizations and custom builds](https://vimeo.com/44154601)
|
|
||||||
* [Lo-Dash’s origin and why it’s a better utility belt](https://vimeo.com/44154600)
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
* AMD loader support ([RequireJS](http://requirejs.org/), [curl.js](https://github.com/cujojs/curl), etc.)
|
|
||||||
* [_.bind](http://lodash.com/docs#bind) supports *"lazy"* binding
|
|
||||||
* [_.debounce](http://lodash.com/docs#debounce)’ed functions match [_.throttle](http://lodash.com/docs#throttle)’ed functions’ return value behavior
|
|
||||||
* [_.forEach](http://lodash.com/docs#forEach) is chainable
|
|
||||||
* [_.forIn](http://lodash.com/docs#forIn) for iterating over an object’s own and inherited properties
|
|
||||||
* [_.forOwn](http://lodash.com/docs#forOwn) for iterating over an object’s own properties
|
|
||||||
* [_.groupBy](http://lodash.com/docs#groupBy), [_.sortedIndex](http://lodash.com/docs#sortedIndex), and [_.uniq](http://lodash.com/docs#uniq) accept a `thisArg` argument
|
|
||||||
* [_.indexOf](http://lodash.com/docs#indexOf) and [_.lastIndexOf](http://lodash.com/docs#lastIndexOf) accept a `fromIndex` argument
|
|
||||||
* [_.partial](http://lodash.com/docs#partial) for more functional fun
|
|
||||||
* [_.template](http://lodash.com/docs#template) utilizes [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) for easier debugging
|
|
||||||
* [_.contains](http://lodash.com/docs#contains), [_.size](http://lodash.com/docs#size), [_.toArray](http://lodash.com/docs#toArray),
|
|
||||||
[and more…](http://lodash.com/docs "_.every, _.filter, _.find, _.forEach, _.groupBy, _.invoke, _.map, _.pluck, _.reduce, _.reduceRight, _.reject, _.some, _sortBy") accept strings
|
|
||||||
|
|
||||||
## Support
|
|
||||||
|
|
||||||
Lo-Dash has been tested in at least Chrome 5-20, Firefox 1.5-13, IE 6-9, Opera 9.25-12, Safari 3.0.4-5.1.7, Node.js 0.4.8-0.8.2, 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.
|
|
||||||
|
|
||||||
* Backbone builds, containing all methods required by Backbone, may be created using the `backbone` modifier argument.
|
|
||||||
~~~ bash
|
|
||||||
lodash backbone
|
|
||||||
~~~
|
|
||||||
|
|
||||||
* Legacy builds, tailored for older browsers without [ES5 support](http://es5.github.com/), may be created using the `legacy` modifier argument.
|
|
||||||
~~~ bash
|
|
||||||
lodash legacy
|
|
||||||
~~~
|
|
||||||
|
|
||||||
* Mobile builds, with IE < 9 bug fixes and method compilation removed, may be created using the `mobile` modifier argument.
|
|
||||||
~~~ bash
|
|
||||||
lodash mobile
|
|
||||||
~~~
|
|
||||||
|
|
||||||
* Strict builds, with `_.bindAll`, `_.extend`, and `_.defaults` in [strict mode](http://es5.github.com/#C), may be created using the `strict` modifier argument.
|
|
||||||
~~~ bash
|
|
||||||
lodash strict
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Custom builds may be created in three ways:
|
|
||||||
|
|
||||||
1. Use the `category` argument to pass the categories of methods to include in the build.<br>
|
|
||||||
Valid categories are *"arrays"*, *"chaining"*, *"collections"*, *"functions"*, *"objects"*, and *"utilities"*.
|
|
||||||
~~~ bash
|
|
||||||
lodash category=collections,functions
|
|
||||||
lodash category="collections, functions"
|
|
||||||
~~~
|
|
||||||
|
|
||||||
2. Use the `exclude` argument to pass the names of methods to exclude from the build.
|
|
||||||
~~~ bash
|
|
||||||
lodash exclude=union,uniq,zip
|
|
||||||
lodash exclude="union, uniq, zip"
|
|
||||||
~~~
|
|
||||||
|
|
||||||
3. Use the `include` argument to pass the names of methods to include in the build.
|
|
||||||
~~~ bash
|
|
||||||
lodash include=each,filter,map
|
|
||||||
lodash include="each, filter, map"
|
|
||||||
~~~
|
|
||||||
|
|
||||||
All arguments, except `exclude` with `include` and `legacy` with `mobile`, may be combined.
|
|
||||||
|
|
||||||
~~~ bash
|
|
||||||
lodash backbone legacy category=utilities exclude=first,last
|
|
||||||
lodash backbone mobile strict category=functions include=pick,uniq
|
|
||||||
~~~
|
|
||||||
|
|
||||||
The `lodash` command-line utility is available when Lo-Dash is installed as a global package (i.e. `npm install -g lodash`).
|
|
||||||
|
|
||||||
Custom builds are saved to `lodash.custom.js` and `lodash.custom.min.js`.
|
|
||||||
|
|
||||||
## Installation and usage
|
## Installation and usage
|
||||||
|
|
||||||
In browsers:
|
In browsers:
|
||||||
|
|
||||||
~~~ html
|
```html
|
||||||
<script src="lodash.js"></script>
|
<script src="lodash.js"></script>
|
||||||
~~~
|
```
|
||||||
|
|
||||||
Using [npm](http://npmjs.org/):
|
Using [`npm`](http://npmjs.org/):
|
||||||
|
|
||||||
~~~ bash
|
```bash
|
||||||
npm install lodash
|
npm install lodash
|
||||||
|
|
||||||
npm install -g lodash
|
npm install -g lodash
|
||||||
~~~
|
npm link lodash
|
||||||
|
```
|
||||||
|
|
||||||
|
To avoid potential issues, update `npm` before installing Lo-Dash:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install npm -g
|
||||||
|
```
|
||||||
|
|
||||||
In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
|
In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
~~~
|
|
||||||
|
|
||||||
In [Narwhal](http://narwhaljs.org/) and [RingoJS v0.7.0-](http://ringojs.org/):
|
// or as a drop-in replacement for Underscore
|
||||||
|
var _ = require('lodash/lodash.underscore');
|
||||||
|
```
|
||||||
|
|
||||||
~~~ js
|
**Note:** If Lo-Dash is installed globally, run [`npm link lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your project’s root directory before requiring it.
|
||||||
|
|
||||||
|
In [RingoJS v0.7.0-](http://ringojs.org/):
|
||||||
|
|
||||||
|
```js
|
||||||
var _ = require('lodash')._;
|
var _ = require('lodash')._;
|
||||||
~~~
|
```
|
||||||
|
|
||||||
In [Rhino](http://www.mozilla.org/rhino/):
|
In [Rhino](http://www.mozilla.org/rhino/):
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
load('lodash.js');
|
load('lodash.js');
|
||||||
~~~
|
```
|
||||||
|
|
||||||
In an AMD loader like [RequireJS](http://requirejs.org/):
|
In an AMD loader like [RequireJS](http://requirejs.org/):
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
require({
|
require({
|
||||||
'paths': {
|
'paths': {
|
||||||
'underscore': 'path/to/lodash'
|
'underscore': 'path/to/lodash'
|
||||||
@@ -147,139 +83,46 @@ require({
|
|||||||
['underscore'], function(_) {
|
['underscore'], function(_) {
|
||||||
console.log(_.VERSION);
|
console.log(_.VERSION);
|
||||||
});
|
});
|
||||||
~~~
|
```
|
||||||
|
|
||||||
## Closed Underscore.js issues <sup>(20+)</sup>
|
## Resources
|
||||||
|
|
||||||
* Allow iteration of objects with a `length` property [[#148](https://github.com/documentcloud/underscore/issues/148), [#154](https://github.com/documentcloud/underscore/issues/154), [#252](https://github.com/documentcloud/underscore/issues/252), [#448](https://github.com/documentcloud/underscore/issues/448), [#659](https://github.com/documentcloud/underscore/issues/659), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L364-370)]
|
For more information check out these articles, screencasts, and other videos over Lo-Dash:
|
||||||
* Ensure array-like objects with invalid `length` properties are treated like regular objects [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L315-321), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L665-679), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L921-924)]
|
|
||||||
* Ensure *"Arrays"* methods allow falsey `array` arguments [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L989-1027)]
|
|
||||||
* Ensure *"Collections"* methods allow string `collection` arguments [[#247](https://github.com/documentcloud/underscore/issues/247), [#276](https://github.com/documentcloud/underscore/issues/276), [#561](https://github.com/documentcloud/underscore/pull/561), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L148-157), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L323-341), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L681-698), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L926-929)]
|
|
||||||
* Ensure templates compiled with errors are inspectable [[#666](https://github.com/documentcloud/underscore/issues/666), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L795-802)]
|
|
||||||
* Fix cross-browser object iteration bugs [[#376](https://github.com/documentcloud/underscore/issues/376), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L224-236), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L375-400), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L496-507), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L515-517), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L535-555), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L725-727)]
|
|
||||||
* 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/v0.4.2/test/test.js#L96-102)]
|
|
||||||
* Register as an AMD module, but still export to global [[#431](https://github.com/documentcloud/underscore/pull/431), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L80-94)]
|
|
||||||
* `_(…)` should return passed wrapper instances [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L114-117)]
|
|
||||||
* `_.contains` should work with strings [[#667](https://github.com/documentcloud/underscore/pull/667), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L148-157)]
|
|
||||||
* `_.escape` should return an empty string when passed `null` or `undefined` [[#407](https://github.com/documentcloud/underscore/issues/427), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L205-208)]
|
|
||||||
* `_.forEach` should be chainable [[#142](https://github.com/documentcloud/underscore/issues/142), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L310-313)]
|
|
||||||
* `_.groupBy` should add values to own, not inherited, properties [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L415-422)]
|
|
||||||
* `_isNaN(new Number(NaN))` should return `true` [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L525-527)]
|
|
||||||
* `_.reduceRight` should pass correct callback arguments when iterating objects [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L649-663)]
|
|
||||||
* `_.size` should return the `length` of string values [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L708-710)]
|
|
||||||
* `_.size` shouldn't error on falsey values [[#650](https://github.com/documentcloud/underscore/pull/650), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L712-719)]
|
|
||||||
* `_.size` should work with `arguments` objects cross-browser [[#653](https://github.com/documentcloud/underscore/issues/653), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L721-723)]
|
|
||||||
* `_.sortedIndex` should support arrays with high `length` values [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L765-774)]
|
|
||||||
* `_.template` should not augment the `options` object [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L789-793)]
|
|
||||||
* `_.throttle` should work when called in a loop [[#502](https://github.com/documentcloud/underscore/issues/502), [test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L872-882)]
|
|
||||||
* `_.zipObject` should accept less than two arguments [[test](https://github.com/bestiejs/lodash/blob/v0.4.2/test/test.js#L951-953)]
|
|
||||||
|
|
||||||
## Optimized methods <sup>(50+)</sup>
|
* Posts
|
||||||
|
- [Say “Hello” to Lo-Dash](http://kitcambridge.be/blog/say-hello-to-lo-dash/)
|
||||||
|
|
||||||
* `_.bind`
|
* Videos
|
||||||
* `_.bindAll`
|
- [Introducing Lo-Dash](https://vimeo.com/44154599)
|
||||||
* `_.clone`
|
- [Lo-Dash optimizations and custom builds](https://vimeo.com/44154601)
|
||||||
* `_.compact`
|
- [Lo-Dash’s origin and why it’s a better utility belt](https://vimeo.com/44154600)
|
||||||
* `_.contains`, `_.include`
|
- [Unit testing in Lo-Dash](https://vimeo.com/45865290)
|
||||||
* `_.defaults`
|
- [Lo-Dash’s approach to native method use](https://vimeo.com/48576012)
|
||||||
* `_.defer`
|
- [CascadiaJS: Lo-Dash for a better utility belt](http://www.youtube.com/watch?v=dpPy4f_SeEk)
|
||||||
* `_.difference`
|
|
||||||
* `_.each`
|
|
||||||
* `_.escape`
|
|
||||||
* `_.every`, `_.all`
|
|
||||||
* `_.extend`
|
|
||||||
* `_.filter`, `_.select`
|
|
||||||
* `_.find`, `_.detect`
|
|
||||||
* `_.flatten`
|
|
||||||
* `_.forEach`, `_.each`
|
|
||||||
* `_.functions`, `_.methods`
|
|
||||||
* `_.groupBy`
|
|
||||||
* `_.indexOf`
|
|
||||||
* `_.intersection`
|
|
||||||
* `_.invoke`
|
|
||||||
* `_.isArguments`
|
|
||||||
* `_.isDate`
|
|
||||||
* `_.isEmpty`
|
|
||||||
* `_.isEqual`
|
|
||||||
* `_.isFinite`
|
|
||||||
* `_.isFunction`
|
|
||||||
* `_.isObject`
|
|
||||||
* `_.isNumber`
|
|
||||||
* `_.isRegExp`
|
|
||||||
* `_.isString`
|
|
||||||
* `_.keys`
|
|
||||||
* `_.lastIndexOf`
|
|
||||||
* `_.map`, `_.collect`
|
|
||||||
* `_.max`
|
|
||||||
* `_.memoize`
|
|
||||||
* `_.min`
|
|
||||||
* `_.mixin`
|
|
||||||
* `_.pick`
|
|
||||||
* `_.pluck`
|
|
||||||
* `_.reduce`, `_.foldl`, `_.inject`
|
|
||||||
* `_.reject`
|
|
||||||
* `_.result`
|
|
||||||
* `_.shuffle`
|
|
||||||
* `_.some`, `_.any`
|
|
||||||
* `_.sortBy`
|
|
||||||
* `_.sortedIndex`
|
|
||||||
* `_.template`
|
|
||||||
* `_.throttle`
|
|
||||||
* `_.times`
|
|
||||||
* `_.toArray`
|
|
||||||
* `_.union`
|
|
||||||
* `_.uniq`, `_.unique`
|
|
||||||
* `_.values`
|
|
||||||
* `_.without`
|
|
||||||
* `_.wrap`
|
|
||||||
* `_.zip`
|
|
||||||
* plus all `_(…)` method wrappers
|
|
||||||
|
|
||||||
## Release Notes
|
## Features
|
||||||
|
|
||||||
### <sup>v0.4.2</sup>
|
* AMD loader support ([RequireJS](http://requirejs.org/), [curl.js](https://github.com/cujojs/curl), etc.)
|
||||||
|
* [_(…)](https://lodash.com/docs#_) supports intuitive chaining
|
||||||
|
* [_.at](https://lodash.com/docs#at) for cherry-picking collection values
|
||||||
|
* [_.bindKey](https://lodash.com/docs#bindKey) for binding [*“lazy”* defined](http://michaux.ca/articles/lazy-function-definition-pattern) methods
|
||||||
|
* [_.cloneDeep](https://lodash.com/docs#cloneDeep) for deep cloning arrays and objects
|
||||||
|
* [_.contains](https://lodash.com/docs#contains) accepts a `fromIndex` argument
|
||||||
|
* [_.forEach](https://lodash.com/docs#forEach) is chainable and supports exiting iteration early
|
||||||
|
* [_.forIn](https://lodash.com/docs#forIn) for iterating over an object’s own and inherited properties
|
||||||
|
* [_.forOwn](https://lodash.com/docs#forOwn) for iterating over an object’s own properties
|
||||||
|
* [_.isPlainObject](https://lodash.com/docs#isPlainObject) checks if values are created by the `Object` constructor
|
||||||
|
* [_.merge](https://lodash.com/docs#merge) for a deep [_.extend](https://lodash.com/docs#extend)
|
||||||
|
* [_.partial](https://lodash.com/docs#partial) and [_.partialRight](https://lodash.com/docs#partialRight) for partial application without `this` binding
|
||||||
|
* [_.template](https://lodash.com/docs#template) supports [*“imports”* options](https://lodash.com/docs#templateSettings_imports), [ES6 template delimiters](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6), and [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
|
||||||
|
* [_.where](https://lodash.com/docs#where) supports deep object comparisons
|
||||||
|
* [_.clone](https://lodash.com/docs#clone), [_.omit](https://lodash.com/docs#omit), [_.pick](https://lodash.com/docs#pick),
|
||||||
|
[and more…](https://lodash.com/docs "_.assign, _.cloneDeep, _.first, _.initial, _.isEqual, _.last, _.merge, _.rest") accept `callback` and `thisArg` arguments
|
||||||
|
* [_.contains](https://lodash.com/docs#contains), [_.size](https://lodash.com/docs#size), [_.toArray](https://lodash.com/docs#toArray),
|
||||||
|
[and more…](https://lodash.com/docs "_.at, _.countBy, _.every, _.filter, _.find, _.forEach, _.groupBy, _.invoke, _.map, _.max, _.min, _.pluck, _.reduce, _.reduceRight, _.reject, _.shuffle, _.some, _.sortBy, _.where") accept strings
|
||||||
|
* [_.filter](https://lodash.com/docs#filter), [_.find](https://lodash.com/docs#find), [_.map](https://lodash.com/docs#map),
|
||||||
|
[and more…](https://lodash.com/docs "_.countBy, _.every, _.first, _.groupBy, _.initial, _.last, _.max, _.min, _.reject, _.rest, _.some, _.sortBy, _.sortedIndex, _.uniq") support *“_.pluck”* and *“_.where”* `callback` shorthands
|
||||||
|
|
||||||
* Added `strict` build
|
## Support
|
||||||
* Ensured `_.bindAll`, `_.extend`, and `_.defaults` avoid strict mode errors when attempting to augment read-only properties
|
|
||||||
* Optimized the iteration of large arrays in `_.difference`, `_.intersection`, and `_.without`
|
|
||||||
* Fixed build bugs related to removing variables
|
|
||||||
|
|
||||||
### <sup>v0.4.1</sup>
|
Lo-Dash has been tested in at least Chrome 5~24, Firefox 1~18, IE 6-10, Opera 9.25-12, Safari 3-6, Node.js 0.4.8-0.8.20, Narwhal 0.3.2, PhantomJS 1.8.1, RingoJS 0.9, and Rhino 1.7RC5.
|
||||||
|
|
||||||
* Fixed `_.template` regression
|
|
||||||
* Optimized build process to detect and remove more unused variables
|
|
||||||
|
|
||||||
### <sup>v0.4.0</sup>
|
|
||||||
|
|
||||||
* Added `bin` and `scripts` entries to package.json
|
|
||||||
* Added `legacy` build option
|
|
||||||
* Added cross-browser support for passing strings to *"Collections"* methods
|
|
||||||
* Added `_.zipObject`
|
|
||||||
* Leveraged `_.indexOf`'s `fromIndex` in `_.difference` and `_.without`
|
|
||||||
* Optimized compiled templates
|
|
||||||
* Optimized inlining the `iteratorTemplate` for builds
|
|
||||||
* Optimized object iteration for *"Collections"* methods
|
|
||||||
* Optimized partially applied `_.bind` in V8
|
|
||||||
* Made compiled templates more debuggable
|
|
||||||
* Made `_.size` work with falsey values and consistent cross-browser with `arguments` objects
|
|
||||||
* Moved `_.groupBy` and `_.sortBy` back to the *"Collections"* category
|
|
||||||
* Removed `arguments` object from `_.range`
|
|
||||||
|
|
||||||
The full changelog is available [here](https://github.com/bestiejs/lodash/wiki/Changelog).
|
|
||||||
|
|
||||||
## 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
|
|
||||||
|
|
||||||
* [John-David Dalton](http://allyoucanleet.com/)
|
|
||||||
[](https://twitter.com/jdalton "Follow @jdalton on Twitter")
|
|
||||||
|
|
||||||
## Contributors
|
|
||||||
|
|
||||||
* [Kit Cambridge](http://kitcambridge.github.com/)
|
|
||||||
[](https://twitter.com/kitcambridge "Follow @kitcambridge on Twitter")
|
|
||||||
* [Mathias Bynens](http://mathiasbynens.be/)
|
|
||||||
[](https://twitter.com/mathias "Follow @mathias on Twitter")
|
|
||||||
|
|||||||
748
build/minify.js
748
build/minify.js
@@ -2,32 +2,62 @@
|
|||||||
;(function() {
|
;(function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/** The Node filesystem, path, `zlib`, and child process modules */
|
/** Load Node modules */
|
||||||
var fs = require('fs'),
|
var fs = require('fs'),
|
||||||
gzip = require('zlib').gzip,
|
https = require('https'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
spawn = require('child_process').spawn;
|
spawn = require('child_process').spawn,
|
||||||
|
zlib = require('zlib'),
|
||||||
/** The directory that is the base of the repository */
|
tar = require('../vendor/tar/tar.js'),
|
||||||
var basePath = path.join(__dirname, '../');
|
_ = require('../lodash.js');
|
||||||
|
|
||||||
/** 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 */
|
/** Load other modules */
|
||||||
var preprocess = require(path.join(__dirname, 'pre-compile')),
|
var preprocess = require('./pre-compile.js'),
|
||||||
postprocess = require(path.join(__dirname, 'post-compile')),
|
postprocess = require('./post-compile.js');
|
||||||
uglifyJS = require(path.join(basePath, 'vendor', 'uglifyjs', 'uglify-js'));
|
|
||||||
|
|
||||||
/** Closure Compiler command-line options */
|
/** The Git object ID of `closure-compiler.tar.gz` */
|
||||||
var closureOptions = [
|
var closureId = '23cf67d0f0b979d97631fc108a2a43bb82225994';
|
||||||
'--compilation_level=ADVANCED_OPTIMIZATIONS',
|
|
||||||
'--language_in=ECMASCRIPT5_STRICT',
|
/** The Git object ID of `uglifyjs.tar.gz` */
|
||||||
'--warning_level=QUIET'
|
var uglifyId = 'a934fb18f8fa2768c6a68de44b6e035fe96a268b';
|
||||||
];
|
|
||||||
|
/** The path of the directory that is the base of the repository */
|
||||||
|
var basePath = fs.realpathSync(path.join(__dirname, '..'));
|
||||||
|
|
||||||
|
/** The path of the `vendor` directory */
|
||||||
|
var vendorPath = path.join(basePath, 'vendor');
|
||||||
|
|
||||||
|
/** The path to the Closure Compiler `.jar` */
|
||||||
|
var closurePath = path.join(vendorPath, 'closure-compiler', 'compiler.jar');
|
||||||
|
|
||||||
|
/** The path to the UglifyJS module */
|
||||||
|
var uglifyPath = path.join(vendorPath, 'uglifyjs', 'tools', 'node.js');
|
||||||
|
|
||||||
|
/** The Closure Compiler command-line options */
|
||||||
|
var closureOptions = ['--warning_level=QUIET'];
|
||||||
|
|
||||||
|
/** The media type for raw blob data */
|
||||||
|
var mediaType = 'application/vnd.github.v3.raw';
|
||||||
|
|
||||||
|
/** Used to reference parts of the blob href */
|
||||||
|
var location = (function() {
|
||||||
|
var host = 'api.github.com',
|
||||||
|
origin = 'https://api.github.com',
|
||||||
|
pathname = '/repos/bestiejs/lodash/git/blobs';
|
||||||
|
|
||||||
|
return {
|
||||||
|
'host': host,
|
||||||
|
'href': origin + pathname,
|
||||||
|
'origin': origin,
|
||||||
|
'pathname': pathname
|
||||||
|
};
|
||||||
|
}());
|
||||||
|
|
||||||
|
/** The Closure Compiler optimization modes */
|
||||||
|
var optimizationModes = {
|
||||||
|
'simple': 'SIMPLE_OPTIMIZATIONS',
|
||||||
|
'advanced': 'ADVANCED_OPTIMIZATIONS'
|
||||||
|
};
|
||||||
|
|
||||||
/** Reassign `existsSync` for older versions of Node */
|
/** Reassign `existsSync` for older versions of Node */
|
||||||
fs.existsSync || (fs.existsSync = path.existsSync);
|
fs.existsSync || (fs.existsSync = path.existsSync);
|
||||||
@@ -35,15 +65,134 @@
|
|||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The exposed `minify` function minifies a given Lo-Dash `source` and invokes
|
* Minifies a given Lo-Dash `source` and invokes the `options.onComplete`
|
||||||
* the `onComplete` callback when finished.
|
* callback when finished. The `onComplete` callback is invoked with one
|
||||||
|
* argument; (outputSource).
|
||||||
*
|
*
|
||||||
* @param {String} source The source to minify.
|
* @param {Array|String} [source=''] The source to minify or array of commands.
|
||||||
* @param {String} workingName The name to give temporary files creates during the minification process.
|
* -o, --output - Write output to a given path/filename.
|
||||||
* @param {Function} onComplete A function called when minification has completed.
|
* -s, --silent - Skip status updates normally logged to the console.
|
||||||
|
* -t, --template - Applies template specific minifier options.
|
||||||
|
*
|
||||||
|
* @param {Object} [options={}] The options object.
|
||||||
|
* outputPath - Write output to a given path/filename.
|
||||||
|
* isSilent - Skip status updates normally logged to the console.
|
||||||
|
* isTemplate - Applies template specific minifier options.
|
||||||
|
* onComplete - The function called once minification has finished.
|
||||||
*/
|
*/
|
||||||
function minify(source, workingName, onComplete) {
|
function minify(source, options) {
|
||||||
new Minify(source, workingName, onComplete);
|
// used to specify the source map URL
|
||||||
|
var sourceMapURL;
|
||||||
|
|
||||||
|
// used to specify the default minifer modes
|
||||||
|
var modes = ['simple', 'advanced', 'hybrid'];
|
||||||
|
|
||||||
|
source || (source = '');
|
||||||
|
options || (options = {});
|
||||||
|
|
||||||
|
// juggle arguments
|
||||||
|
if (Array.isArray(source)) {
|
||||||
|
// convert commands to an options object
|
||||||
|
options = source;
|
||||||
|
|
||||||
|
// used to report invalid command-line arguments
|
||||||
|
var invalidArgs = _.reject(options.slice(options[0] == 'node' ? 2 : 0), function(value, index, options) {
|
||||||
|
if (/^(?:-o|--output)$/.test(options[index - 1]) ||
|
||||||
|
/^modes=.*$/.test(value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var result = [
|
||||||
|
'-o', '--output',
|
||||||
|
'-p', '--source-map',
|
||||||
|
'-s', '--silent',
|
||||||
|
'-t', '--template'
|
||||||
|
].indexOf(value) > -1;
|
||||||
|
|
||||||
|
if (!result && /^(?:-p|--source-map)$/.test(options[index - 1])) {
|
||||||
|
result = true;
|
||||||
|
sourceMapURL = value;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
|
// report invalid arguments
|
||||||
|
if (invalidArgs.length) {
|
||||||
|
console.log(
|
||||||
|
'\n' +
|
||||||
|
'Invalid argument' + (invalidArgs.length > 1 ? 's' : '') +
|
||||||
|
' passed: ' + invalidArgs.join(', ')
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var filePath = options[options.length - 1],
|
||||||
|
isMapped = options.indexOf('-p') > -1 || options.indexOf('--source-map') > -1,
|
||||||
|
isSilent = options.indexOf('-s') > -1 || options.indexOf('--silent') > -1,
|
||||||
|
isTemplate = options.indexOf('-t') > -1 || options.indexOf('--template') > -1,
|
||||||
|
outputPath = path.join(path.dirname(filePath), path.basename(filePath, '.js') + '.min.js');
|
||||||
|
|
||||||
|
modes = options.reduce(function(result, value) {
|
||||||
|
var match = value.match(/modes=(.*)$/);
|
||||||
|
return match ? match[1].split(/, */) : result;
|
||||||
|
}, modes);
|
||||||
|
|
||||||
|
outputPath = options.reduce(function(result, value, index) {
|
||||||
|
if (/-o|--output/.test(value)) {
|
||||||
|
result = options[index + 1];
|
||||||
|
result = path.join(fs.realpathSync(path.dirname(result)), path.basename(result));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}, outputPath);
|
||||||
|
|
||||||
|
options = {
|
||||||
|
'filePath': filePath,
|
||||||
|
'isMapped': isMapped,
|
||||||
|
'isSilent': isSilent,
|
||||||
|
'isTemplate': isTemplate,
|
||||||
|
'modes': modes,
|
||||||
|
'outputPath': outputPath,
|
||||||
|
'sourceMapURL': sourceMapURL
|
||||||
|
};
|
||||||
|
|
||||||
|
source = fs.readFileSync(filePath, 'utf8');
|
||||||
|
}
|
||||||
|
|
||||||
|
modes = options.modes || modes;
|
||||||
|
if (options.isMapped) {
|
||||||
|
modes = modes.filter(function(mode) {
|
||||||
|
return mode != 'hybrid';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (options.isTemplate) {
|
||||||
|
modes = modes.filter(function(mode) {
|
||||||
|
return mode != 'advanced';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
options.modes = modes;
|
||||||
|
|
||||||
|
// fetch the Closure Compiler
|
||||||
|
getDependency({
|
||||||
|
'id': 'closure-compiler',
|
||||||
|
'hashId': closureId,
|
||||||
|
'path': vendorPath,
|
||||||
|
'title': 'the Closure Compiler',
|
||||||
|
'onComplete': function(exception) {
|
||||||
|
var error = exception;
|
||||||
|
|
||||||
|
// fetch UglifyJS
|
||||||
|
getDependency({
|
||||||
|
'id': 'uglifyjs',
|
||||||
|
'hashId': uglifyId,
|
||||||
|
'title': 'UglifyJS',
|
||||||
|
'path': vendorPath,
|
||||||
|
'onComplete': function(exception) {
|
||||||
|
error || (error = exception);
|
||||||
|
if (!error) {
|
||||||
|
new Minify(source, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,27 +201,130 @@
|
|||||||
* @private
|
* @private
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {String} source The source to minify.
|
* @param {String} source The source to minify.
|
||||||
* @param {String} workingName The name to give temporary files creates during the minification process.
|
* @param {Object} options The options object.
|
||||||
* @param {Function} onComplete A function called when minification has completed.
|
* outputPath - Write output to a given path/filename.
|
||||||
|
* isSilent - Skip status updates normally logged to the console.
|
||||||
|
* isTemplate - Applies template specific minifier options.
|
||||||
|
* onComplete - The function called once minification has finished.
|
||||||
*/
|
*/
|
||||||
function Minify(source, workingName, onComplete) {
|
function Minify(source, options) {
|
||||||
// create the destination directory if it doesn't exist
|
// juggle arguments
|
||||||
if (!fs.existsSync(distPath)) {
|
if (typeof source == 'object' && source) {
|
||||||
// avoid errors when called as a npm executable
|
options = source || options;
|
||||||
try {
|
source = options.source || '';
|
||||||
fs.mkdirSync(distPath);
|
|
||||||
} catch(e) { }
|
|
||||||
}
|
}
|
||||||
|
this.compiled = { 'simple': {}, 'advanced': {} };
|
||||||
this.compiled = {};
|
this.hybrid = { 'simple': {}, 'advanced': {} };
|
||||||
this.hybrid = {};
|
|
||||||
this.uglified = {};
|
this.uglified = {};
|
||||||
this.onComplete = onComplete;
|
|
||||||
this.source = source = preprocess(source);
|
this.filePath = options.filePath;
|
||||||
this.workingName = workingName;
|
this.isMapped = !!options.isMapped;
|
||||||
|
this.isSilent = !!options.isSilent;
|
||||||
|
this.isTemplate = !!options.isTemplate;
|
||||||
|
this.outputPath = options.outputPath;
|
||||||
|
this.sourceMapURL = options.sourceMapURL;
|
||||||
|
|
||||||
|
var modes = this.modes = options.modes;
|
||||||
|
source = this.source = preprocess(source, options);
|
||||||
|
|
||||||
|
this.onComplete = options.onComplete || function(data) {
|
||||||
|
var outputPath = this.outputPath,
|
||||||
|
sourceMap = data.sourceMap;
|
||||||
|
|
||||||
|
fs.writeFileSync(outputPath, data.source, 'utf8');
|
||||||
|
if (sourceMap) {
|
||||||
|
fs.writeFileSync(getMapPath(outputPath), sourceMap, 'utf8');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// begin the minification process
|
// begin the minification process
|
||||||
closureCompile.call(this, source, onClosureCompile.bind(this));
|
if (modes.indexOf('simple') > -1) {
|
||||||
|
closureCompile.call(this, source, 'simple', onClosureSimpleCompile.bind(this));
|
||||||
|
} else if (modes.indexOf('advanced') > -1) {
|
||||||
|
onClosureSimpleGzip.call(this);
|
||||||
|
} else {
|
||||||
|
onClosureAdvancedGzip.call(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches a required `.tar.gz` dependency with the given Git object ID from
|
||||||
|
* the Lo-Dash repo on GitHub. The object ID may be obtained by running
|
||||||
|
* `git hash-object path/to/dependency.tar.gz`.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Object} options The options object.
|
||||||
|
* id - The Git object ID of the `.tar.gz` file.
|
||||||
|
* onComplete - The function called once the extraction has finished.
|
||||||
|
* path - The path of the extraction directory.
|
||||||
|
* title - The dependency's title used in status updates logged to the console.
|
||||||
|
*/
|
||||||
|
function getDependency(options) {
|
||||||
|
options || (options = {});
|
||||||
|
|
||||||
|
var ran,
|
||||||
|
destPath = options.path,
|
||||||
|
hashId = options.hashId,
|
||||||
|
id = options.id,
|
||||||
|
onComplete = options.onComplete,
|
||||||
|
title = options.title;
|
||||||
|
|
||||||
|
// exit early if dependency exists
|
||||||
|
if (fs.existsSync(path.join(destPath, id))) {
|
||||||
|
onComplete();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var callback = function(exception) {
|
||||||
|
if (ran) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (exception) {
|
||||||
|
console.error([
|
||||||
|
'There was a problem installing ' + title + '.',
|
||||||
|
'Try running the command as root, via `sudo`, or manually install by running:',
|
||||||
|
'',
|
||||||
|
"curl -H 'Accept: " + mediaType + "' " + location.href + '/' + hashId + " | tar xvz -C '" + destPath + "'",
|
||||||
|
''
|
||||||
|
].join('\n'));
|
||||||
|
}
|
||||||
|
ran = true;
|
||||||
|
process.removeListener('uncaughtException', callback);
|
||||||
|
onComplete(exception);
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log('Downloading ' + title + '...');
|
||||||
|
process.on('uncaughtException', callback);
|
||||||
|
|
||||||
|
https.get({
|
||||||
|
'host': location.host,
|
||||||
|
'path': location.pathname + '/' + hashId,
|
||||||
|
'headers': {
|
||||||
|
// By default, all GitHub blob API endpoints return a JSON document
|
||||||
|
// containing Base64-encoded blob data. Overriding the `Accept` header
|
||||||
|
// with the GitHub raw media type returns the blob data directly.
|
||||||
|
// See http://developer.github.com/v3/media/.
|
||||||
|
'Accept': mediaType
|
||||||
|
}
|
||||||
|
}, function(response) {
|
||||||
|
var decompressor = zlib.createUnzip(),
|
||||||
|
parser = new tar.Extract({ 'path': destPath });
|
||||||
|
|
||||||
|
parser.on('end', callback);
|
||||||
|
response.pipe(decompressor).pipe(parser);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the source map path from the given output path.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {String} outputPath The output path.
|
||||||
|
* @returns {String} Returns the source map path.
|
||||||
|
*/
|
||||||
|
function getMapPath(outputPath) {
|
||||||
|
return path.join(path.dirname(outputPath), path.basename(outputPath, '.js') + '.map');
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
@@ -83,45 +335,86 @@
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {String} source The JavaScript source to minify.
|
* @param {String} source The JavaScript source to minify.
|
||||||
* @param {String} [message] The message to log.
|
* @param {String} mode The optimization mode.
|
||||||
* @param {Function} callback The function to call once the process completes.
|
* @param {Function} callback The function called once the process has completed.
|
||||||
*/
|
*/
|
||||||
function closureCompile(source, message, callback) {
|
function closureCompile(source, mode, callback) {
|
||||||
// the standard error stream, standard output stream, and Closure Compiler process
|
var filePath = this.filePath,
|
||||||
var error = '',
|
isAdvanced = mode == 'advanced',
|
||||||
output = '',
|
isMapped = this.isMapped,
|
||||||
compiler = spawn('java', ['-jar', closurePath].concat(closureOptions));
|
options = closureOptions.slice(),
|
||||||
|
outputPath = this.outputPath,
|
||||||
|
mapPath = getMapPath(outputPath),
|
||||||
|
sourceMapURL = this.sourceMapURL || path.basename(mapPath);
|
||||||
|
|
||||||
// juggle arguments
|
// remove copyright header to make other modifications easier
|
||||||
if (typeof message == 'function') {
|
var license = (/^(?:\s*\/\/.*\s*|\s*\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/\s*)*/.exec(source) || [''])[0];
|
||||||
callback = message;
|
if (license) {
|
||||||
message = null;
|
source = source.replace(license, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(message == null
|
var hasIIFE = /^;?\(function[^{]+{\s*/.test(source),
|
||||||
? 'Compressing ' + this.workingName + ' using the Closure Compiler...'
|
isStrict = hasIIFE && /^;?\(function[^{]+{\s*["']use strict["']/.test(source);
|
||||||
: message
|
|
||||||
);
|
|
||||||
|
|
||||||
compiler.stdout.on('data', function(data) {
|
// to avoid stripping the IIFE, convert it to a function call
|
||||||
// append the data to the output stream
|
if (hasIIFE && isAdvanced) {
|
||||||
output += data;
|
source = source
|
||||||
});
|
.replace(/\(function/, '__iife__$&')
|
||||||
|
.replace(/\(this\)\)([\s;]*(\n\/\/.+)?)$/, ', this)$1');
|
||||||
|
}
|
||||||
|
|
||||||
|
options.push('--compilation_level=' + optimizationModes[mode]);
|
||||||
|
if (isMapped) {
|
||||||
|
options.push('--create_source_map=' + mapPath, '--source_map_format=V3');
|
||||||
|
}
|
||||||
|
|
||||||
|
var compiler = spawn('java', ['-jar', closurePath].concat(options));
|
||||||
|
if (!this.isSilent) {
|
||||||
|
console.log('Compressing ' + path.basename(outputPath, '.js') + ' using the Closure Compiler (' + mode + ')...');
|
||||||
|
}
|
||||||
|
|
||||||
|
var error = '';
|
||||||
compiler.stderr.on('data', function(data) {
|
compiler.stderr.on('data', function(data) {
|
||||||
// append the error message to the error stream
|
|
||||||
error += data;
|
error += data;
|
||||||
});
|
});
|
||||||
|
|
||||||
compiler.on('exit', function(status) {
|
var output = '';
|
||||||
var exception = null;
|
compiler.stdout.on('data', function(data) {
|
||||||
|
output += data;
|
||||||
|
});
|
||||||
|
|
||||||
|
compiler.on('exit', function(status) {
|
||||||
// `status` contains the process exit code
|
// `status` contains the process exit code
|
||||||
if (status) {
|
if (status) {
|
||||||
exception = new Error(error);
|
var exception = new Error(error);
|
||||||
exception.status = status;
|
exception.status = status;
|
||||||
}
|
}
|
||||||
callback(exception, output);
|
// restore IIFE and move exposed vars inside the IIFE
|
||||||
|
if (hasIIFE && isAdvanced) {
|
||||||
|
output = output
|
||||||
|
.replace(/__iife__\(/, '(')
|
||||||
|
.replace(/,\s*this\)([\s;]*(\n\/\/.+)?)$/, '(this))$1')
|
||||||
|
.replace(/^((?:var (?:\w+=(?:!0|!1|null)[,;])+)?)([\s\S]*?function[^{]+{)/, '$2$1');
|
||||||
|
}
|
||||||
|
// inject "use strict" directive
|
||||||
|
if (isStrict) {
|
||||||
|
output = output.replace(/^[\s\S]*?function[^{]+{/, '$&"use strict";');
|
||||||
|
}
|
||||||
|
// restore copyright header
|
||||||
|
if (license) {
|
||||||
|
output = license + output;
|
||||||
|
}
|
||||||
|
if (isMapped) {
|
||||||
|
var mapOutput = fs.readFileSync(mapPath, 'utf8');
|
||||||
|
fs.unlinkSync(mapPath);
|
||||||
|
output = output.replace(/[\s;]*$/, '\n/*\n//@ sourceMappingURL=' + sourceMapURL) + '\n*/';
|
||||||
|
|
||||||
|
mapOutput = JSON.parse(mapOutput);
|
||||||
|
mapOutput.file = path.basename(outputPath);
|
||||||
|
mapOutput.sources = [path.basename(filePath)];
|
||||||
|
mapOutput = JSON.stringify(mapOutput, null, 2);
|
||||||
|
}
|
||||||
|
callback(exception, output, mapOutput);
|
||||||
});
|
});
|
||||||
|
|
||||||
// proxy the standard input to the Closure Compiler
|
// proxy the standard input to the Closure Compiler
|
||||||
@@ -135,84 +428,146 @@
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {String} source The JavaScript source to minify.
|
* @param {String} source The JavaScript source to minify.
|
||||||
* @param {String} [message] The message to log.
|
* @param {String} label The label to log.
|
||||||
* @param {Function} callback The function to call once the process completes.
|
* @param {Function} callback The function called once the process has completed.
|
||||||
*/
|
*/
|
||||||
function uglify(source, message, callback) {
|
function uglify(source, label, callback) {
|
||||||
var exception,
|
if (!this.isSilent) {
|
||||||
result,
|
console.log('Compressing ' + path.basename(this.outputPath, '.js') + ' using ' + label + '...');
|
||||||
ugly = uglifyJS.uglify;
|
|
||||||
|
|
||||||
// juggle arguments
|
|
||||||
if (typeof message == 'function') {
|
|
||||||
callback = message;
|
|
||||||
message = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(message == null
|
|
||||||
? 'Compressing ' + this.workingName + ' using UglifyJS...'
|
|
||||||
: message
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
result = ugly.gen_code(
|
var uglifyJS = require(uglifyPath);
|
||||||
// enable unsafe transformations
|
|
||||||
ugly.ast_squeeze_more(
|
// 1. parse
|
||||||
ugly.ast_squeeze(
|
var toplevel = uglifyJS.parse(source);
|
||||||
// munge variable and function names, excluding the special `define`
|
|
||||||
// function exposed by AMD loaders
|
// 2. compress
|
||||||
ugly.ast_mangle(uglifyJS.parser.parse(source), {
|
// enable unsafe comparisons
|
||||||
'except': ['define']
|
toplevel.figure_out_scope();
|
||||||
}
|
toplevel = toplevel.transform(uglifyJS.Compressor({
|
||||||
))), {
|
'comparisons': false,
|
||||||
'ascii_only': true
|
'unsafe_comps': true,
|
||||||
|
'warnings': false
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 3. mangle
|
||||||
|
// excluding the `define` function exposed by AMD loaders
|
||||||
|
toplevel.figure_out_scope();
|
||||||
|
toplevel.compute_char_frequency();
|
||||||
|
toplevel.mangle_names({
|
||||||
|
'except': ['define']
|
||||||
});
|
});
|
||||||
} catch(e) {
|
|
||||||
exception = e;
|
// 4. output
|
||||||
|
// restrict lines to 500 characters for consistency with the Closure Compiler
|
||||||
|
var stream = uglifyJS.OutputStream({
|
||||||
|
'ascii_only': true,
|
||||||
|
'comments': /@cc_on|@license|@preserve/i,
|
||||||
|
'max_line_len': 500,
|
||||||
|
});
|
||||||
|
|
||||||
|
toplevel.print(stream);
|
||||||
}
|
}
|
||||||
// lines are restricted to 500 characters for consistency with the Closure Compiler
|
catch(e) {
|
||||||
callback(exception, result && ugly.split_lines(result, 500));
|
var exception = e;
|
||||||
|
}
|
||||||
|
callback(exception, stream && String(stream));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `closureCompile()` callback.
|
* The Closure Compiler callback for simple optimizations.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {Object|Undefined} exception The error object.
|
* @param {Object|Undefined} exception The error object.
|
||||||
* @param {String} result The resulting minified source.
|
* @param {String} result The resulting minified source.
|
||||||
|
* @param {String} map The source map output.
|
||||||
*/
|
*/
|
||||||
function onClosureCompile(exception, result) {
|
function onClosureSimpleCompile(exception, result, map) {
|
||||||
if (exception) {
|
if (exception) {
|
||||||
throw exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
// store the post-processed Closure Compiler result and gzip it
|
result = postprocess(result);
|
||||||
this.compiled.source = result = postprocess(result);
|
|
||||||
gzip(result, onClosureGzip.bind(this));
|
var simple = this.compiled.simple;
|
||||||
|
simple.source = result;
|
||||||
|
simple.sourceMap = map;
|
||||||
|
zlib.gzip(result, onClosureSimpleGzip.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Closure Compiler `gzip` callback.
|
* The Closure Compiler `gzip` callback for simple optimizations.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {Object|Undefined} exception The error object.
|
* @param {Object|Undefined} exception The error object.
|
||||||
* @param {Buffer} result The resulting gzipped source.
|
* @param {Buffer} result The resulting gzipped source.
|
||||||
*/
|
*/
|
||||||
function onClosureGzip(exception, result) {
|
function onClosureSimpleGzip(exception, result) {
|
||||||
if (exception) {
|
if (exception) {
|
||||||
throw exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
// store the gzipped result and report the size
|
if (result != null) {
|
||||||
this.compiled.gzip = result;
|
if (!this.isSilent) {
|
||||||
console.log('Done. Size: %d bytes.', result.length);
|
console.log('Done. Size: %d bytes.', result.length);
|
||||||
|
}
|
||||||
// next, minify the source using only UglifyJS
|
this.compiled.simple.gzip = result;
|
||||||
uglify.call(this, this.source, onUglify.bind(this));
|
}
|
||||||
|
// compile the source using advanced optimizations
|
||||||
|
if (this.modes.indexOf('advanced') > -1) {
|
||||||
|
closureCompile.call(this, this.source, 'advanced', onClosureAdvancedCompile.bind(this));
|
||||||
|
} else {
|
||||||
|
onClosureAdvancedGzip.call(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `uglify()` callback.
|
* The Closure Compiler callback for advanced optimizations.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Object|Undefined} exception The error object.
|
||||||
|
* @param {String} result The resulting minified source.
|
||||||
|
* @param {String} map The source map output.
|
||||||
|
*/
|
||||||
|
function onClosureAdvancedCompile(exception, result, map) {
|
||||||
|
if (exception) {
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
result = postprocess(result);
|
||||||
|
|
||||||
|
var advanced = this.compiled.advanced;
|
||||||
|
advanced.source = result;
|
||||||
|
advanced.sourceMap = map;
|
||||||
|
zlib.gzip(result, onClosureAdvancedGzip.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Closure Compiler `gzip` callback for advanced optimizations.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Object|Undefined} exception The error object.
|
||||||
|
* @param {Buffer} result The resulting gzipped source.
|
||||||
|
*/
|
||||||
|
function onClosureAdvancedGzip(exception, result) {
|
||||||
|
if (exception) {
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
if (result != null) {
|
||||||
|
if (!this.isSilent) {
|
||||||
|
console.log('Done. Size: %d bytes.', result.length);
|
||||||
|
}
|
||||||
|
this.compiled.advanced.gzip = result;
|
||||||
|
}
|
||||||
|
// minify the source using UglifyJS
|
||||||
|
if (!this.isMapped) {
|
||||||
|
uglify.call(this, this.source, 'UglifyJS', onUglify.bind(this));
|
||||||
|
} else {
|
||||||
|
onComplete.call(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The UglifyJS callback.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {Object|Undefined} exception The error object.
|
* @param {Object|Undefined} exception The error object.
|
||||||
@@ -222,9 +577,9 @@
|
|||||||
if (exception) {
|
if (exception) {
|
||||||
throw exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
// store the post-processed Uglified result and gzip it
|
result = postprocess(result);
|
||||||
this.uglified.source = result = postprocess(result);
|
this.uglified.source = result;
|
||||||
gzip(result, onUglifyGzip.bind(this));
|
zlib.gzip(result, onUglifyGzip.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -238,89 +593,143 @@
|
|||||||
if (exception) {
|
if (exception) {
|
||||||
throw exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
var message = 'Compressing ' + this.workingName + ' using hybrid minification...';
|
if (result != null) {
|
||||||
|
if (!this.isSilent) {
|
||||||
// store the gzipped result and report the size
|
console.log('Done. Size: %d bytes.', result.length);
|
||||||
this.uglified.gzip = result;
|
}
|
||||||
console.log('Done. Size: %d bytes.', result.length);
|
this.uglified.gzip = result;
|
||||||
|
}
|
||||||
// next, minify the Closure Compiler minified source using UglifyJS
|
// minify the already Closure Compiler simple optimized source using UglifyJS
|
||||||
uglify.call(this, this.compiled.source, message, onHybrid.bind(this));
|
var modes = this.modes;
|
||||||
|
if (modes.indexOf('hybrid') > -1) {
|
||||||
|
if (modes.indexOf('simple') > -1) {
|
||||||
|
uglify.call(this, this.compiled.simple.source, 'hybrid (simple)', onSimpleHybrid.bind(this));
|
||||||
|
} else if (modes.indexOf('advanced') > -1) {
|
||||||
|
onSimpleHybridGzip.call(this);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
onComplete.call(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The hybrid `uglify()` callback.
|
* The hybrid callback for simple optimizations.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {Object|Undefined} exception The error object.
|
* @param {Object|Undefined} exception The error object.
|
||||||
* @param {String} result The resulting minified source.
|
* @param {String} result The resulting minified source.
|
||||||
*/
|
*/
|
||||||
function onHybrid(exception, result) {
|
function onSimpleHybrid(exception, result) {
|
||||||
if (exception) {
|
if (exception) {
|
||||||
throw exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
// store the post-processed Uglified result and gzip it
|
result = postprocess(result);
|
||||||
this.hybrid.source = result = postprocess(result);
|
this.hybrid.simple.source = result;
|
||||||
gzip(result, onHybridGzip.bind(this));
|
zlib.gzip(result, onSimpleHybridGzip.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The hybrid `gzip` callback.
|
* The hybrid `gzip` callback for simple optimizations.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {Object|Undefined} exception The error object.
|
* @param {Object|Undefined} exception The error object.
|
||||||
* @param {Buffer} result The resulting gzipped source.
|
* @param {Buffer} result The resulting gzipped source.
|
||||||
*/
|
*/
|
||||||
function onHybridGzip(exception, result) {
|
function onSimpleHybridGzip(exception, result) {
|
||||||
if (exception) {
|
if (exception) {
|
||||||
throw exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
// store the gzipped result and report the size
|
if (result != null) {
|
||||||
this.hybrid.gzip = result;
|
if (!this.isSilent) {
|
||||||
console.log('Done. Size: %d bytes.', result.length);
|
console.log('Done. Size: %d bytes.', result.length);
|
||||||
|
}
|
||||||
|
this.hybrid.simple.gzip = result;
|
||||||
|
}
|
||||||
|
// minify the already Closure Compiler advance optimized source using UglifyJS
|
||||||
|
if (this.modes.indexOf('advanced') > -1) {
|
||||||
|
uglify.call(this, this.compiled.advanced.source, 'hybrid (advanced)', onAdvancedHybrid.bind(this));
|
||||||
|
} else {
|
||||||
|
onComplete.call(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hybrid callback for advanced optimizations.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Object|Undefined} exception The error object.
|
||||||
|
* @param {String} result The resulting minified source.
|
||||||
|
*/
|
||||||
|
function onAdvancedHybrid(exception, result) {
|
||||||
|
if (exception) {
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
result = postprocess(result);
|
||||||
|
this.hybrid.advanced.source = result;
|
||||||
|
zlib.gzip(result, onAdvancedHybridGzip.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hybrid `gzip` callback for advanced optimizations.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Object|Undefined} exception The error object.
|
||||||
|
* @param {Buffer} result The resulting gzipped source.
|
||||||
|
*/
|
||||||
|
function onAdvancedHybridGzip(exception, result) {
|
||||||
|
if (exception) {
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
if (result != null) {
|
||||||
|
if (!this.isSilent) {
|
||||||
|
console.log('Done. Size: %d bytes.', result.length);
|
||||||
|
}
|
||||||
|
this.hybrid.advanced.gzip = result;
|
||||||
|
}
|
||||||
// finish by choosing the smallest compressed file
|
// finish by choosing the smallest compressed file
|
||||||
onComplete.call(this);
|
onComplete.call(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The callback executed after JavaScript source is minified and gzipped.
|
* The callback executed after the source is minified and gzipped.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function onComplete() {
|
function onComplete() {
|
||||||
var compiled = this.compiled,
|
var compiledSimple = this.compiled.simple,
|
||||||
hybrid = this.hybrid,
|
compiledAdvanced = this.compiled.advanced,
|
||||||
name = this.workingName,
|
uglified = this.uglified,
|
||||||
uglified = this.uglified;
|
hybridSimple = this.hybrid.simple,
|
||||||
|
hybridAdvanced = this.hybrid.advanced;
|
||||||
|
|
||||||
// avoid errors when called as a npm executable
|
var objects = [
|
||||||
try {
|
compiledSimple,
|
||||||
// save the Closure Compiled version to disk
|
compiledAdvanced,
|
||||||
fs.writeFileSync(path.join(distPath, name + '.compiler.js'), compiled.source);
|
uglified,
|
||||||
fs.writeFileSync(path.join(distPath, name + '.compiler.js.gz'), compiled.gzip);
|
hybridSimple,
|
||||||
|
hybridAdvanced
|
||||||
|
];
|
||||||
|
|
||||||
// save the Uglified version to disk
|
var gzips = objects
|
||||||
fs.writeFileSync(path.join(distPath, name + '.uglify.js'), uglified.source);
|
.map(function(data) { return data.gzip; })
|
||||||
fs.writeFileSync(path.join(distPath, name + '.uglify.js.gz'), uglified.gzip);
|
.filter(Boolean);
|
||||||
|
|
||||||
// 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);
|
|
||||||
} catch(e) { }
|
|
||||||
|
|
||||||
// select the smallest gzipped file and use its minified counterpart as the
|
// select the smallest gzipped file and use its minified counterpart as the
|
||||||
// official minified release (ties go to Closure Compiler)
|
// official minified release (ties go to the Closure Compiler)
|
||||||
var min = Math.min(compiled.gzip.length, hybrid.gzip.length, uglified.gzip.length);
|
var min = gzips.reduce(function(min, gzip) {
|
||||||
|
var length = gzip.length;
|
||||||
|
return min > length ? length : min;
|
||||||
|
}, Infinity);
|
||||||
|
|
||||||
// pass the minified source to the minify instances "onComplete" callback
|
// pass the minified source to the "onComplete" callback
|
||||||
this.onComplete(
|
objects.some(function(data) {
|
||||||
compiled.gzip.length == min
|
var gzip = data.gzip;
|
||||||
? compiled.source
|
if (gzip && gzip.length == min) {
|
||||||
: uglified.gzip.length == min
|
data.outputPath = this.outputPath;
|
||||||
? uglified.source
|
this.onComplete(data);
|
||||||
: hybrid.source
|
return true;
|
||||||
);
|
}
|
||||||
|
}, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
@@ -334,14 +743,11 @@
|
|||||||
// was invoked directly (e.g. `node minify.js source.js`) and write to
|
// was invoked directly (e.g. `node minify.js source.js`) and write to
|
||||||
// `<filename>.min.js`
|
// `<filename>.min.js`
|
||||||
(function() {
|
(function() {
|
||||||
var filePath = process.argv[2],
|
var options = process.argv;
|
||||||
dirPath = path.dirname(filePath),
|
if (options.length < 3) {
|
||||||
source = fs.readFileSync(filePath, 'utf8'),
|
return;
|
||||||
workingName = path.basename(filePath, '.js') + '.min';
|
}
|
||||||
|
minify(options);
|
||||||
minify(source, workingName, function(result) {
|
|
||||||
fs.writeFileSync(path.join(dirPath, workingName + '.js'), result, 'utf8');
|
|
||||||
});
|
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
}());
|
}());
|
||||||
|
|||||||
@@ -6,11 +6,13 @@
|
|||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
|
||||||
/** The minimal license/copyright template */
|
/** The minimal license/copyright template */
|
||||||
var licenseTemplate =
|
var licenseTemplate = [
|
||||||
'/*!\n' +
|
'/**',
|
||||||
' Lo-Dash @VERSION lodash.com/license\n' +
|
' * @license',
|
||||||
' Underscore.js 1.3.3 github.com/documentcloud/underscore/blob/master/LICENSE\n' +
|
' * Lo-Dash <%= VERSION %> lodash.com/license',
|
||||||
'*/';
|
' * Underscore.js 1.4.4 underscorejs.org/LICENSE',
|
||||||
|
' */'
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
@@ -22,29 +24,35 @@
|
|||||||
* @returns {String} Returns the processed source.
|
* @returns {String} Returns the processed source.
|
||||||
*/
|
*/
|
||||||
function postprocess(source) {
|
function postprocess(source) {
|
||||||
// exit early if snippet isn't found
|
// remove copyright header
|
||||||
|
source = source.replace(/^\/\**[\s\S]+?\*\/\n/, '');
|
||||||
|
|
||||||
|
// correct overly aggressive Closure Compiler advanced optimizations
|
||||||
|
source = source
|
||||||
|
.replace(/prototype\s*=\s*{\s*valueOf\s*:\s*1\s*}/, 'prototype={valueOf:1,y:1}')
|
||||||
|
.replace(/(document[^&]+&&)\s*(?:\w+|!\d)/, '$1!({toString:0}+"")');
|
||||||
|
|
||||||
|
// flip `typeof` expressions to help optimize Safari and
|
||||||
|
// correct the AMD module definition for AMD build optimizers
|
||||||
|
// (e.g. from `"number" == typeof x` to `typeof x == "number")
|
||||||
|
source = source.replace(/(\w)?("[^"]+")\s*([!=]=)\s*(typeof(?:\s*\([^)]+\)|\s+[.\w]+(?!\[)))/g, function(match, other, type, equality, expression) {
|
||||||
|
return (other ? other + ' ' : '') + expression + equality + type;
|
||||||
|
});
|
||||||
|
|
||||||
|
// add trailing semicolon
|
||||||
|
if (source) {
|
||||||
|
source = source.replace(/[\s;]*?(\s*\/\/.*\s*|\s*\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/\s*)*$/, ';$1');
|
||||||
|
}
|
||||||
|
// exit early if version snippet isn't found
|
||||||
var snippet = /VERSION\s*[=:]\s*([\'"])(.*?)\1/.exec(source);
|
var snippet = /VERSION\s*[=:]\s*([\'"])(.*?)\1/.exec(source);
|
||||||
if (!snippet) {
|
if (!snippet) {
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
// add new copyright header
|
||||||
|
var version = snippet[2];
|
||||||
|
source = licenseTemplate.replace('<%= VERSION %>', version) + '\n;' + source;
|
||||||
|
|
||||||
// set the version
|
return source;
|
||||||
var license = licenseTemplate.replace('@VERSION', snippet[2]);
|
|
||||||
|
|
||||||
// move vars exposed by Closure Compiler into the IIFE
|
|
||||||
source = source.replace(/^([^(\n]+)\s*(\(function[^)]+\){)/, '$2$1');
|
|
||||||
|
|
||||||
// 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
|
|
||||||
source = license + '\n;' + source;
|
|
||||||
|
|
||||||
// add trailing semicolon
|
|
||||||
return source.replace(/[\s;]*$/, ';');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
@@ -52,13 +60,20 @@
|
|||||||
// expose `postprocess`
|
// expose `postprocess`
|
||||||
if (module != require.main) {
|
if (module != require.main) {
|
||||||
module.exports = postprocess;
|
module.exports = postprocess;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
// read the Lo-Dash source file from the first argument if the script
|
// read the Lo-Dash source file from the first argument if the script
|
||||||
// was invoked directly (e.g. `node post-compile.js source.js`) and write to
|
// was invoked directly (e.g. `node post-compile.js source.js`) and write to
|
||||||
// the same file
|
// the same file
|
||||||
(function() {
|
(function() {
|
||||||
var source = fs.readFileSync(process.argv[2], 'utf8');
|
var options = process.argv;
|
||||||
fs.writeFileSync(process.argv[2], postprocess(source), 'utf8');
|
if (options.length < 3) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var filePath = options[options.length - 1],
|
||||||
|
source = fs.readFileSync(filePath, 'utf8');
|
||||||
|
|
||||||
|
fs.writeFileSync(filePath, postprocess(source), 'utf8');
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
}());
|
}());
|
||||||
|
|||||||
@@ -7,89 +7,77 @@
|
|||||||
|
|
||||||
/** Used to minify variables embedded in compiled strings */
|
/** Used to minify variables embedded in compiled strings */
|
||||||
var compiledVars = [
|
var compiledVars = [
|
||||||
'accumulator',
|
|
||||||
'args',
|
'args',
|
||||||
'arrayClass',
|
'argsIndex',
|
||||||
'bind',
|
'argsLength',
|
||||||
'callback',
|
'callback',
|
||||||
'className',
|
|
||||||
'collection',
|
'collection',
|
||||||
'compareAscending',
|
'createCallback',
|
||||||
'ctor',
|
'ctor',
|
||||||
'funcClass',
|
'guard',
|
||||||
'funcs',
|
|
||||||
'hasOwnProperty',
|
'hasOwnProperty',
|
||||||
'identity',
|
|
||||||
'index',
|
'index',
|
||||||
'isFunc',
|
'isArguments',
|
||||||
'iteratee',
|
'isArray',
|
||||||
'iterateeIndex',
|
'isString',
|
||||||
'iteratorBind',
|
'iterable',
|
||||||
'length',
|
'length',
|
||||||
'methodName',
|
|
||||||
'nativeKeys',
|
'nativeKeys',
|
||||||
'noaccum',
|
|
||||||
'object',
|
'object',
|
||||||
'objectTypes',
|
'objectTypes',
|
||||||
'prop',
|
'ownIndex',
|
||||||
'propIndex',
|
'ownProps',
|
||||||
'props',
|
|
||||||
'property',
|
|
||||||
'propertyIsEnumerable',
|
|
||||||
'result',
|
'result',
|
||||||
'skipProto',
|
'skipProto',
|
||||||
'slice',
|
'source',
|
||||||
'stringClass',
|
'thisArg'
|
||||||
'target',
|
|
||||||
'thisArg',
|
|
||||||
'toString',
|
|
||||||
'value'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/** Used to minify `compileIterator` option properties */
|
/** Used to minify `compileIterator` option properties */
|
||||||
var iteratorOptions = [
|
var iteratorOptions = [
|
||||||
'args',
|
'args',
|
||||||
'array',
|
'arrays',
|
||||||
'arrayBranch',
|
|
||||||
'beforeLoop',
|
|
||||||
'bottom',
|
'bottom',
|
||||||
'exit',
|
|
||||||
'firstArg',
|
'firstArg',
|
||||||
'hasDontEnumBug',
|
'hasDontEnumBug',
|
||||||
'inLoop',
|
'hasEnumPrototype',
|
||||||
'init',
|
|
||||||
'isKeysFast',
|
'isKeysFast',
|
||||||
'object',
|
'loop',
|
||||||
'objectBranch',
|
'nonEnumArgs',
|
||||||
'noCharByIndex',
|
'noCharByIndex',
|
||||||
'shadowed',
|
'shadowed',
|
||||||
'top',
|
'top',
|
||||||
'useHas',
|
'useHas'
|
||||||
'useStrict'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
/** Used to minify variables and string values to a single character */
|
/** Used to minify variables and string values to a single character */
|
||||||
var minNames = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
var minNames = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
||||||
|
minNames.push.apply(minNames, minNames.map(function(value) {
|
||||||
|
return value + value;
|
||||||
|
}));
|
||||||
|
|
||||||
/** Used to protect the specified properties from getting minified */
|
/** Used to protect the specified properties from getting minified */
|
||||||
var propWhitelist = [
|
var propWhitelist = [
|
||||||
'_',
|
'_',
|
||||||
'_chain',
|
'__wrapped__',
|
||||||
'_wrapped',
|
|
||||||
'after',
|
'after',
|
||||||
'all',
|
'all',
|
||||||
'amd',
|
'amd',
|
||||||
'any',
|
'any',
|
||||||
|
'assign',
|
||||||
|
'at',
|
||||||
'attachEvent',
|
'attachEvent',
|
||||||
'bind',
|
'bind',
|
||||||
'bindAll',
|
'bindAll',
|
||||||
'chain',
|
'bindKey',
|
||||||
'clearTimeout',
|
'clearTimeout',
|
||||||
'clone',
|
'clone',
|
||||||
|
'cloneDeep',
|
||||||
'collect',
|
'collect',
|
||||||
'compact',
|
'compact',
|
||||||
'compose',
|
'compose',
|
||||||
'contains',
|
'contains',
|
||||||
|
'countBy',
|
||||||
'criteria',
|
'criteria',
|
||||||
'debounce',
|
'debounce',
|
||||||
'defaults',
|
'defaults',
|
||||||
@@ -97,12 +85,13 @@
|
|||||||
'delay',
|
'delay',
|
||||||
'detect',
|
'detect',
|
||||||
'difference',
|
'difference',
|
||||||
|
'drop',
|
||||||
'each',
|
'each',
|
||||||
'environment',
|
'environment',
|
||||||
'escape',
|
'escape',
|
||||||
'escape',
|
|
||||||
'evaluate',
|
'evaluate',
|
||||||
'every',
|
'every',
|
||||||
|
'exports',
|
||||||
'extend',
|
'extend',
|
||||||
'filter',
|
'filter',
|
||||||
'find',
|
'find',
|
||||||
@@ -114,16 +103,20 @@
|
|||||||
'forIn',
|
'forIn',
|
||||||
'forOwn',
|
'forOwn',
|
||||||
'functions',
|
'functions',
|
||||||
|
'global',
|
||||||
'groupBy',
|
'groupBy',
|
||||||
'has',
|
'has',
|
||||||
'head',
|
'head',
|
||||||
|
'imports',
|
||||||
'identity',
|
'identity',
|
||||||
'include',
|
'include',
|
||||||
|
'index',
|
||||||
'indexOf',
|
'indexOf',
|
||||||
'initial',
|
'initial',
|
||||||
'inject',
|
'inject',
|
||||||
'interpolate',
|
'interpolate',
|
||||||
'intersection',
|
'intersection',
|
||||||
|
'invert',
|
||||||
'invoke',
|
'invoke',
|
||||||
'isArguments',
|
'isArguments',
|
||||||
'isArray',
|
'isArray',
|
||||||
@@ -140,6 +133,7 @@
|
|||||||
'isNull',
|
'isNull',
|
||||||
'isNumber',
|
'isNumber',
|
||||||
'isObject',
|
'isObject',
|
||||||
|
'isPlainObject',
|
||||||
'isRegExp',
|
'isRegExp',
|
||||||
'isString',
|
'isString',
|
||||||
'isUndefined',
|
'isUndefined',
|
||||||
@@ -149,15 +143,21 @@
|
|||||||
'map',
|
'map',
|
||||||
'max',
|
'max',
|
||||||
'memoize',
|
'memoize',
|
||||||
|
'merge',
|
||||||
'methods',
|
'methods',
|
||||||
'min',
|
'min',
|
||||||
'mixin',
|
'mixin',
|
||||||
'noConflict',
|
'noConflict',
|
||||||
|
'object',
|
||||||
|
'omit',
|
||||||
'once',
|
'once',
|
||||||
'opera',
|
'opera',
|
||||||
|
'pairs',
|
||||||
'partial',
|
'partial',
|
||||||
|
'partialRight',
|
||||||
'pick',
|
'pick',
|
||||||
'pluck',
|
'pluck',
|
||||||
|
'random',
|
||||||
'range',
|
'range',
|
||||||
'reduce',
|
'reduce',
|
||||||
'reduceRight',
|
'reduceRight',
|
||||||
@@ -165,6 +165,7 @@
|
|||||||
'rest',
|
'rest',
|
||||||
'result',
|
'result',
|
||||||
'select',
|
'select',
|
||||||
|
'setImmediate',
|
||||||
'setTimeout',
|
'setTimeout',
|
||||||
'shuffle',
|
'shuffle',
|
||||||
'size',
|
'size',
|
||||||
@@ -180,6 +181,7 @@
|
|||||||
'throttle',
|
'throttle',
|
||||||
'times',
|
'times',
|
||||||
'toArray',
|
'toArray',
|
||||||
|
'unescape',
|
||||||
'union',
|
'union',
|
||||||
'uniq',
|
'uniq',
|
||||||
'unique',
|
'unique',
|
||||||
@@ -188,10 +190,15 @@
|
|||||||
'values',
|
'values',
|
||||||
'variable',
|
'variable',
|
||||||
'VERSION',
|
'VERSION',
|
||||||
|
'where',
|
||||||
'without',
|
'without',
|
||||||
'wrap',
|
'wrap',
|
||||||
'zip',
|
'zip',
|
||||||
'zipObject'
|
|
||||||
|
// properties used by the `backbone` and `underscore` builds
|
||||||
|
'__chain__',
|
||||||
|
'chain',
|
||||||
|
'findWhere'
|
||||||
];
|
];
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
@@ -199,25 +206,28 @@
|
|||||||
/**
|
/**
|
||||||
* Pre-process a given Lo-Dash `source`, preparing it for minification.
|
* Pre-process a given Lo-Dash `source`, preparing it for minification.
|
||||||
*
|
*
|
||||||
* @param {String} source The source to process.
|
* @param {String} [source=''] The source to process.
|
||||||
|
* @param {Object} [options={}] The options object.
|
||||||
* @returns {String} Returns the processed source.
|
* @returns {String} Returns the processed source.
|
||||||
*/
|
*/
|
||||||
function preprocess(source) {
|
function preprocess(source, options) {
|
||||||
// remove copyright to add later in post-compile.js
|
source || (source = '');
|
||||||
source = source.replace(/\/\*![\s\S]+?\*\//, '');
|
options || (options = {});
|
||||||
|
|
||||||
// remove unrecognized JSDoc tags so Closure Compiler won't complain
|
// remove unrecognized JSDoc tags so the Closure Compiler won't complain
|
||||||
source = source.replace(/@(?:alias|category)\b.*/g, '');
|
source = source.replace(/@(?:alias|category)\b.*/g, '');
|
||||||
|
|
||||||
// add brackets to whitelisted properties so Closure Compiler won't mung them
|
if (options.isTemplate) {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
// add brackets to whitelisted properties so the Closure Compiler won't mung them
|
||||||
// http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
|
// http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
|
||||||
source = source.replace(RegExp('\\.(' + propWhitelist.join('|') + ')\\b', 'g'), "['$1']");
|
source = source.replace(RegExp('\\.(' + propWhitelist.join('|') + ')\\b', 'g'), function(match, prop) {
|
||||||
|
return "['" + prop.replace(/['\n\r\t]/g, '\\$&') + "']";
|
||||||
// remove brackets from `_.escape()` in `tokenizeEscape`
|
});
|
||||||
source = source.replace(/_\['escape']\("/, '_.escape("');
|
|
||||||
|
|
||||||
// remove brackets from `_.escape()` in `_.template`
|
// remove brackets from `_.escape()` in `_.template`
|
||||||
source = source.replace(/__e *= *_\['escape']/, '__e=_.escape');
|
source = source.replace(/__e *= *_\['escape']/g, '__e=_.escape');
|
||||||
|
|
||||||
// remove brackets from `collection.indexOf` in `_.contains`
|
// remove brackets from `collection.indexOf` in `_.contains`
|
||||||
source = source.replace("collection['indexOf'](target)", 'collection.indexOf(target)');
|
source = source.replace("collection['indexOf'](target)", 'collection.indexOf(target)');
|
||||||
@@ -226,56 +236,56 @@
|
|||||||
source = source.replace("result[length]['value']", 'result[length].value');
|
source = source.replace("result[length]['value']", 'result[length].value');
|
||||||
|
|
||||||
// remove whitespace from string literals
|
// remove whitespace from string literals
|
||||||
source = source.replace(/'(?:(?=(\\?))\1.)*?'/g, function(string) {
|
source = source.replace(/^([ "'\w]+:)? *"[^"\\\n]*(?:\\.[^"\\\n]*)*"|'[^'\\\n]*(?:\\.[^'\\\n]*)*'/gm, function(string, captured) {
|
||||||
|
// remove object literal property name
|
||||||
|
if (/:$/.test(captured)) {
|
||||||
|
string = string.slice(captured.length);
|
||||||
|
}
|
||||||
// avoids removing the '\n' of the `stringEscapes` object
|
// avoids removing the '\n' of the `stringEscapes` object
|
||||||
return string.replace(/\[object |else if|function | in |return\s+[\w']|throw |typeof |use strict|var |@ |'\\n'|\\\\n|\\n|\s+/g, function(match) {
|
string = string.replace(/\[object |delete |else (?!{)|function | in |return\s+[\w"']|throw |typeof |use strict|var |@ |(["'])\\n\1|\\\\n|\\n|\s+/g, function(match) {
|
||||||
return match == false || match == '\\n' ? '' : match;
|
return match == false || match == '\\n' ? '' : match;
|
||||||
});
|
});
|
||||||
|
// prepend object literal property name
|
||||||
|
return (captured || '') + string;
|
||||||
});
|
});
|
||||||
|
|
||||||
// remove whitespace from `_.template` related regexpes
|
// remove whitespace from `_.template` related regexes
|
||||||
source = source.replace(/(?:reDelimiterCode\w+|reEmptyString\w+|reInsertVariable) *=.+/g, function(match) {
|
source = source.replace(/reEmptyString\w+ *=.+/g, function(match) {
|
||||||
return match.replace(/ |\\n/g, '');
|
return match.replace(/ |\\n/g, '');
|
||||||
});
|
});
|
||||||
|
|
||||||
// remove newline from double-quoted strings in `_.template`
|
// remove newline from double-quoted strings in `_.template`
|
||||||
source = source
|
source = source
|
||||||
.replace('"\';\\n__with ("', '"\';__with("')
|
.replace('"__p += \'"', '"__p+=\'"')
|
||||||
.replace('"\\n}__\\n__p += \'"', '"}____p+=\'"')
|
.replace('"\';\n"', '"\';"')
|
||||||
.replace('"__p = \'"', '"__p=\'"')
|
|
||||||
.replace('"\';\\n"', '"\';"')
|
|
||||||
.replace("') {\\n'", "'){'")
|
|
||||||
|
|
||||||
// remove `useSourceURL` variable
|
|
||||||
source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *try *\{(?:\s*\/\/.*\n)* *var useSourceURL[\s\S]+?catch[^}]+}\n/, '');
|
|
||||||
|
|
||||||
// remove debug sourceURL use in `_.template`
|
// remove debug sourceURL use in `_.template`
|
||||||
source = source.replace(/(?:\s*\/\/.*\n)* *if *\(useSourceURL[^}]+}/, '');
|
source = source.replace(/(?:\s*\/\/.*\n)* *var sourceURL[^;]+;|\+ *sourceURL/g, '');
|
||||||
|
|
||||||
// minify internal properties used by `_.sortBy`
|
// minify internal properties used by 'compareAscending' and `_.sortBy`
|
||||||
(function() {
|
(function() {
|
||||||
var properties = ['criteria', 'value'],
|
var properties = ['criteria', 'index', 'value'],
|
||||||
snippets = source.match(/( +)(?:function compareAscending|var sortBy)\b[\s\S]+?\n\1}/g);
|
snippets = source.match(/( +)function (?:compareAscending|sortBy)\b[\s\S]+?\n\1}/g);
|
||||||
|
|
||||||
if (!snippets) {
|
if (!snippets) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
snippets.forEach(function(snippet) {
|
snippets.forEach(function(snippet) {
|
||||||
var modified = snippet,
|
var modified = snippet;
|
||||||
isSortBy = /var sortBy\b/.test(modified),
|
|
||||||
isInlined = !/\bcreateIterator\b/.test(modified);
|
|
||||||
|
|
||||||
// minify properties
|
// minify properties
|
||||||
properties.forEach(function(property, index) {
|
properties.forEach(function(property, index) {
|
||||||
// add quotes around properties in the inlined `_.sortBy` of the mobile
|
var minName = minNames[index],
|
||||||
// build so Closure Compiler won't mung them
|
reBracketProp = RegExp("\\['(" + property + ")'\\]", 'g'),
|
||||||
if (isSortBy && isInlined) {
|
reDotProp = RegExp('\\.' + property + '\\b', 'g'),
|
||||||
modified = modified
|
rePropColon = RegExp("([^?\\s])\\s*([\"'])?\\b" + property + "\\2 *:", 'g');
|
||||||
.replace(RegExp('\\.' + property + '\\b', 'g'), "['" + minNames[index] + "']")
|
|
||||||
.replace(RegExp('\\b' + property + ' *:', 'g'), "'" + minNames[index] + "':");
|
modified = modified
|
||||||
}
|
.replace(reBracketProp, "['" + minName + "']")
|
||||||
modified = modified.replace(RegExp('\\b' + property + '\\b', 'g'), minNames[index]);
|
.replace(reDotProp, "['" + minName + "']")
|
||||||
|
.replace(rePropColon, "$1'" + minName + "':");
|
||||||
});
|
});
|
||||||
|
|
||||||
// replace with modified snippet
|
// replace with modified snippet
|
||||||
source = source.replace(snippet, modified);
|
source = source.replace(snippet, modified);
|
||||||
});
|
});
|
||||||
@@ -305,46 +315,36 @@
|
|||||||
isIteratorTemplate = /var iteratorTemplate\b/.test(snippet),
|
isIteratorTemplate = /var iteratorTemplate\b/.test(snippet),
|
||||||
modified = snippet;
|
modified = snippet;
|
||||||
|
|
||||||
// add brackets to whitelisted properties so Closure Compiler won't mung them
|
// add brackets to iterator option properties so the Closure Compiler won't mung them
|
||||||
modified = modified.replace(RegExp('\\.(' + iteratorOptions.join('|') + ')\\b', 'g'), "['$1']");
|
modified = modified.replace(RegExp('\\.(' + iteratorOptions.join('|') + ')\\b', 'g'), function(match, prop) {
|
||||||
|
return "['" + prop.replace(/['\n\r\t]/g, '\\$&') + "']";
|
||||||
|
});
|
||||||
|
|
||||||
if (isCreateIterator) {
|
if (isCreateIterator) {
|
||||||
// replace with modified snippet early and clip snippet to the `factory`
|
// clip before the `factory` call to avoid minifying its arguments
|
||||||
// call so other arguments aren't minified
|
|
||||||
source = source.replace(snippet, modified);
|
source = source.replace(snippet, modified);
|
||||||
snippet = modified = modified.replace(/factory\([\s\S]+$/, '');
|
snippet = modified = modified.replace(/return factory\([\s\S]+$/, '');
|
||||||
}
|
}
|
||||||
|
// minify `createIterator` option property names
|
||||||
|
iteratorOptions.forEach(function(property, index) {
|
||||||
|
var minName = minNames[index];
|
||||||
|
|
||||||
|
// minify variables in `iteratorTemplate` or property names in everything else
|
||||||
|
modified = isIteratorTemplate
|
||||||
|
? modified.replace(RegExp('\\b' + property + '\\b', 'g'), minName)
|
||||||
|
: modified.replace(RegExp("'" + property + "'", 'g'), "'" + minName + "'");
|
||||||
|
});
|
||||||
|
|
||||||
// minify snippet variables / arguments
|
// minify snippet variables / arguments
|
||||||
compiledVars.forEach(function(variable, index) {
|
compiledVars.forEach(function(variable, index) {
|
||||||
|
var minName = minNames[index];
|
||||||
|
|
||||||
// ensure properties in compiled strings aren't minified
|
// ensure properties in compiled strings aren't minified
|
||||||
modified = modified.replace(RegExp('([^.]\\b)' + variable + '\\b(?!\' *[\\]:])', 'g'), '$1' + minNames[index]);
|
modified = modified.replace(RegExp('([^.]\\b)' + variable + '\\b(?!\' *[\\]:])', 'g'), '$1' + minName);
|
||||||
|
|
||||||
// correct `typeof x == 'object'`
|
// correct `typeof` values
|
||||||
if (variable == 'object') {
|
if (/^(?:boolean|function|object|number|string|undefined)$/.test(variable)) {
|
||||||
modified = modified.replace(RegExp("(typeof [^']+')" + minNames[index] + "'", 'g'), "$1object'");
|
modified = modified.replace(RegExp("(typeof [^']+')" + minName + "'", 'g'), '$1' + variable + "'");
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// minify `createIterator` option property names
|
|
||||||
iteratorOptions.forEach(function(property, index) {
|
|
||||||
if (isIteratorTemplate) {
|
|
||||||
// minify property names as interpolated template variables
|
|
||||||
modified = modified.replace(RegExp('\\b' + property + '\\b', 'g'), minNames[index]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (property == 'array' || property == 'object') {
|
|
||||||
// minify "array" and "object" sub property names
|
|
||||||
modified = modified.replace(RegExp("'" + property + "'( *[\\]:])", 'g'), "'" + minNames[index] + "'$1");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// minify property name strings
|
|
||||||
modified = modified.replace(RegExp("'" + property + "'", 'g'), "'" + minNames[index] + "'");
|
|
||||||
// minify property names in regexps and accessors
|
|
||||||
if (isCreateIterator) {
|
|
||||||
modified = modified.replace(RegExp('([\\.|/])' + property + '\\b' , 'g'), '$1' + minNames[index]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -366,8 +366,17 @@
|
|||||||
// was invoked directly (e.g. `node pre-compile.js source.js`) and write to
|
// was invoked directly (e.g. `node pre-compile.js source.js`) and write to
|
||||||
// the same file
|
// the same file
|
||||||
(function() {
|
(function() {
|
||||||
var source = fs.readFileSync(process.argv[2], 'utf8');
|
var options = process.argv;
|
||||||
fs.writeFileSync(process.argv[2], preprocess(source), 'utf8');
|
if (options.length < 3) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var filePath = options[options.length - 1],
|
||||||
|
isTemplate = options.indexOf('-t') > -1 || options.indexOf('--template') > -1,
|
||||||
|
source = fs.readFileSync(filePath, 'utf8');
|
||||||
|
|
||||||
|
fs.writeFileSync(filePath, preprocess(source, {
|
||||||
|
'isTemplate': isTemplate
|
||||||
|
}), 'utf8');
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
}());
|
}());
|
||||||
|
|||||||
5152
dist/lodash.compat.js
vendored
Normal file
5152
dist/lodash.compat.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
42
dist/lodash.compat.min.js
vendored
Normal file
42
dist/lodash.compat.min.js
vendored
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Lo-Dash 1.0.2 (Custom Build) lodash.com/license
|
||||||
|
* Build: `lodash -o ./dist/lodash.compat.js`
|
||||||
|
* Underscore.js 1.4.4 underscorejs.org/LICENSE
|
||||||
|
*/
|
||||||
|
;(function(n,t){function r(n){return n&&typeof n=="object"&&n.__wrapped__?n:this instanceof r?(this.__wrapped__=n,void 0):new r(n)}function e(n,t,r){t||(t=0);var e=n.length,u=e-t>=(r||at);if(u){var o={};for(r=t-1;++r<e;){var i=n[r]+"";(St.call(o,i)?o[i]:o[i]=[]).push(n[r])}}return function(r){if(u){var e=r+"";return St.call(o,e)&&-1<z(o[e],r)}return-1<z(n,r,t)}}function u(n){return n.charCodeAt(0)}function o(n,t){var r=n.b,e=t.b;if(n=n.a,t=t.a,n!==t){if(n>t||typeof n=="undefined")return 1;if(n<t||typeof t=="undefined")return-1
|
||||||
|
}return r<e?-1:1}function i(n,t,r,e){function u(){var a=arguments,c=i?this:t;return o||(n=t[f]),r.length&&(a=a.length?(a=v(a),e?a.concat(r):r.concat(a)):r),this instanceof u?(s.prototype=n.prototype,c=new s,s.prototype=W,a=n.apply(c,a),x(a)?a:c):n.apply(c,a)}var o=w(n),i=!r,f=t;return i&&(r=t),o||(t=n),u}function f(n,t,r){if(n==W)return G;var e=typeof n;if("function"!=e){if("object"!=e)return function(t){return t[n]};var u=vr(n);return function(t){for(var r=u.length,e=X;r--&&(e=j(t[u[r]],n[u[r]],ft)););return e
|
||||||
|
}}return typeof t!="undefined"?1===r?function(r){return n.call(t,r)}:2===r?function(r,e){return n.call(t,r,e)}:4===r?function(r,e,u,o){return n.call(t,r,e,u,o)}:function(r,e,u){return n.call(t,r,e,u)}:n}function a(){for(var n,t={e:tt,f:rt,g:Jt,i:Wt,j:Zt,k:jt,b:"l(n)",c:"",h:"",l:"",m:Q},r=0;n=arguments[r];r++)for(var e in n)t[e]=n[e];if(n=t.a,t.d=/^[^,]+/.exec(n)[0],r="var j,n="+t.d+",u=n;if(!n)return u;"+t.l+";",t.b?(r+="var o=n.length;j=-1;if("+t.b+"){",t.j&&(r+="if(m(n)){n=n.split('')}"),r+="while(++j<o){"+t.h+"}}else{"):t.i&&(r+="var o=n.length;j=-1;if(o&&k(n)){while(++j<o){j+='';"+t.h+"}}else{"),t.f&&(r+="var v=typeof n=='function';"),t.g&&t.m?(r+="var s=-1,t=r[typeof n]?p(n):[],o=t.length;while(++s<o){j=t[s];",t.f&&(r+="if(!(v&&j=='prototype')){"),r+=t.h+"",t.f&&(r+="}")):(r+="for(j in n){",(t.f||t.m)&&(r+="if(",t.f&&(r+="!(v&&j=='prototype')"),t.f&&t.m&&(r+="&&"),t.m&&(r+="i.call(n,j)"),r+="){"),r+=t.h+";",(t.f||t.m)&&(r+="}")),r+="}",t.e)for(r+="var g=n.constructor;",e=0;7>e;e++)r+="j='"+t.k[e]+"';if(","constructor"==t.k[e]&&(r+="!(g&&g.prototype===n)&&"),r+="i.call(n,j)){"+t.h+"}";
|
||||||
|
return(t.b||t.i)&&(r+="}"),r+=t.c+";return u",Function("f,i,k,l,m,r,p","return function("+n+"){"+r+"}")(f,St,y,sr,A,ur,Ft)}function c(n){return"\\"+or[n]}function l(n){return gr[n]}function p(n){return typeof n.toString!="function"&&typeof(n+"")=="string"}function s(){}function v(n,t,r){t||(t=0),typeof r=="undefined"&&(r=n?n.length:0);var e=-1;r=r-t||0;for(var u=Array(0>r?0:r);++e<r;)u[e]=n[t+e];return u}function g(n){return yr[n]}function y(n){return kt.call(n)==Bt}function h(n){var t=X;if(!n||typeof n!="object"||y(n))return t;
|
||||||
|
var r=n.constructor;return!w(r)&&(!nr||!p(n))||r instanceof r?et?(lr(n,function(n,r,e){return t=!St.call(e,r),X}),t===X):(lr(n,function(n,r){t=r}),t===X||St.call(n,t)):t}function m(n){var t=[];return pr(n,function(n,r){t.push(r)}),t}function d(n,r,e,u,o,i){var a=n;if(typeof r=="function"&&(u=e,e=r,r=X),typeof e=="function"){e=typeof u=="undefined"?e:f(e,u,1);var a=e(a),c=typeof a!="undefined";c||(a=n)}if(u=x(a)){var l=kt.call(a);if(!rr[l]||nr&&p(a))return a;var s=sr(a)}if(!u||!r)return u&&!c?s?v(a):hr({},a):a;
|
||||||
|
switch(u=er[l],l){case Pt:case zt:return c?a:new u(+a);case Ct:case Ut:return c?a:new u(a);case Lt:return c?a:u(a.source,gt.exec(a))}for(o||(o=[]),i||(i=[]),l=o.length;l--;)if(o[l]==n)return i[l];return c||(a=s?u(a.length):{},s&&(St.call(n,"index")&&(a.index=n.index),St.call(n,"input")&&(a.input=n.input))),o.push(n),i.push(a),(s?$:pr)(c?a:n,function(n,u){a[u]=d(n,r,e,t,o,i)}),a}function _(n){var t=[];return lr(n,function(n,r){w(n)&&t.push(r)}),t.sort()}function b(n){for(var t=-1,r=vr(n),e=r.length,u={};++t<e;){var o=r[t];
|
||||||
|
u[n[o]]=o}return u}function j(n,t,r,e,u,o){var i=r===ft;if(r&&!i){r=typeof e=="undefined"?r:f(r,e,2);var a=r(n,t);if(typeof a!="undefined")return!!a}if(n===t)return 0!==n||1/n==1/t;var c=typeof n,l=typeof t;if(n===n&&(!n||"function"!=c&&"object"!=c)&&(!t||"function"!=l&&"object"!=l))return X;if(n==W||t==W)return n===t;if(l=kt.call(n),c=kt.call(t),l==Bt&&(l=Kt),c==Bt&&(c=Kt),l!=c)return X;switch(l){case Pt:case zt:return+n==+t;case Ct:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case Lt:case Ut:return n==t+""
|
||||||
|
}if(c=l==Mt,!c){if(n.__wrapped__||t.__wrapped__)return j(n.__wrapped__||n,t.__wrapped__||t,r,e,u,o);if(l!=Kt||nr&&(p(n)||p(t)))return X;var l=!Xt&&y(n)?Object:n.constructor,s=!Xt&&y(t)?Object:t.constructor;if(l!=s&&(!w(l)||!(l instanceof l&&w(s)&&s instanceof s)))return X}for(u||(u=[]),o||(o=[]),l=u.length;l--;)if(u[l]==n)return o[l]==t;var v=0,a=Q;if(u.push(n),o.push(t),c){if(l=n.length,v=t.length,a=v==n.length,!a&&!i)return a;for(;v--;)if(c=l,s=t[v],i)for(;c--&&!(a=j(n[c],s,r,e,u,o)););else if(!(a=j(n[v],s,r,e,u,o)))break;
|
||||||
|
return a}return lr(t,function(t,i,f){return St.call(f,i)?(v++,a=St.call(n,i)&&j(n[i],t,r,e,u,o)):void 0}),a&&!i&&lr(n,function(n,t,r){return St.call(r,t)?a=-1<--v:void 0}),a}function w(n){return typeof n=="function"}function x(n){return n?ur[typeof n]:X}function O(n){return typeof n=="number"||kt.call(n)==Ct}function A(n){return typeof n=="string"||kt.call(n)==Ut}function S(n,t,r){var e=arguments,u=0,o=2;if(!x(n))return n;if(r===ft)var i=e[3],a=e[4],c=e[5];else a=[],c=[],typeof r!="number"&&(o=e.length),3<o&&"function"==typeof e[o-2]?i=f(e[--o-1],e[o--],2):2<o&&"function"==typeof e[o-1]&&(i=e[--o]);
|
||||||
|
for(;++u<o;)(sr(e[u])?$:pr)(e[u],function(t,r){var e,u,o=t,f=n[r];if(t&&((u=sr(t))||dr(t))){for(o=a.length;o--;)if(e=a[o]==t){f=c[o];break}e||(f=u?sr(f)?f:[]:dr(f)?f:{},i&&(o=i(f,t),typeof o!="undefined"&&(f=o)),a.push(t),c.push(f),i||(f=S(f,t,ft,i,a,c)))}else i&&(o=i(f,t),typeof o=="undefined"&&(o=t)),typeof o!="undefined"&&(f=o);n[r]=f});return n}function E(n){for(var t=-1,r=vr(n),e=r.length,u=Array(e);++t<e;)u[t]=n[r[t]];return u}function k(n,t,r){var e=-1,u=n?n.length:0,o=X;return r=(0>r?qt(0,u+r):r)||0,typeof u=="number"?o=-1<(A(n)?n.indexOf(t,r):z(n,t,r)):cr(n,function(n){return++e<r?void 0:!(o=n===t)
|
||||||
|
}),o}function I(n,t,r){var e=Q;if(t=f(t,r),sr(n)){r=-1;for(var u=n.length;++r<u&&(e=!!t(n[r],r,n)););}else cr(n,function(n,r,u){return e=!!t(n,r,u)});return e}function N(n,t,r){var e=[];if(t=f(t,r),sr(n)){r=-1;for(var u=n.length;++r<u;){var o=n[r];t(o,r,n)&&e.push(o)}}else cr(n,function(n,r,u){t(n,r,u)&&e.push(n)});return e}function R(n,t,r){var e;return t=f(t,r),$(n,function(n,r,u){return t(n,r,u)?(e=n,X):void 0}),e}function $(n,t,r){if(t&&typeof r=="undefined"&&sr(n)){r=-1;for(var e=n.length;++r<e&&t(n[r],r,n)!==X;);}else cr(n,t,r);
|
||||||
|
return n}function F(n,t,r){var e=-1,u=n?n.length:0,o=Array(typeof u=="number"?u:0);if(t=f(t,r),sr(n))for(;++e<u;)o[e]=t(n[e],e,n);else cr(n,function(n,r,u){o[++e]=t(n,r,u)});return o}function q(n,t,r){var e=-1/0,o=e;if(!t&&sr(n)){r=-1;for(var i=n.length;++r<i;){var a=n[r];a>o&&(o=a)}}else t=!t&&A(n)?u:f(t,r),cr(n,function(n,r,u){r=t(n,r,u),r>e&&(e=r,o=n)});return o}function D(n,t,r,e){var u=3>arguments.length;if(t=f(t,e,4),sr(n)){var o=-1,i=n.length;for(u&&(r=n[++o]);++o<i;)r=t(r,n[o],o,n)}else cr(n,function(n,e,o){r=u?(u=X,n):t(r,n,e,o)
|
||||||
|
});return r}function T(n,t,r,e){var u=n,o=n?n.length:0,i=3>arguments.length;if(typeof o!="number")var a=vr(n),o=a.length;else Zt&&A(n)&&(u=n.split(""));return t=f(t,e,4),$(n,function(n,e,f){e=a?a[--o]:--o,r=i?(i=X,u[e]):t(r,u[e],e,f)}),r}function B(n,t,r){var e;if(t=f(t,r),sr(n)){r=-1;for(var u=n.length;++r<u&&!(e=t(n[r],r,n)););}else cr(n,function(n,r,u){return!(e=t(n,r,u))});return!!e}function M(n,t,r){if(n){var e=0,u=n.length;if(typeof t!="number"&&t!=W){var o=-1;for(t=f(t,r);++o<u&&t(n[o],o,n);)e++
|
||||||
|
}else if(e=t,e==W||r)return n[0];return v(n,0,Dt(qt(0,e),u))}}function P(n,t){for(var r=-1,e=n?n.length:0,u=[];++r<e;){var o=n[r];sr(o)?Et.apply(u,t?o:P(o)):u.push(o)}return u}function z(n,t,r){var e=-1,u=n?n.length:0;if(typeof r=="number")e=(0>r?qt(0,u+r):r||0)-1;else if(r)return e=K(n,t),n[e]===t?e:-1;for(;++e<u;)if(n[e]===t)return e;return-1}function C(n,t,r){if(typeof t!="number"&&t!=W){var e=0,u=-1,o=n?n.length:0;for(t=f(t,r);++u<o&&t(n[u],u,n);)e++}else e=t==W||r?1:qt(0,t);return v(n,e)}function K(n,t,r,e){var u=0,o=n?n.length:u;
|
||||||
|
for(r=r?f(r,e,1):G,t=r(t);u<o;)e=u+o>>>1,r(n[e])<t?u=e+1:o=e;return u}function L(n,t,r,e){var u=-1,o=n?n.length:0,i=[],a=i;typeof t=="function"&&(e=r,r=t,t=X);var c=!t&&75<=o;if(c)var l={};for(r&&(a=[],r=f(r,e));++u<o;){e=n[u];var p=r?r(e,u,n):e;if(c)var s=p+"",s=St.call(l,s)?!(a=l[s]):a=l[s]=[];(t?!u||a[a.length-1]!==p:s||0>z(a,p))&&((r||c)&&a.push(p),i.push(e))}return i}function U(n,t){return Ht||It&&2<arguments.length?It.call.apply(It,arguments):i(n,t,v(arguments,2))}function V(n){var r=v(arguments,1);
|
||||||
|
return setTimeout(function(){n.apply(t,r)},1)}function G(n){return n}function H(n){$(_(n),function(t){var e=r[t]=n[t];r.prototype[t]=function(){var n=[this.__wrapped__];return Et.apply(n,arguments),new r(e.apply(r,n))}})}function J(){return this.__wrapped__}var Q=!0,W=null,X=!1,Y=typeof exports=="object"&&exports,Z=typeof module=="object"&&module&&module.exports==Y&&module,nt=typeof global=="object"&&global;nt.global===nt&&(n=nt);var tt,rt,et,ut=[],ot={},it=0,ft=ot,at=30,ct=n._,lt=/&(?:amp|lt|gt|quot|#39);/g,pt=/\b__p\+='';/g,st=/\b(__p\+=)''\+/g,vt=/(__e\(.*?\)|\b__t\))\+'';/g,gt=/\w*$/,yt=RegExp("^"+(ot.valueOf+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),ht=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,mt=/<%=([\s\S]+?)%>/g,dt=/($^)/,_t=/[&<>"']/g,bt=/['\n\r\t\u2028\u2029\\]/g,jt="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),wt=Math.ceil,xt=ut.concat,Ot=Math.floor,At=yt.test(At=Object.getPrototypeOf)&&At,St=ot.hasOwnProperty,Et=ut.push,kt=ot.toString,It=yt.test(It=v.bind)&&It,Nt=yt.test(Nt=Array.isArray)&&Nt,Rt=n.isFinite,$t=n.isNaN,Ft=yt.test(Ft=Object.keys)&&Ft,qt=Math.max,Dt=Math.min,Tt=Math.random,Bt="[object Arguments]",Mt="[object Array]",Pt="[object Boolean]",zt="[object Date]",Ct="[object Number]",Kt="[object Object]",Lt="[object RegExp]",Ut="[object String]",Vt=!!n.attachEvent,Gt=It&&!/\n|true/.test(It+Vt),Ht=It&&!Gt,Jt=Ft&&(Vt||Gt),Qt=(Qt={0:1,length:1},ut.splice.call(Qt,0,1),Qt[0]),Wt=Q;
|
||||||
|
(function(){function n(){this.x=1}var t=[];n.prototype={valueOf:1,y:1};for(var r in new n)t.push(r);for(r in arguments)Wt=!r;tt=!/valueOf/.test(t),rt=n.propertyIsEnumerable("prototype"),et="x"!=t[0]})(1);var Xt=arguments.constructor==Object,Yt=!y(arguments),Zt="xx"!="x"[0]+Object("x")[0];try{var nr=kt.call(document)==Kt&&!({toString:0}+"")}catch(tr){}var rr={"[object Function]":X};rr[Bt]=rr[Mt]=rr[Pt]=rr[zt]=rr[Ct]=rr[Kt]=rr[Lt]=rr[Ut]=Q;var er={};er[Mt]=Array,er[Pt]=Boolean,er[zt]=Date,er[Kt]=Object,er[Ct]=Number,er[Lt]=RegExp,er[Ut]=String;
|
||||||
|
var ur={"boolean":X,"function":Q,object:Q,number:X,string:X,undefined:X},or={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};r.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:mt,variable:"",imports:{_:r}};var ir={a:"q,w,h",l:"var a=arguments,b=0,c=typeof h=='number'?2:a.length;while(++b<c){n=a[b];if(n&&r[typeof n]){",h:"if(typeof u[j]=='undefined')u[j]=n[j]",c:"}}"},fr={a:"e,d,x",l:"d=d&&typeof x=='undefined'?d:f(d,x)",b:"typeof o=='number'",h:"if(d(n[j],j,e)===false)return u"},ar={l:"if(!r[typeof n])return u;"+fr.l,b:X},cr=a(fr);
|
||||||
|
Yt&&(y=function(n){return n?St.call(n,"callee"):X});var lr=a(fr,ar,{m:X}),pr=a(fr,ar),sr=Nt||function(n){return Xt&&n instanceof Array||kt.call(n)==Mt},vr=Ft?function(n){return x(n)?rt&&typeof n=="function"||Wt&&n.length&&y(n)?m(n):Ft(n):[]}:m,gr={"&":"&","<":"<",">":">",'"':""","'":"'"},yr=b(gr),hr=a(ir,{l:ir.l.replace(";",";if(c>3&&typeof a[c-2]=='function'){var d=f(a[--c-1],a[c--],2);}else if(c>2&&typeof a[c-1]=='function'){d=a[--c];}"),h:"u[j]=d?d(u[j],n[j]):n[j]"}),mr=a(ir);
|
||||||
|
w(/x/)&&(w=function(n){return n instanceof Function||"[object Function]"==kt.call(n)});var dr=At?function(n){if(!n||typeof n!="object")return X;var t=n.valueOf,r=typeof t=="function"&&(r=At(t))&&At(r);return r?n==r||At(n)==r&&!y(n):h(n)}:h,_r=F,br=N;Gt&&Z&&typeof setImmediate=="function"&&(V=U(setImmediate,n)),r.after=function(n,t){return 1>n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},r.assign=hr,r.at=function(n){var t=-1,r=xt.apply(ut,v(arguments,1)),e=r.length,u=Array(e);for(Zt&&A(n)&&(n=n.split(""));++t<e;)u[t]=n[r[t]];
|
||||||
|
return u},r.bind=U,r.bindAll=function(n){for(var t=xt.apply(ut,arguments),r=1<t.length?0:(t=_(n),-1),e=t.length;++r<e;){var u=t[r];n[u]=U(n[u],n)}return n},r.bindKey=function(n,t){return i(n,t,v(arguments,2))},r.compact=function(n){for(var t=-1,r=n?n.length:0,e=[];++t<r;){var u=n[t];u&&e.push(u)}return e},r.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length;r--;)t=[n[r].apply(this,t)];return t[0]}},r.countBy=function(n,t,r){var e={};return t=f(t,r),$(n,function(n,r,u){r=t(n,r,u)+"",St.call(e,r)?e[r]++:e[r]=1
|
||||||
|
}),e},r.debounce=function(n,t,r){function e(){f=W,r||(o=n.apply(i,u))}var u,o,i,f;return function(){var a=r&&!f;return u=arguments,i=this,clearTimeout(f),f=setTimeout(e,t),a&&(o=n.apply(i,u)),o}},r.defaults=mr,r.defer=V,r.delay=function(n,r){var e=v(arguments,2);return setTimeout(function(){n.apply(t,e)},r)},r.difference=function(n){for(var t=-1,r=n?n.length:0,u=xt.apply(ut,arguments),u=e(u,r),o=[];++t<r;){var i=n[t];u(i)||o.push(i)}return o},r.filter=N,r.flatten=P,r.forEach=$,r.forIn=lr,r.forOwn=pr,r.functions=_,r.groupBy=function(n,t,r){var e={};
|
||||||
|
return t=f(t,r),$(n,function(n,r,u){r=t(n,r,u)+"",(St.call(e,r)?e[r]:e[r]=[]).push(n)}),e},r.initial=function(n,t,r){if(!n)return[];var e=0,u=n.length;if(typeof t!="number"&&t!=W){var o=u;for(t=f(t,r);o--&&t(n[o],o,n);)e++}else e=t==W||r?1:t||e;return v(n,0,Dt(qt(0,u-e),u))},r.intersection=function(n){var t=arguments,r=t.length,u={0:{}},o=-1,i=n?n.length:0,f=100<=i,a=[],c=a;n:for(;++o<i;){var l=n[o];if(f)var p=l+"",p=St.call(u[0],p)?!(c=u[0][p]):c=u[0][p]=[];if(p||0>z(c,l)){f&&c.push(l);for(var s=r;--s;)if(!(u[s]||(u[s]=e(t[s],0,100)))(l))continue n;
|
||||||
|
a.push(l)}}return a},r.invert=b,r.invoke=function(n,t){var r=v(arguments,2),e=-1,u=typeof t=="function",o=n?n.length:0,i=Array(typeof o=="number"?o:0);return $(n,function(n){i[++e]=(u?t:n[t]).apply(n,r)}),i},r.keys=vr,r.map=F,r.max=q,r.memoize=function(n,t){var r={};return function(){var e=(t?t.apply(this,arguments):arguments[0])+"";return St.call(r,e)?r[e]:r[e]=n.apply(this,arguments)}},r.merge=S,r.min=function(n,t,r){var e=1/0,o=e;if(!t&&sr(n)){r=-1;for(var i=n.length;++r<i;){var a=n[r];a<o&&(o=a)
|
||||||
|
}}else t=!t&&A(n)?u:f(t,r),cr(n,function(n,r,u){r=t(n,r,u),r<e&&(e=r,o=n)});return o},r.object=function(n,t){for(var r=-1,e=n?n.length:0,u={};++r<e;){var o=n[r];t?u[o]=t[r]:u[o[0]]=o[1]}return u},r.omit=function(n,t,r){var e=typeof t=="function",u={};if(e)t=f(t,r);else var o=xt.apply(ut,arguments);return lr(n,function(n,r,i){(e?!t(n,r,i):0>z(o,r,1))&&(u[r]=n)}),u},r.once=function(n){var t,r;return function(){return t?r:(t=Q,r=n.apply(this,arguments),n=W,r)}},r.pairs=function(n){for(var t=-1,r=vr(n),e=r.length,u=Array(e);++t<e;){var o=r[t];
|
||||||
|
u[t]=[o,n[o]]}return u},r.partial=function(n){return i(n,v(arguments,1))},r.partialRight=function(n){return i(n,v(arguments,1),W,ft)},r.pick=function(n,t,r){var e={};if(typeof t!="function")for(var u=0,o=xt.apply(ut,arguments),i=x(n)?o.length:0;++u<i;){var a=o[u];a in n&&(e[a]=n[a])}else t=f(t,r),lr(n,function(n,r,u){t(n,r,u)&&(e[r]=n)});return e},r.pluck=_r,r.range=function(n,t,r){n=+n||0,r=+r||1,t==W&&(t=n,n=0);var e=-1;t=qt(0,wt((t-n)/r));for(var u=Array(t);++e<t;)u[e]=n,n+=r;return u},r.reject=function(n,t,r){return t=f(t,r),N(n,function(n,r,e){return!t(n,r,e)
|
||||||
|
})},r.rest=C,r.shuffle=function(n){var t=-1,r=n?n.length:0,e=Array(typeof r=="number"?r:0);return $(n,function(n){var r=Ot(Tt()*(++t+1));e[t]=e[r],e[r]=n}),e},r.sortBy=function(n,t,r){var e=-1,u=n?n.length:0,i=Array(typeof u=="number"?u:0);for(t=f(t,r),$(n,function(n,r,u){i[++e]={a:t(n,r,u),b:e,c:n}}),u=i.length,i.sort(o);u--;)i[u]=i[u].c;return i},r.tap=function(n,t){return t(n),n},r.throttle=function(n,t){function r(){f=new Date,i=W,u=n.apply(o,e)}var e,u,o,i,f=0;return function(){var a=new Date,c=t-(a-f);
|
||||||
|
return e=arguments,o=this,0<c?i||(i=setTimeout(r,c)):(clearTimeout(i),i=W,f=a,u=n.apply(o,e)),u}},r.times=function(n,t,r){n=+n||0;for(var e=-1,u=Array(n);++e<n;)u[e]=t.call(r,e);return u},r.toArray=function(n){return n&&typeof n.length=="number"?Zt&&A(n)?n.split(""):v(n):E(n)},r.union=function(){return L(xt.apply(ut,arguments))},r.uniq=L,r.values=E,r.where=br,r.without=function(n){for(var t=-1,r=n?n.length:0,u=e(arguments,1),o=[];++t<r;){var i=n[t];u(i)||o.push(i)}return o},r.wrap=function(n,t){return function(){var r=[n];
|
||||||
|
return Et.apply(r,arguments),t.apply(this,r)}},r.zip=function(n){for(var t=-1,r=n?q(_r(arguments,"length")):0,e=Array(r);++t<r;)e[t]=_r(arguments,t);return e},r.collect=F,r.drop=C,r.each=$,r.extend=hr,r.methods=_,r.select=N,r.tail=C,r.unique=L,H(r),r.clone=d,r.cloneDeep=function(n,t,r){return d(n,Q,t,r)},r.contains=k,r.escape=function(n){return n==W?"":(n+"").replace(_t,l)},r.every=I,r.find=R,r.has=function(n,t){return n?St.call(n,t):X},r.identity=G,r.indexOf=z,r.isArguments=y,r.isArray=sr,r.isBoolean=function(n){return n===Q||n===X||kt.call(n)==Pt
|
||||||
|
},r.isDate=function(n){return n instanceof Date||kt.call(n)==zt},r.isElement=function(n){return n?1===n.nodeType:X},r.isEmpty=function(n){var t=Q;if(!n)return t;var r=kt.call(n),e=n.length;return r==Mt||r==Ut||r==Bt||Yt&&y(n)||r==Kt&&typeof e=="number"&&w(n.splice)?!e:(pr(n,function(){return t=X}),t)},r.isEqual=j,r.isFinite=function(n){return Rt(n)&&!$t(parseFloat(n))},r.isFunction=w,r.isNaN=function(n){return O(n)&&n!=+n},r.isNull=function(n){return n===W},r.isNumber=O,r.isObject=x,r.isPlainObject=dr,r.isRegExp=function(n){return n instanceof RegExp||kt.call(n)==Lt
|
||||||
|
},r.isString=A,r.isUndefined=function(n){return typeof n=="undefined"},r.lastIndexOf=function(n,t,r){var e=n?n.length:0;for(typeof r=="number"&&(e=(0>r?qt(0,e+r):Dt(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},r.mixin=H,r.noConflict=function(){return n._=ct,this},r.random=function(n,t){return n==W&&t==W&&(t=1),n=+n||0,t==W&&(t=n,n=0),n+Ot(Tt()*((+t||0)-n+1))},r.reduce=D,r.reduceRight=T,r.result=function(n,r){var e=n?n[r]:t;return w(e)?n[r]():e},r.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:vr(n).length
|
||||||
|
},r.some=B,r.sortedIndex=K,r.template=function(n,e,u){var o=r.templateSettings;n||(n=""),u=mr({},u,o);var i,f=mr({},u.imports,o.imports),o=vr(f),f=E(f),a=0,l=u.interpolate||dt,p="__p+='";n.replace(RegExp((u.escape||dt).source+"|"+l.source+"|"+(l===mt?ht:dt).source+"|"+(u.evaluate||dt).source+"|$","g"),function(t,r,e,u,o,f){return e||(e=u),p+=n.slice(a,f).replace(bt,c),r&&(p+="'+__e("+r+")+'"),o&&(i=Q,p+="';"+o+";__p+='"),e&&(p+="'+((__t=("+e+"))==null?'':__t)+'"),a=f+t.length,t}),p+="';\n",l=u=u.variable,l||(u="obj",p="with("+u+"){"+p+"}"),p=(i?p.replace(pt,""):p).replace(st,"$1").replace(vt,"$1;"),p="function("+u+"){"+(l?"":u+"||("+u+"={});")+"var __t,__p='',__e=_.escape"+(i?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":";")+p+"return __p}";
|
||||||
|
try{var s=Function(o,"return "+p).apply(t,f)}catch(v){throw v.source=p,v}return e?s(e):(s.source=p,s)},r.unescape=function(n){return n==W?"":(n+"").replace(lt,g)},r.uniqueId=function(n){var t=++it;return(n==W?"":n+"")+t},r.all=I,r.any=B,r.detect=R,r.foldl=D,r.foldr=T,r.include=k,r.inject=D,pr(r,function(n,t){r.prototype[t]||(r.prototype[t]=function(){var t=[this.__wrapped__];return Et.apply(t,arguments),n.apply(r,t)})}),r.first=M,r.last=function(n,t,r){if(n){var e=0,u=n.length;if(typeof t!="number"&&t!=W){var o=u;
|
||||||
|
for(t=f(t,r);o--&&t(n[o],o,n);)e++}else if(e=t,e==W||r)return n[u-1];return v(n,qt(0,u-e))}},r.take=M,r.head=M,pr(r,function(n,t){r.prototype[t]||(r.prototype[t]=function(t,e){var u=n(this.__wrapped__,t,e);return t==W||e&&typeof t!="function"?u:new r(u)})}),r.VERSION="1.0.2",r.prototype.toString=function(){return this.__wrapped__+""},r.prototype.value=J,r.prototype.valueOf=J,cr(["join","pop","shift"],function(n){var t=ut[n];r.prototype[n]=function(){return t.apply(this.__wrapped__,arguments)}}),cr(["push","reverse","sort","unshift"],function(n){var t=ut[n];
|
||||||
|
r.prototype[n]=function(){return t.apply(this.__wrapped__,arguments),this}}),cr(["concat","slice","splice"],function(n){var t=ut[n];r.prototype[n]=function(){return new r(t.apply(this.__wrapped__,arguments))}}),Qt&&cr(["pop","shift","splice"],function(n){var t=ut[n],e="splice"==n;r.prototype[n]=function(){var n=this.__wrapped__,u=t.apply(n,arguments);return 0===n.length&&delete n[0],e?new r(u):u}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(n._=r,define(function(){return r
|
||||||
|
})):Y?Z?(Z.exports=r)._=r:Y._=r:n._=r})(this);
|
||||||
4983
dist/lodash.js
vendored
Normal file
4983
dist/lodash.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
41
dist/lodash.min.js
vendored
Normal file
41
dist/lodash.min.js
vendored
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Lo-Dash 1.0.2 (Custom Build) lodash.com/license
|
||||||
|
* Build: `lodash modern -o ./dist/lodash.js`
|
||||||
|
* Underscore.js 1.4.4 underscorejs.org/LICENSE
|
||||||
|
*/
|
||||||
|
;(function(n,r){function t(n){return n&&"object"==typeof n&&n.__wrapped__?n:this instanceof t?(this.__wrapped__=n,r):new t(n)}function e(n,r,t){r||(r=0);var e=n.length,u=e-r>=(t||ut);if(u)for(var a={},o=r-1;++o<e;){var i=n[o]+"";(wt.call(a,i)?a[i]:a[i]=[]).push(n[o])}return function(t){if(u){var e=t+"";return wt.call(a,e)&&sr(a[e],t)>-1}return sr(n,t,r)>-1}}function u(n){return n.charCodeAt(0)}function a(n,r){var t=n.index,e=r.index;if(n=n.criteria,r=r.criteria,n!==r){if(n>r||"undefined"==typeof n)return 1;
|
||||||
|
if(n<r||"undefined"==typeof r)return-1}return t<e?-1:1}function o(n,r,t,e){function u(){var f=arguments,l=o?this:r;if(a||(n=r[i]),t.length&&(f=f.length?(f=p(f),e?f.concat(t):t.concat(f)):t),this instanceof u){s.prototype=n.prototype,l=new s,s.prototype=null;var c=n.apply(l,f);return S(c)?c:l}return n.apply(l,f)}var a=E(n),o=!t,i=r;return o&&(t=r),a||(r=n),u}function i(n,r,t){if(null==n)return Br;var e=typeof n;if("function"!=e){if("object"!=e)return function(r){return r[n]};var u=ue(n);return function(r){for(var t=u.length,e=!1;t--&&(e=O(r[u[t]],n[u[t]],et)););return e
|
||||||
|
}}return"undefined"!=typeof r?1===t?function(t){return n.call(r,t)}:2===t?function(t,e){return n.call(r,t,e)}:4===t?function(t,e,u,a){return n.call(r,t,e,u,a)}:function(t,e,u){return n.call(r,t,e,u)}:n}function f(){for(var n,r={isKeysFast:Ut,arrays:"isArray(iterable)",bottom:"",loop:"",top:"",useHas:!0},t=0;n=arguments[t];t++)for(var e in n)r[e]=n[e];var u=r.args;r.firstArg=/^[^,]+/.exec(u)[0];var a=Function("createCallback, hasOwnProperty, isArguments, isArray, isString, objectTypes, nativeKeys","return function("+u+") {\n"+Wt(r)+"\n}");
|
||||||
|
return a(i,wt,v,ee,N,Jt,St)}function l(n){return"\\"+Qt[n]}function c(n){return ae[n]}function s(){}function p(n,r,t){r||(r=0),"undefined"==typeof t&&(t=n?n.length:0);for(var e=-1,u=t-r||0,a=Array(u<0?0:u);++e<u;)a[e]=n[r+e];return a}function g(n){return oe[n]}function v(n){return At.call(n)==Ft}function y(n){var r=!1;if(!n||"object"!=typeof n||v(n))return r;var t=n.constructor;return!E(t)||t instanceof t?(re(n,function(n,t){r=t}),r===!1||wt.call(n,r)):r}function h(n){var r=[];return te(n,function(n,t){r.push(t)
|
||||||
|
}),r}function d(n,t,e,u,a,o){var f=n;if("function"==typeof t&&(u=e,e=t,t=!1),"function"==typeof e){e="undefined"==typeof u?e:i(e,u,1),f=e(f);var l="undefined"!=typeof f;l||(f=n)}var c=S(f);if(c){var s=At.call(f);if(!Vt[s])return f;var g=ee(f)}if(!c||!t)return c&&!l?g?p(f):ie({},f):f;var v=Gt[s];switch(s){case $t:case Pt:return l?f:new v(+f);case qt:case Ct:return l?f:new v(f);case Ht:return l?f:v(f.source,ct.exec(f))}a||(a=[]),o||(o=[]);for(var y=a.length;y--;)if(a[y]==n)return o[y];return l||(f=g?v(f.length):{},g&&(wt.call(n,"index")&&(f.index=n.index),wt.call(n,"input")&&(f.input=n.input))),a.push(n),o.push(f),(g?G:te)(l?f:n,function(n,u){f[u]=d(n,t,e,r,a,o)
|
||||||
|
}),f}function m(n,r,t){return d(n,!0,r,t)}function b(n){var r=[];return re(n,function(n,t){E(n)&&r.push(t)}),r.sort()}function _(n,r){return n?wt.call(n,r):!1}function x(n){for(var r=-1,t=ue(n),e=t.length,u={};++r<e;){var a=t[r];u[n[a]]=a}return u}function w(n){return n===!0||n===!1||At.call(n)==$t}function j(n){return n instanceof Date||At.call(n)==Pt}function A(n){return n?1===n.nodeType:!1}function k(n){var r=!0;if(!n)return r;var t=At.call(n),e=n.length;return t==Nt||t==Ct||t==Ft||t==Bt&&"number"==typeof e&&E(n.splice)?!e:(te(n,function(){return r=!1
|
||||||
|
}),r)}function O(n,t,e,u,a,o){var f=e===et;if(e&&!f){e="undefined"==typeof u?e:i(e,u,2);var l=e(n,t);if("undefined"!=typeof l)return!!l}if(n===t)return 0!==n||1/n==1/t;var c=typeof n,s=typeof t;if(n===n&&(!n||"function"!=c&&"object"!=c)&&(!t||"function"!=s&&"object"!=s))return!1;if(null==n||null==t)return n===t;var p=At.call(n),g=At.call(t);if(p==Ft&&(p=Bt),g==Ft&&(g=Bt),p!=g)return!1;switch(p){case $t:case Pt:return+n==+t;case qt:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case Ht:case Ct:return n==t+""
|
||||||
|
}var v=p==Nt;if(!v){if(n.__wrapped__||t.__wrapped__)return O(n.__wrapped__||n,t.__wrapped__||t,e,u,a,o);if(p!=Bt)return!1;var y=n.constructor,h=t.constructor;if(y!=h&&!(E(y)&&y instanceof y&&E(h)&&h instanceof h))return!1}a||(a=[]),o||(o=[]);for(var d=a.length;d--;)if(a[d]==n)return o[d]==t;var m=0;if(l=!0,a.push(n),o.push(t),v){if(d=n.length,m=t.length,l=m==n.length,!l&&!f)return l;for(;m--;){var b=d,_=t[m];if(f)for(;b--&&!(l=O(n[b],_,e,u,a,o)););else if(!(l=O(n[m],_,e,u,a,o)))break}return l}return re(t,function(t,i,f){return wt.call(f,i)?(m++,l=wt.call(n,i)&&O(n[i],t,e,u,a,o)):r
|
||||||
|
}),l&&!f&&re(n,function(n,t,e){return wt.call(e,t)?l=--m>-1:r}),l}function I(n){return It(n)&&!Et(parseFloat(n))}function E(n){return"function"==typeof n}function S(n){return n?Jt[typeof n]:!1}function L(n){return T(n)&&n!=+n}function R(n){return null===n}function T(n){return"number"==typeof n||At.call(n)==qt}function F(n){return n instanceof RegExp||At.call(n)==Ht}function N(n){return"string"==typeof n||At.call(n)==Ct}function $(n){return"undefined"==typeof n}function P(n,r,t){var e=arguments,u=0,a=2;
|
||||||
|
if(!S(n))return n;if(t===et)var o=e[3],f=e[4],l=e[5];else f=[],l=[],"number"!=typeof t&&(a=e.length),a>3&&"function"==typeof e[a-2]?o=i(e[--a-1],e[a--],2):a>2&&"function"==typeof e[a-1]&&(o=e[--a]);for(;++u<a;)(ee(e[u])?G:te)(e[u],function(r,t){var e,u,a=r,i=n[t];if(r&&((u=ee(r))||le(r))){for(var c=f.length;c--;)if(e=f[c]==r){i=l[c];break}e||(i=u?ee(i)?i:[]:le(i)?i:{},o&&(a=o(i,r),"undefined"!=typeof a&&(i=a)),f.push(r),l.push(i),o||(i=P(i,r,et,o,f,l)))}else o&&(a=o(i,r),"undefined"==typeof a&&(a=r)),"undefined"!=typeof a&&(i=a);
|
||||||
|
n[t]=i});return n}function D(n,r,t){var e="function"==typeof r,u={};if(e)r=i(r,t);else var a=bt.apply(nt,arguments);return re(n,function(n,t,o){(e?!r(n,t,o):sr(a,t,1)<0)&&(u[t]=n)}),u}function q(n){for(var r=-1,t=ue(n),e=t.length,u=Array(e);++r<e;){var a=t[r];u[r]=[a,n[a]]}return u}function B(n,r,t){var e={};if("function"!=typeof r)for(var u=0,a=bt.apply(nt,arguments),o=S(n)?a.length:0;++u<o;){var f=a[u];f in n&&(e[f]=n[f])}else r=i(r,t),re(n,function(n,t,u){r(n,t,u)&&(e[t]=n)});return e}function H(n){for(var r=-1,t=ue(n),e=t.length,u=Array(e);++r<e;)u[r]=n[t[r]];
|
||||||
|
return u}function C(n){for(var r=-1,t=bt.apply(nt,p(arguments,1)),e=t.length,u=Array(e);++r<e;)u[r]=n[t[r]];return u}function K(n,t,e){var u=-1,a=n?n.length:0,o=!1;return e=(e<0?Lt(0,a+e):e)||0,"number"==typeof a?o=(N(n)?n.indexOf(t,e):sr(n,t,e))>-1:ne(n,function(n){return++u<e?r:!(o=n===t)}),o}function M(n,r,t){var e={};return r=i(r,t),G(n,function(n,t,u){t=r(n,t,u)+"",wt.call(e,t)?e[t]++:e[t]=1}),e}function z(n,r,t){var e=!0;if(r=i(r,t),ee(n))for(var u=-1,a=n.length;++u<a&&(e=!!r(n[u],u,n)););else ne(n,function(n,t,u){return e=!!r(n,t,u)
|
||||||
|
});return e}function U(n,r,t){var e=[];if(r=i(r,t),ee(n))for(var u=-1,a=n.length;++u<a;){var o=n[u];r(o,u,n)&&e.push(o)}else ne(n,function(n,t,u){r(n,t,u)&&e.push(n)});return e}function V(n,t,e){var u;return t=i(t,e),G(n,function(n,e,a){return t(n,e,a)?(u=n,!1):r}),u}function G(n,r,t){if(r&&"undefined"==typeof t&&ee(n))for(var e=-1,u=n.length;++e<u&&r(n[e],e,n)!==!1;);else ne(n,r,t);return n}function J(n,r,t){var e={};return r=i(r,t),G(n,function(n,t,u){t=r(n,t,u)+"",(wt.call(e,t)?e[t]:e[t]=[]).push(n)
|
||||||
|
}),e}function Q(n,r){var t=p(arguments,2),e=-1,u="function"==typeof r,a=n?n.length:0,o=Array("number"==typeof a?a:0);return G(n,function(n){o[++e]=(u?r:n[r]).apply(n,t)}),o}function W(n,r,t){var e=-1,u=n?n.length:0,a=Array("number"==typeof u?u:0);if(r=i(r,t),ee(n))for(;++e<u;)a[e]=r(n[e],e,n);else ne(n,function(n,t,u){a[++e]=r(n,t,u)});return a}function X(n,r,t){var e=-1/0,a=e;if(!r&&ee(n))for(var o=-1,f=n.length;++o<f;){var l=n[o];l>a&&(a=l)}else r=!r&&N(n)?u:i(r,t),ne(n,function(n,t,u){var o=r(n,t,u);
|
||||||
|
o>e&&(e=o,a=n)});return a}function Y(n,r,t){var e=1/0,a=e;if(!r&&ee(n))for(var o=-1,f=n.length;++o<f;){var l=n[o];l<a&&(a=l)}else r=!r&&N(n)?u:i(r,t),ne(n,function(n,t,u){var o=r(n,t,u);o<e&&(e=o,a=n)});return a}function Z(n,r,t,e){var u=arguments.length<3;if(r=i(r,e,4),ee(n)){var a=-1,o=n.length;for(u&&(t=n[++a]);++a<o;)t=r(t,n[a],a,n)}else ne(n,function(n,e,a){t=u?(u=!1,n):r(t,n,e,a)});return t}function nr(n,r,t,e){var u=n,a=n?n.length:0,o=arguments.length<3;if("number"!=typeof a){var f=ue(n);a=f.length
|
||||||
|
}return r=i(r,e,4),G(n,function(n,e,i){e=f?f[--a]:--a,t=o?(o=!1,u[e]):r(t,u[e],e,i)}),t}function rr(n,r,t){return r=i(r,t),U(n,function(n,t,e){return!r(n,t,e)})}function tr(n){var r=-1,t=n?n.length:0,e=Array("number"==typeof t?t:0);return G(n,function(n){var t=_t(Tt()*(++r+1));e[r]=e[t],e[t]=n}),e}function er(n){var r=n?n.length:0;return"number"==typeof r?r:ue(n).length}function ur(n,r,t){var e;if(r=i(r,t),ee(n))for(var u=-1,a=n.length;++u<a&&!(e=r(n[u],u,n)););else ne(n,function(n,t,u){return!(e=r(n,t,u))
|
||||||
|
});return!!e}function ar(n,r,t){var e=-1,u=n?n.length:0,o=Array("number"==typeof u?u:0);for(r=i(r,t),G(n,function(n,t,u){o[++e]={criteria:r(n,t,u),index:e,value:n}}),u=o.length,o.sort(a);u--;)o[u]=o[u].value;return o}function or(n){return n&&"number"==typeof n.length?p(n):H(n)}function ir(n){for(var r=-1,t=n?n.length:0,e=[];++r<t;){var u=n[r];u&&e.push(u)}return e}function fr(n){for(var r=-1,t=n?n.length:0,u=bt.apply(nt,arguments),a=e(u,t),o=[];++r<t;){var i=n[r];a(i)||o.push(i)}return o}function lr(n,r,t){if(n){var e=0,u=n.length;
|
||||||
|
if("number"!=typeof r&&null!=r){var a=-1;for(r=i(r,t);++a<u&&r(n[a],a,n);)e++}else if(e=r,null==e||t)return n[0];return p(n,0,Rt(Lt(0,e),u))}}function cr(n,r){for(var t=-1,e=n?n.length:0,u=[];++t<e;){var a=n[t];ee(a)?jt.apply(u,r?a:cr(a)):u.push(a)}return u}function sr(n,r,t){var e=-1,u=n?n.length:0;if("number"==typeof t)e=(t<0?Lt(0,u+t):t||0)-1;else if(t)return e=br(n,r),n[e]===r?e:-1;for(;++e<u;)if(n[e]===r)return e;return-1}function pr(n,r,t){if(!n)return[];var e=0,u=n.length;if("number"!=typeof r&&null!=r){var a=u;
|
||||||
|
for(r=i(r,t);a--&&r(n[a],a,n);)e++}else e=null==r||t?1:r||e;return p(n,0,Rt(Lt(0,u-e),u))}function gr(n){var r=arguments,t=r.length,u={0:{}},a=-1,o=n?n.length:0,i=o>=100,f=[],l=f;n:for(;++a<o;){var c=n[a];if(i)var s=c+"",p=wt.call(u[0],s)?!(l=u[0][s]):l=u[0][s]=[];if(p||sr(l,c)<0){i&&l.push(c);for(var g=t;--g;)if(!(u[g]||(u[g]=e(r[g],0,100)))(c))continue n;f.push(c)}}return f}function vr(n,r,t){if(n){var e=0,u=n.length;if("number"!=typeof r&&null!=r){var a=u;for(r=i(r,t);a--&&r(n[a],a,n);)e++}else if(e=r,null==e||t)return n[u-1];
|
||||||
|
return p(n,Lt(0,u-e))}}function yr(n,r,t){var e=n?n.length:0;for("number"==typeof t&&(e=(t<0?Lt(0,e+t):Rt(t,e-1))+1);e--;)if(n[e]===r)return e;return-1}function hr(n,r){for(var t=-1,e=n?n.length:0,u={};++t<e;){var a=n[t];r?u[a]=r[t]:u[a[0]]=a[1]}return u}function dr(n,r,t){n=+n||0,t=+t||1,null==r&&(r=n,n=0);for(var e=-1,u=Lt(0,mt((r-n)/t)),a=Array(u);++e<u;)a[e]=n,n+=t;return a}function mr(n,r,t){if("number"!=typeof r&&null!=r){var e=0,u=-1,a=n?n.length:0;for(r=i(r,t);++u<a&&r(n[u],u,n);)e++}else e=null==r||t?1:Lt(0,r);
|
||||||
|
return p(n,e)}function br(n,r,t,e){var u=0,a=n?n.length:u;for(t=t?i(t,e,1):Br,r=t(r);u<a;){var o=u+a>>>1;t(n[o])<r?u=o+1:a=o}return u}function _r(){return xr(bt.apply(nt,arguments))}function xr(n,r,t,e){var u=-1,a=n?n.length:0,o=[],f=o;"function"==typeof r&&(e=t,t=r,r=!1);var l=!r&&a>=75;if(l)var c={};for(t&&(f=[],t=i(t,e));++u<a;){var s=n[u],p=t?t(s,u,n):s;if(l)var g=p+"",v=wt.call(c,g)?!(f=c[g]):f=c[g]=[];(r?!u||f[f.length-1]!==p:v||sr(f,p)<0)&&((t||l)&&f.push(p),o.push(s))}return o}function wr(n){for(var r=-1,t=n?n.length:0,u=e(arguments,1),a=[];++r<t;){var o=n[r];
|
||||||
|
u(o)||a.push(o)}return a}function jr(n){for(var r=-1,t=n?X(ce(arguments,"length")):0,e=Array(t);++r<t;)e[r]=ce(arguments,r);return e}function Ar(n,t){return n<1?t():function(){return--n<1?t.apply(this,arguments):r}}function kr(n,r){return zt||kt&&arguments.length>2?kt.call.apply(kt,arguments):o(n,r,p(arguments,2))}function Or(n){for(var r=bt.apply(nt,arguments),t=r.length>1?0:(r=b(n),-1),e=r.length;++t<e;){var u=r[t];n[u]=kr(n[u],n)}return n}function Ir(n,r){return o(n,r,p(arguments,2))}function Er(){var n=arguments;
|
||||||
|
return function(){for(var r=arguments,t=n.length;t--;)r=[n[t].apply(this,r)];return r[0]}}function Sr(n,r,t){function e(){i=null,t||(a=n.apply(o,u))}var u,a,o,i;return function(){var f=t&&!i;return u=arguments,o=this,clearTimeout(i),i=setTimeout(e,r),f&&(a=n.apply(o,u)),a}}function Lr(n,t){var e=p(arguments,2);return setTimeout(function(){n.apply(r,e)},t)}function Rr(n){var t=p(arguments,1);return setTimeout(function(){n.apply(r,t)},1)}function Tr(n,r){var t={};return function(){var e=(r?r.apply(this,arguments):arguments[0])+"";
|
||||||
|
return wt.call(t,e)?t[e]:t[e]=n.apply(this,arguments)}}function Fr(n){var r,t;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}}function Nr(n){return o(n,p(arguments,1))}function $r(n){return o(n,p(arguments,1),null,et)}function Pr(n,r){function t(){i=new Date,o=null,u=n.apply(a,e)}var e,u,a,o,i=0;return function(){var f=new Date,l=r-(f-i);return e=arguments,a=this,l>0?o||(o=setTimeout(t,l)):(clearTimeout(o),o=null,i=f,u=n.apply(a,e)),u}}function Dr(n,r){return function(){var t=[n];
|
||||||
|
return jt.apply(t,arguments),r.apply(this,t)}}function qr(n){return null==n?"":(n+"").replace(yt,c)}function Br(n){return n}function Hr(n){G(b(n),function(r){var e=t[r]=n[r];t.prototype[r]=function(){var n=[this.__wrapped__];return jt.apply(n,arguments),new t(e.apply(t,n))}})}function Cr(){return n._=at,this}function Kr(n,r){return null==n&&null==r&&(r=1),n=+n||0,null==r&&(r=n,n=0),n+_t(Tt()*((+r||0)-n+1))}function Mr(n,t){var e=n?n[t]:r;return E(e)?n[t]():e}function zr(n,e,u){var a=t.templateSettings;
|
||||||
|
n||(n=""),u=fe({},u,a);var o,i=fe({},u.imports,a.imports),f=ue(i),c=H(i),s=0,p=u.interpolate||vt,g="__p += '",v=RegExp((u.escape||vt).source+"|"+p.source+"|"+(p===gt?pt:vt).source+"|"+(u.evaluate||vt).source+"|$","g");n.replace(v,function(r,t,e,u,a,i){return e||(e=u),g+=n.slice(s,i).replace(ht,l),t&&(g+="' +\n__e("+t+") +\n'"),a&&(o=!0,g+="';\n"+a+";\n__p += '"),e&&(g+="' +\n((__t = ("+e+")) == null ? '' : __t) +\n'"),s=i+r.length,r}),g+="';\n";var y=u.variable,h=y;h||(y="obj",g="with ("+y+") {\n"+g+"\n}\n"),g=(o?g.replace(it,""):g).replace(ft,"$1").replace(lt,"$1;"),g="function("+y+") {\n"+(h?"":y+" || ("+y+" = {});\n")+"var __t, __p = '', __e = _.escape"+(o?", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n":";\n")+g+"return __p\n}";
|
||||||
|
var d="\n/*\n//@ sourceURL="+(u.sourceURL||"/lodash/template/source["+dt++ +"]")+"\n*/";try{var m=Function(f,"return "+g+d).apply(r,c)}catch(b){throw b.source=g,b}return e?m(e):(m.source=g,m)}function Ur(n,r,t){n=+n||0;for(var e=-1,u=Array(n);++e<n;)u[e]=r.call(t,e);return u}function Vr(n){return null==n?"":(n+"").replace(ot,g)}function Gr(n){var r=++tt;return(null==n?"":n+"")+r}function Jr(n,r){return r(n),n}function Qr(){return this.__wrapped__+""}function Wr(){return this.__wrapped__}var Xr="object"==typeof exports&&exports,Yr="object"==typeof module&&module&&module.exports==Xr&&module,Zr="object"==typeof global&&global;
|
||||||
|
Zr.global===Zr&&(n=Zr);var nt=[],rt={},tt=0,et=rt,ut=30,at=n._,ot=/&(?:amp|lt|gt|quot|#39);/g,it=/\b__p \+= '';/g,ft=/\b(__p \+=) '' \+/g,lt=/(__e\(.*?\)|\b__t\)) \+\n'';/g,ct=/\w*$/,st=RegExp("^"+(rt.valueOf+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),pt=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,gt=/<%=([\s\S]+?)%>/g,vt=/($^)/,yt=/[&<>"']/g,ht=/['\n\r\t\u2028\u2029\\]/g,dt=0,mt=Math.ceil,bt=nt.concat,_t=Math.floor,xt=st.test(xt=Object.getPrototypeOf)&&xt,wt=rt.hasOwnProperty,jt=nt.push,At=rt.toString,kt=st.test(kt=p.bind)&&kt,Ot=st.test(Ot=Array.isArray)&&Ot,It=n.isFinite,Et=n.isNaN,St=st.test(St=Object.keys)&&St,Lt=Math.max,Rt=Math.min,Tt=Math.random,Ft="[object Arguments]",Nt="[object Array]",$t="[object Boolean]",Pt="[object Date]",Dt="[object Function]",qt="[object Number]",Bt="[object Object]",Ht="[object RegExp]",Ct="[object String]",Kt=!!n.attachEvent,Mt=kt&&!/\n|true/.test(kt+Kt),zt=kt&&!Mt,Ut=St&&(Kt||Mt),Vt={};
|
||||||
|
Vt[Dt]=!1,Vt[Ft]=Vt[Nt]=Vt[$t]=Vt[Pt]=Vt[qt]=Vt[Bt]=Vt[Ht]=Vt[Ct]=!0;var Gt={};Gt[Nt]=Array,Gt[$t]=Boolean,Gt[Pt]=Date,Gt[Bt]=Object,Gt[qt]=Number,Gt[Ht]=RegExp,Gt[Ct]=String;var Jt={"boolean":!1,"function":!0,object:!0,number:!1,string:!1,undefined:!1},Qt={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};t.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:gt,variable:"",imports:{_:t}};var Wt=function(n){var r="var index, iterable = "+n.firstArg+", result = iterable;\nif (!iterable) return result;\n"+n.top+";\n";
|
||||||
|
return n.arrays&&(r+="var length = iterable.length; index = -1;\nif ("+n.arrays+") {\n while (++index < length) {\n "+n.loop+"\n }\n}\nelse { "),n.isKeysFast&&n.useHas?r+="\n var ownIndex = -1,\n ownProps = objectTypes[typeof iterable] ? nativeKeys(iterable) : [],\n length = ownProps.length;\n\n while (++ownIndex < length) {\n index = ownProps[ownIndex];\n "+n.loop+"\n } ":(r+="\n for (index in iterable) {",n.useHas&&(r+="\n if (",n.useHas&&(r+="hasOwnProperty.call(iterable, index)"),r+=") { "),r+=n.loop+"; ",n.useHas&&(r+="\n }"),r+="\n } "),n.arrays&&(r+="\n}"),r+=n.bottom+";\nreturn result"
|
||||||
|
},Xt={args:"object, source, guard",top:"var args = arguments,\n argsIndex = 0,\n argsLength = typeof guard == 'number' ? 2 : args.length;\nwhile (++argsIndex < argsLength) {\n iterable = args[argsIndex];\n if (iterable && objectTypes[typeof iterable]) {",loop:"if (typeof result[index] == 'undefined') result[index] = iterable[index]",bottom:" }\n}"},Yt={args:"collection, callback, thisArg",top:"callback = callback && typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg)",arrays:"typeof length == 'number'",loop:"if (callback(iterable[index], index, collection) === false) return result"},Zt={top:"if (!objectTypes[typeof iterable]) return result;\n"+Yt.top,arrays:!1},ne=f(Yt),re=f(Yt,Zt,{useHas:!1}),te=f(Yt,Zt),ee=Ot||function(n){return n instanceof Array||At.call(n)==Nt
|
||||||
|
},ue=St?function(n){return S(n)?St(n):[]}:h,ae={"&":"&","<":"<",">":">",'"':""","'":"'"},oe=x(ae),ie=f(Xt,{top:Xt.top.replace(";",";\nif (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n var callback = createCallback(args[--argsLength - 1], args[argsLength--], 2);\n} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n callback = args[--argsLength];\n}"),loop:"result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]"}),fe=f(Xt);
|
||||||
|
E(/x/)&&(E=function(n){return n instanceof Function||At.call(n)==Dt});var le=xt?function(n){if(!n||"object"!=typeof n)return!1;var r=n.valueOf,t="function"==typeof r&&(t=xt(r))&&xt(t);return t?n==t||xt(n)==t&&!v(n):y(n)}:y,ce=W,se=U;Mt&&Yr&&"function"==typeof setImmediate&&(Rr=kr(setImmediate,n)),t.after=Ar,t.assign=ie,t.at=C,t.bind=kr,t.bindAll=Or,t.bindKey=Ir,t.compact=ir,t.compose=Er,t.countBy=M,t.debounce=Sr,t.defaults=fe,t.defer=Rr,t.delay=Lr,t.difference=fr,t.filter=U,t.flatten=cr,t.forEach=G,t.forIn=re,t.forOwn=te,t.functions=b,t.groupBy=J,t.initial=pr,t.intersection=gr,t.invert=x,t.invoke=Q,t.keys=ue,t.map=W,t.max=X,t.memoize=Tr,t.merge=P,t.min=Y,t.object=hr,t.omit=D,t.once=Fr,t.pairs=q,t.partial=Nr,t.partialRight=$r,t.pick=B,t.pluck=ce,t.range=dr,t.reject=rr,t.rest=mr,t.shuffle=tr,t.sortBy=ar,t.tap=Jr,t.throttle=Pr,t.times=Ur,t.toArray=or,t.union=_r,t.uniq=xr,t.values=H,t.where=se,t.without=wr,t.wrap=Dr,t.zip=jr,t.collect=W,t.drop=mr,t.each=G,t.extend=ie,t.methods=b,t.select=U,t.tail=mr,t.unique=xr,Hr(t),t.clone=d,t.cloneDeep=m,t.contains=K,t.escape=qr,t.every=z,t.find=V,t.has=_,t.identity=Br,t.indexOf=sr,t.isArguments=v,t.isArray=ee,t.isBoolean=w,t.isDate=j,t.isElement=A,t.isEmpty=k,t.isEqual=O,t.isFinite=I,t.isFunction=E,t.isNaN=L,t.isNull=R,t.isNumber=T,t.isObject=S,t.isPlainObject=le,t.isRegExp=F,t.isString=N,t.isUndefined=$,t.lastIndexOf=yr,t.mixin=Hr,t.noConflict=Cr,t.random=Kr,t.reduce=Z,t.reduceRight=nr,t.result=Mr,t.size=er,t.some=ur,t.sortedIndex=br,t.template=zr,t.unescape=Vr,t.uniqueId=Gr,t.all=z,t.any=ur,t.detect=V,t.foldl=Z,t.foldr=nr,t.include=K,t.inject=Z,te(t,function(n,r){t.prototype[r]||(t.prototype[r]=function(){var r=[this.__wrapped__];
|
||||||
|
return jt.apply(r,arguments),n.apply(t,r)})}),t.first=lr,t.last=vr,t.take=lr,t.head=lr,te(t,function(n,r){t.prototype[r]||(t.prototype[r]=function(r,e){var u=n(this.__wrapped__,r,e);return null==r||e&&"function"!=typeof r?u:new t(u)})}),t.VERSION="1.0.2",t.prototype.toString=Qr,t.prototype.value=Wr,t.prototype.valueOf=Wr,ne(["join","pop","shift"],function(n){var r=nt[n];t.prototype[n]=function(){return r.apply(this.__wrapped__,arguments)}}),ne(["push","reverse","sort","unshift"],function(n){var r=nt[n];
|
||||||
|
t.prototype[n]=function(){return r.apply(this.__wrapped__,arguments),this}}),ne(["concat","slice","splice"],function(n){var r=nt[n];t.prototype[n]=function(){return new t(r.apply(this.__wrapped__,arguments))}}),"function"==typeof define&&"object"==typeof define.amd&&define.amd?(n._=t,define(function(){return t})):Xr?Yr?(Yr.exports=t)._=t:Xr._=t:n._=t})(this);
|
||||||
4307
dist/lodash.underscore.js
vendored
Normal file
4307
dist/lodash.underscore.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
34
dist/lodash.underscore.min.js
vendored
Normal file
34
dist/lodash.underscore.min.js
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Lo-Dash 1.0.2 (Custom Build) lodash.com/license
|
||||||
|
* Build: `lodash underscore -o ./dist/lodash.underscore.js`
|
||||||
|
* Underscore.js 1.4.4 underscorejs.org/LICENSE
|
||||||
|
*/
|
||||||
|
;(function(n,t){function r(n,t){var r;if(n&&qt[typeof n])for(r in t||(t=G),n)if(t(n[r],r,n)===tt)break}function e(n,t,r){if(n){t=t&&typeof r=="undefined"?t:a(t,r);var e=n.length;if(r=-1,typeof e=="number")for(;++r<e&&t(n[r],r,n)!==tt;);else for(r in n)if(pt.call(n,r)&&t(n[r],r,n)===tt)break}}function u(n){return n&&typeof n=="object"&&n.__wrapped__?n:this instanceof u?(this.__wrapped__=n,void 0):new u(n)}function o(n,t){var r=n.b,e=t.b;if(n=n.a,t=t.a,n!==t){if(n>t||typeof n=="undefined")return 1;if(n<t||typeof t=="undefined")return-1
|
||||||
|
}return r<e?-1:1}function i(n,t,r){function e(){var a=arguments,f=o?this:t;return u||(n=t[i]),r.length&&(a=a.length?(a=p(a),r.concat(a)):r),this instanceof e?(l.prototype=n.prototype,f=new l,l.prototype=K,a=n.apply(f,a),w(a)?a:f):n.apply(f,a)}var u=j(n),o=!r,i=t;return o&&(r=t),u||(t=n),e}function a(n,t,r){if(n==K)return G;var e=typeof n;if("function"!=e){if("object"!=e)return function(t){return t[n]};var u=Dt(n);return function(t){for(var r=u.length,e=L;r--&&(e=t[u[r]]===n[u[r]]););return e}}return typeof t!="undefined"?1===r?function(r){return n.call(t,r)
|
||||||
|
}:2===r?function(r,e){return n.call(t,r,e)}:4===r?function(r,e,u,o){return n.call(t,r,e,u,o)}:function(r,e,u){return n.call(t,r,e,u)}:n}function f(n){return"\\"+It[n]}function c(n){return Mt[n]}function l(){}function p(n,t,r){t||(t=0),typeof r=="undefined"&&(r=n?n.length:0);var e=-1;r=r-t||0;for(var u=Array(0>r?0:r);++e<r;)u[e]=n[t+e];return u}function s(n){return $t[n]}function v(n){return vt.call(n)==wt}function h(n){var t,r=[],e=function(n,t){r.push(t)};if(n&&qt[typeof n])for(t in e||(e=G),n)if(pt.call(n,t)&&e(n[t],t,n)===tt)break;
|
||||||
|
return r}function g(n){if(!n)return n;for(var t=1,r=arguments.length;t<r;t++){var e=arguments[t];if(e)for(var u in e)n[u]=e[u]}return n}function y(n){if(!n)return n;for(var t=1,r=arguments.length;t<r;t++){var e=arguments[t];if(e)for(var u in e)n[u]==K&&(n[u]=e[u])}return n}function m(n){var t=[];return r(n,function(n,r){j(n)&&t.push(r)}),t.sort()}function _(n){for(var t=-1,r=Dt(n),e=r.length,u={};++t<e;){var o=r[t];u[n[o]]=o}return u}function d(n){if(!n)return J;if(Bt(n)||x(n))return!n.length;for(var t in n)if(pt.call(n,t))return L;
|
||||||
|
return J}function b(n,t,e,u){if(n===t)return 0!==n||1/n==1/t;var o=typeof n,i=typeof t;if(n===n&&(!n||"function"!=o&&"object"!=o)&&(!t||"function"!=i&&"object"!=i))return L;if(n==K||t==K)return n===t;if(i=vt.call(n),o=vt.call(t),i!=o)return L;switch(i){case xt:case Et:return+n==+t;case Ot:return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case Nt:case kt:return n==t+""}if(o=i==At,!o){if(n.__wrapped__||t.__wrapped__)return b(n.__wrapped__||n,t.__wrapped__||t,e,u);if(i!=St)return L;var i=n.constructor,a=t.constructor;
|
||||||
|
if(i!=a&&(!j(i)||!(i instanceof i&&j(a)&&a instanceof a)))return L}for(e||(e=[]),u||(u=[]),i=e.length;i--;)if(e[i]==n)return u[i]==t;var f=J,c=0;if(e.push(n),u.push(t),o){if(c=t.length,f=c==n.length)for(;c--&&(f=b(n[c],t[c],e,u)););return f}return r(t,function(t,r,o){return pt.call(o,r)?(c++,!(f=pt.call(n,r)&&b(n[r],t,e,u))&&tt):void 0}),f&&r(n,function(n,t,r){return pt.call(r,t)?!(f=-1<--c)&&tt:void 0}),f}function j(n){return typeof n=="function"}function w(n){return n?qt[typeof n]:L}function A(n){return typeof n=="number"||vt.call(n)==Ot
|
||||||
|
}function x(n){return typeof n=="string"||vt.call(n)==kt}function E(n){for(var t=-1,r=Dt(n),e=r.length,u=Array(e);++t<e;)u[t]=n[r[t]];return u}function O(n,t){var r=L;return typeof(n?n.length:0)=="number"?r=-1<z(n,t):e(n,function(n){return(r=n===t)&&tt}),r}function S(n,t,r){var u=J;if(t=a(t,r),Bt(n)){r=-1;for(var o=n.length;++r<o&&(u=!!t(n[r],r,n)););}else e(n,function(n,r,e){return!(u=!!t(n,r,e))&&tt});return u}function N(n,t,r){var u=[];if(t=a(t,r),Bt(n)){r=-1;for(var o=n.length;++r<o;){var i=n[r];
|
||||||
|
t(i,r,n)&&u.push(i)}}else e(n,function(n,r,e){t(n,r,e)&&u.push(n)});return u}function k(n,t,r){var e;return t=a(t,r),F(n,function(n,r,u){return t(n,r,u)?(e=n,tt):void 0}),e}function F(n,t,r){if(t&&typeof r=="undefined"&&Bt(n)){r=-1;for(var u=n.length;++r<u&&t(n[r],r,n)!==tt;);}else e(n,t,r)}function R(n,t,r){var u=-1,o=n?n.length:0,i=Array(typeof o=="number"?o:0);if(t=a(t,r),Bt(n))for(;++u<o;)i[u]=t(n[u],u,n);else e(n,function(n,r,e){i[++u]=t(n,r,e)});return i}function T(n,t,r){var u=-1/0,o=u;if(!t&&Bt(n)){r=-1;
|
||||||
|
for(var i=n.length;++r<i;){var f=n[r];f>o&&(o=f)}}else t=a(t,r),e(n,function(n,r,e){r=t(n,r,e),r>u&&(u=r,o=n)});return o}function q(n,t,r,u){var o=3>arguments.length;if(t=a(t,u,4),Bt(n)){var i=-1,f=n.length;for(o&&(r=n[++i]);++i<f;)r=t(r,n[i],i,n)}else e(n,function(n,e,u){r=o?(o=L,n):t(r,n,e,u)});return r}function I(n,t,r,e){var u=n?n.length:0,o=3>arguments.length;if(typeof u!="number")var i=Dt(n),u=i.length;return t=a(t,e,4),F(n,function(e,a,f){a=i?i[--u]:--u,r=o?(o=L,n[a]):t(r,n[a],a,f)}),r}function B(n,t,r){var u;
|
||||||
|
if(t=a(t,r),Bt(n)){r=-1;for(var o=n.length;++r<o&&!(u=t(n[r],r,n)););}else e(n,function(n,r,e){return(u=t(n,r,e))&&tt});return!!u}function D(n,t,r){return r&&d(t)?K:(r?k:N)(n,t)}function M(n,t,r){if(n){var e=0,u=n.length;if(typeof t!="number"&&t!=K){var o=-1;for(t=a(t,r);++o<u&&t(n[o],o,n);)e++}else if(e=t,e==K||r)return n[0];return p(n,0,bt(dt(0,e),u))}}function $(n,t){for(var r=-1,e=n?n.length:0,u=[];++r<e;){var o=n[r];Bt(o)?st.apply(u,t?o:$(o)):u.push(o)}return u}function z(n,t,r){var e=-1,u=n?n.length:0;
|
||||||
|
if(typeof r=="number")e=(0>r?dt(0,u+r):r||0)-1;else if(r)return e=P(n,t),n[e]===t?e:-1;for(;++e<u;)if(n[e]===t)return e;return-1}function C(n,t,r){if(typeof t!="number"&&t!=K){var e=0,u=-1,o=n?n.length:0;for(t=a(t,r);++u<o&&t(n[u],u,n);)e++}else e=t==K||r?1:dt(0,t);return p(n,e)}function P(n,t,r,e){var u=0,o=n?n.length:u;for(r=r?a(r,e,1):G,t=r(t);u<o;)e=u+o>>>1,r(n[e])<t?u=e+1:o=e;return u}function U(n,t,r,e){var u=-1,o=n?n.length:0,i=[],f=i;for(typeof t=="function"&&(e=r,r=t,t=L),r&&(f=[],r=a(r,e));++u<o;){e=n[u];
|
||||||
|
var c=r?r(e,u,n):e;(t?!u||f[f.length-1]!==c:0>z(f,c))&&(r&&f.push(c),i.push(e))}return i}function V(n,t){return Ft||ht&&2<arguments.length?ht.call.apply(ht,arguments):i(n,t,p(arguments,2))}function W(n){var r=p(arguments,1);return setTimeout(function(){n.apply(t,r)},1)}function G(n){return n}function H(n){F(m(n),function(t){var r=u[t]=n[t];u.prototype[t]=function(){var n=[this.__wrapped__];return st.apply(n,arguments),n=r.apply(u,n),this.__chain__&&(n=new u(n),n.__chain__=J),n}})}var J=!0,K=null,L=!1,Q=typeof exports=="object"&&exports,X=typeof module=="object"&&module&&module.exports==Q&&module,Y=typeof global=="object"&&global;
|
||||||
|
Y.global===Y&&(n=Y);var Z=[],Y={},nt=0,tt=Y,rt=n._,et=/&(?:amp|lt|gt|quot|#39);/g,ut=RegExp("^"+(Y.valueOf+"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),ot=/($^)/,it=/[&<>"']/g,at=/['\n\r\t\u2028\u2029\\]/g,ft=Math.ceil,ct=Z.concat,lt=Math.floor,pt=Y.hasOwnProperty,st=Z.push,vt=Y.toString,ht=ut.test(ht=p.bind)&&ht,gt=ut.test(gt=Array.isArray)&>,yt=n.isFinite,mt=n.isNaN,_t=ut.test(_t=Object.keys)&&_t,dt=Math.max,bt=Math.min,jt=Math.random,wt="[object Arguments]",At="[object Array]",xt="[object Boolean]",Et="[object Date]",Ot="[object Number]",St="[object Object]",Nt="[object RegExp]",kt="[object String]",Y=!!n.attachEvent,Y=ht&&!/\n|true/.test(ht+Y),Ft=ht&&!Y,Rt=(Rt={0:1,length:1},Z.splice.call(Rt,0,1),Rt[0]),Tt=arguments.constructor==Object,qt={"boolean":L,"function":J,object:J,number:L,string:L,undefined:L},It={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};
|
||||||
|
u.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},v(arguments)||(v=function(n){return n?pt.call(n,"callee"):L});var Bt=gt||function(n){return Tt&&n instanceof Array||vt.call(n)==At},Dt=_t?function(n){return w(n)?_t(n):[]}:h,Mt={"&":"&","<":"<",">":">",'"':""","'":"'"},$t=_(Mt);j(/x/)&&(j=function(n){return n instanceof Function||"[object Function]"==vt.call(n)});var zt=R;Y&&X&&typeof setImmediate=="function"&&(W=V(setImmediate,n)),u.after=function(n,t){return 1>n?t():function(){return 1>--n?t.apply(this,arguments):void 0
|
||||||
|
}},u.bind=V,u.bindAll=function(n){for(var t=ct.apply(Z,arguments),r=1<t.length?0:(t=m(n),-1),e=t.length;++r<e;){var u=t[r];n[u]=V(n[u],n)}return n},u.compact=function(n){for(var t=-1,r=n?n.length:0,e=[];++t<r;){var u=n[t];u&&e.push(u)}return e},u.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length;r--;)t=[n[r].apply(this,t)];return t[0]}},u.countBy=function(n,t,r){var e={};return t=a(t,r),F(n,function(n,r,u){r=t(n,r,u)+"",pt.call(e,r)?e[r]++:e[r]=1}),e},u.debounce=function(n,t,r){function e(){a=K,r||(o=n.apply(i,u))
|
||||||
|
}var u,o,i,a;return function(){var f=r&&!a;return u=arguments,i=this,clearTimeout(a),a=setTimeout(e,t),f&&(o=n.apply(i,u)),o}},u.defaults=y,u.defer=W,u.delay=function(n,r){var e=p(arguments,2);return setTimeout(function(){n.apply(t,e)},r)},u.difference=function(n){for(var t=-1,r=n.length,e=ct.apply(Z,arguments),u=[];++t<r;){var o=n[t];0>z(e,o,r)&&u.push(o)}return u},u.filter=N,u.flatten=$,u.forEach=F,u.functions=m,u.groupBy=function(n,t,r){var e={};return t=a(t,r),F(n,function(n,r,u){r=t(n,r,u)+"",(pt.call(e,r)?e[r]:e[r]=[]).push(n)
|
||||||
|
}),e},u.initial=function(n,t,r){if(!n)return[];var e=0,u=n.length;if(typeof t!="number"&&t!=K){var o=u;for(t=a(t,r);o--&&t(n[o],o,n);)e++}else e=t==K||r?1:t||e;return p(n,0,bt(dt(0,u-e),u))},u.intersection=function(n){var t=arguments,r=t.length,e=-1,u=n?n.length:0,o=[];n:for(;++e<u;){var i=n[e];if(0>z(o,i)){for(var a=r;--a;)if(0>z(t[a],i))continue n;o.push(i)}}return o},u.invert=_,u.invoke=function(n,t){var r=p(arguments,2),e=-1,u=typeof t=="function",o=n?n.length:0,i=Array(typeof o=="number"?o:0);
|
||||||
|
return F(n,function(n){i[++e]=(u?t:n[t]).apply(n,r)}),i},u.keys=Dt,u.map=R,u.max=T,u.memoize=function(n,t){var r={};return function(){var e=(t?t.apply(this,arguments):arguments[0])+"";return pt.call(r,e)?r[e]:r[e]=n.apply(this,arguments)}},u.min=function(n,t,r){var u=1/0,o=u;if(!t&&Bt(n)){r=-1;for(var i=n.length;++r<i;){var f=n[r];f<o&&(o=f)}}else t=a(t,r),e(n,function(n,r,e){r=t(n,r,e),r<u&&(u=r,o=n)});return o},u.object=function(n,t){for(var r=-1,e=n?n.length:0,u={};++r<e;){var o=n[r];t?u[o]=t[r]:u[o[0]]=o[1]
|
||||||
|
}return u},u.omit=function(n){var t=ct.apply(Z,arguments),e={};return r(n,function(n,r){0>z(t,r,1)&&(e[r]=n)}),e},u.once=function(n){var t,r;return function(){return t?r:(t=J,r=n.apply(this,arguments),n=K,r)}},u.pairs=function(n){for(var t=-1,r=Dt(n),e=r.length,u=Array(e);++t<e;){var o=r[t];u[t]=[o,n[o]]}return u},u.partial=function(n){return i(n,p(arguments,1))},u.pick=function(n){for(var t=0,r=ct.apply(Z,arguments),e=r.length,u={};++t<e;){var o=r[t];o in n&&(u[o]=n[o])}return u},u.pluck=zt,u.range=function(n,t,r){n=+n||0,r=+r||1,t==K&&(t=n,n=0);
|
||||||
|
var e=-1;t=dt(0,ft((t-n)/r));for(var u=Array(t);++e<t;)u[e]=n,n+=r;return u},u.reject=function(n,t,r){return t=a(t,r),N(n,function(n,r,e){return!t(n,r,e)})},u.rest=C,u.shuffle=function(n){var t=-1,r=n?n.length:0,e=Array(typeof r=="number"?r:0);return F(n,function(n){var r=lt(jt()*(++t+1));e[t]=e[r],e[r]=n}),e},u.sortBy=function(n,t,r){var e=-1,u=n?n.length:0,i=Array(typeof u=="number"?u:0);for(t=a(t,r),F(n,function(n,r,u){i[++e]={a:t(n,r,u),b:e,c:n}}),u=i.length,i.sort(o);u--;)i[u]=i[u].c;return i
|
||||||
|
},u.tap=function(n,t){return t(n),n},u.throttle=function(n,t){function r(){a=new Date,i=K,u=n.apply(o,e)}var e,u,o,i,a=0;return function(){var f=new Date,c=t-(f-a);return e=arguments,o=this,0<c?i||(i=setTimeout(r,c)):(clearTimeout(i),i=K,a=f,u=n.apply(o,e)),u}},u.times=function(n,t,r){n=+n||0;for(var e=-1,u=Array(n);++e<n;)u[e]=t.call(r,e);return u},u.toArray=function(n){return n&&typeof n.length=="number"?p(n):E(n)},u.union=function(){return U(ct.apply(Z,arguments))},u.uniq=U,u.values=E,u.where=D,u.without=function(n){for(var t=-1,r=n.length,e=[];++t<r;){var u=n[t];
|
||||||
|
0>z(arguments,u,1)&&e.push(u)}return e},u.wrap=function(n,t){return function(){var r=[n];return st.apply(r,arguments),t.apply(this,r)}},u.zip=function(n){for(var t=-1,r=n?T(zt(arguments,"length")):0,e=Array(r);++t<r;)e[t]=zt(arguments,t);return e},u.collect=R,u.drop=C,u.each=F,u.extend=g,u.methods=m,u.select=N,u.tail=C,u.unique=U,u.clone=function(n){return w(n)?Bt(n)?p(n):g({},n):n},u.contains=O,u.escape=function(n){return n==K?"":(n+"").replace(it,c)},u.every=S,u.find=k,u.findWhere=function(n,t){return D(n,t,J)
|
||||||
|
},u.has=function(n,t){return n?pt.call(n,t):L},u.identity=G,u.indexOf=z,u.isArguments=v,u.isArray=Bt,u.isBoolean=function(n){return n===J||n===L||vt.call(n)==xt},u.isDate=function(n){return n instanceof Date||vt.call(n)==Et},u.isElement=function(n){return n?1===n.nodeType:L},u.isEmpty=d,u.isEqual=b,u.isFinite=function(n){return yt(n)&&!mt(parseFloat(n))},u.isFunction=j,u.isNaN=function(n){return A(n)&&n!=+n},u.isNull=function(n){return n===K},u.isNumber=A,u.isObject=w,u.isRegExp=function(n){return n instanceof RegExp||vt.call(n)==Nt
|
||||||
|
},u.isString=x,u.isUndefined=function(n){return typeof n=="undefined"},u.lastIndexOf=function(n,t,r){var e=n?n.length:0;for(typeof r=="number"&&(e=(0>r?dt(0,e+r):bt(r,e-1))+1);e--;)if(n[e]===t)return e;return-1},u.mixin=H,u.noConflict=function(){return n._=rt,this},u.random=function(n,t){return n==K&&t==K&&(t=1),n=+n||0,t==K&&(t=n,n=0),n+lt(jt()*((+t||0)-n+1))},u.reduce=q,u.reduceRight=I,u.result=function(n,t){var r=n?n[t]:K;return j(r)?n[t]():r},u.size=function(n){var t=n?n.length:0;return typeof t=="number"?t:Dt(n).length
|
||||||
|
},u.some=B,u.sortedIndex=P,u.template=function(n,t,r){n||(n=""),r=y({},r,u.templateSettings);var e=0,o="__p+='",i=r.variable;n.replace(RegExp((r.escape||ot).source+"|"+(r.interpolate||ot).source+"|"+(r.evaluate||ot).source+"|$","g"),function(t,r,u,i,a){return o+=n.slice(e,a).replace(at,f),r&&(o+="'+_['escape']("+r+")+'"),i&&(o+="';"+i+";__p+='"),u&&(o+="'+((__t=("+u+"))==null?'':__t)+'"),e=a+t.length,t}),o+="';\n",i||(i="obj",o="with("+i+"||{}){"+o+"}"),o="function("+i+"){var __t,__p='',__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}"+o+"return __p}";
|
||||||
|
try{var a=Function("_","return "+o)(u)}catch(c){throw c.source=o,c}return t?a(t):(a.source=o,a)},u.unescape=function(n){return n==K?"":(n+"").replace(et,s)},u.uniqueId=function(n){var t=++nt+"";return n?n+t:t},u.all=S,u.any=B,u.detect=k,u.foldl=q,u.foldr=I,u.include=O,u.inject=q,u.first=M,u.last=function(n,t,r){if(n){var e=0,u=n.length;if(typeof t!="number"&&t!=K){var o=u;for(t=a(t,r);o--&&t(n[o],o,n);)e++}else if(e=t,e==K||r)return n[u-1];return p(n,dt(0,u-e))}},u.take=M,u.head=M,u.chain=function(n){return n=new u(n),n.__chain__=J,n
|
||||||
|
},u.VERSION="1.0.2",H(u),u.prototype.chain=function(){return this.__chain__=J,this},u.prototype.value=function(){return this.__wrapped__},e("pop push reverse shift sort splice unshift".split(" "),function(n){var t=Z[n];u.prototype[n]=function(){var n=this.__wrapped__;return t.apply(n,arguments),Rt&&0===n.length&&delete n[0],this}}),e(["concat","join","slice"],function(n){var t=Z[n];u.prototype[n]=function(){var n=t.apply(this.__wrapped__,arguments);return this.__chain__&&(n=new u(n),n.__chain__=J),n
|
||||||
|
}}),Q?X?(X.exports=u)._=u:Q._=u:n._=u})(this);
|
||||||
5374
doc/README.md
5374
doc/README.md
File diff suppressed because it is too large
Load Diff
@@ -1,35 +1,38 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
// cleanup requested filepath
|
// cleanup requested file path
|
||||||
$file = isset($_GET['f']) ? $_GET['f'] : 'lodash';
|
$filePath = isset($_GET['f']) ? $_GET['f'] : 'lodash';
|
||||||
$file = preg_replace('#(\.*[\/])+#', '', $file);
|
$filePath = preg_replace('#(\.*[\/])+#', '', $filePath);
|
||||||
$file .= preg_match('/\.[a-z]+$/', $file) ? '' : '.js';
|
$filePath .= preg_match('/\.[a-z]+$/', $filePath) ? '' : '.js';
|
||||||
|
|
||||||
// output filename
|
// output filename
|
||||||
if (isset($_GET['o'])) {
|
if (isset($_GET['o'])) {
|
||||||
$output = $_GET['o'];
|
$outputName = $_GET['o'];
|
||||||
} else if (isset($_SERVER['argv'][1])) {
|
} else if (isset($_SERVER['argv'][1])) {
|
||||||
$output = $_SERVER['argv'][1];
|
$outputName = $_SERVER['argv'][1];
|
||||||
} else {
|
} else {
|
||||||
$output = basename($file);
|
$outputName = basename($filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
require('../vendor/docdown/docdown.php');
|
require('../vendor/docdown/docdown.php');
|
||||||
|
|
||||||
|
// get package version
|
||||||
|
$version = json_decode(file_get_contents('../package.json'))->version;
|
||||||
|
|
||||||
// generate Markdown
|
// generate Markdown
|
||||||
$markdown = docdown(array(
|
$markdown = docdown(array(
|
||||||
'path' => '../' . $file,
|
'path' => '../' . $filePath,
|
||||||
'title' => 'Lo-Dash <sup>v0.4.2</sup>',
|
'title' => '<a href="http://lodash.com/">Lo-Dash</a> <span>v' . $version . '</span>',
|
||||||
'url' => 'https://github.com/bestiejs/lodash/blob/master/lodash.js'
|
'toc' => 'categories',
|
||||||
|
'url' => 'https://github.com/lodash/lodash/blob/' . $version . '/lodash.js'
|
||||||
));
|
));
|
||||||
|
|
||||||
// save to a .md file
|
// save to a `.md` file
|
||||||
file_put_contents($output . '.md', $markdown);
|
file_put_contents($outputName . '.md', $markdown);
|
||||||
|
|
||||||
// print
|
// print
|
||||||
header('Content-Type: text/plain;charset=utf-8');
|
header('Content-Type: text/plain;charset=utf-8');
|
||||||
echo $markdown . PHP_EOL;
|
echo $markdown . PHP_EOL;
|
||||||
|
?>
|
||||||
?>
|
|
||||||
|
|||||||
35
lodash.min.js
vendored
35
lodash.min.js
vendored
@@ -1,35 +0,0 @@
|
|||||||
/*!
|
|
||||||
Lo-Dash 0.4.2 lodash.com/license
|
|
||||||
Underscore.js 1.3.3 github.com/documentcloud/underscore/blob/master/LICENSE
|
|
||||||
*/
|
|
||||||
;(function(e,t){"use strict";function s(e){return new o(e)}function o(e){if(e&&e._wrapped)return e;this._wrapped=e}function u(e,t,n){t||(t=0);var r=e.length,i=r-t>=(n||30),s=i?{}:e;if(i)for(var o=t-1;++o<r;)n=e[o]+"",(Y.call(s,n)?s[n]:s[n]=[]).push(e[o]);return function(e){if(i){var n=e+"";return Y.call(s,n)&&-1<E(s[n],e)}return-1<E(s,e,t)}}function a(){for(var e,t,n,s=-1,o=arguments.length,u={e:"",f:"",j:"",p:"",c:{d:""},m:{d:""}};++s<o;)for(t in e=arguments[s],e)n=(n=e[t])==r?"":n,/d|i/.test(t)?
|
|
||||||
("string"==typeof n&&(n={b:n,l:n}),u.c[t]=n.b,u.m[t]=n.l):u[t]=n;e=u.a,t=/^[^,]+/.exec(e)[0],u.g=t,u.h=mt,u.k=wt,u.o=J,u.q=u.q!==i,u.r=u.r!==i,"n"in u||(u.n=yt),u.f||(u.f="if(!"+t+")return D");if("g"!=t||!u.c.i)u.c=r;t="",u.r&&(t+="'use strict';"),t+="var n,p="+u.g+",D",u.j&&(t+="="+u.j),t+=";"+u.f+";"+u.p+";",u.c&&(t+="var s=p.length;n=-1;",u.m&&(t+="if(s===s>>>0){"),u.n&&(t+="if(J.call(p)==G){p=p.split('')}"),t+=u.c.d+";while(++n<s){"+u.c.i+"}",u.m&&(t+="}"));if(u.m){u.c&&(t+="else{"),u.h||(t+="var E=typeof p=='function'&&C.call(p,'prototype');"
|
|
||||||
),u.k&&u.q?t+="var A=u(p),z=-1,s=A.length;"+u.m.d+";while(++z<s){n=A[z];if(!(E&&n=='prototype')){"+u.m.i+"}}":(t+=u.m.d+";for(n in p){",u.h?(u.q&&(t+="if(l.call(p,n)){"),t+=u.m.i+";",u.q&&(t+="}")):(t+="if(!(E&&n=='prototype')",u.q&&(t+="&&l.call(p,n)"),t+="){"+u.m.i+"}"),t+="}");if(u.h){t+="var i=p.constructor;";for(n=0;7>n;n++)t+="n='"+u.o[n]+"';if(","constructor"==u.o[n]&&(t+="!(i&&i.prototype===p)&&"),t+="l.call(p,n)){"+u.m.i+"}"}u.c&&(t+="}")}return t+=u.e+";return D",Function("c,d,h,j,l,m,r,x,u,C,F,G,J"
|
|
||||||
,"return function("+e+"){"+t+"}")(ut,C,f,lt,Y,L,p,St,ot,et,tt,pt,nt)}function f(e,n){return e=e.a,n=n.a,e===t?1:n===t?-1:e<n?-1:e>n?1:0}function l(e,t){return Q[t]}function c(e){return"\\"+xt[e]}function h(e){return Et[e]}function p(e,t){return function(n,r,i){return e.call(t,n,r,i)}}function d(){}function v(e,t){if(I.test(t))return"<e%-"+t+"%>";var n=Q.length;return Q[n]="'+__e("+t+")+'",K+n}function m(e,t,n,r){return e=Q.length,t?Q[e]="';"+t+";__p+='":n?Q[e]="'+__e("+n+")+'":r&&(Q[e]="'+((__t=("+
|
|
||||||
r+"))==null?'':__t)+'"),K+e}function g(e,t){if(I.test(t))return"<e%="+t+"%>";var n=Q.length;return Q[n]="'+((__t=("+t+"))==null?'':__t)+'",K+n}function y(e,t,n,r){if(!e)return n;var i=e.length,s=3>arguments.length;r&&(t=p(t,r));if(i===i>>>0){var o=yt&&nt.call(e)==pt?e.split(""):e;for(i&&s&&(n=o[--i]);i--;)n=t(n,o[i],i,e);return n}o=Zt(e);for((i=o.length)&&s&&(n=e[o[--i]]);i--;)s=o[i],n=t(n,e[s],s,e);return n}function b(e,t,n){if(e)return t==r||n?e[0]:tt.call(e,0,t)}function w(e,t){var n=[];if(!e)
|
|
||||||
return n;for(var r,i=-1,s=e.length;++i<s;)r=e[i],Gt(r)?Z.apply(n,t?r:w(r)):n.push(r);return n}function E(e,t,n){if(!e)return-1;var r=-1,i=e.length;if(n){if("number"!=typeof n)return r=T(e,t),e[r]===t?r:-1;r=(0>n?Math.max(0,i+n):n)-1}for(;++r<i;)if(e[r]===t)return r;return-1}function S(e,t,n){var r=-Infinity,i=r;if(!e)return i;var s=-1,o=e.length;if(!t){for(;++s<o;)e[s]>i&&(i=e[s]);return i}for(n&&(t=p(t,n));++s<o;)n=t(e[s],s,e),n>r&&(r=n,i=e[s]);return i}function x(e,t,n){return e?tt.call(e,t==r||
|
|
||||||
n?1:t):[]}function T(e,t,n,r){if(!e)return 0;var i=0,s=e.length;if(n){r&&(n=C(n,r));for(t=n(t);i<s;)r=i+s>>>1,n(e[r])<t?i=r+1:s=r}else for(;i<s;)r=i+s>>>1,e[r]<t?i=r+1:s=r;return i}function N(e,t,n,r){var s=[];if(!e)return s;var o=-1,u=e.length,a=[];"function"==typeof t&&(r=n,n=t,t=i);for(n?r&&(n=p(n,r)):n=L;++o<u;)if(r=n(e[o],o,e),t?!o||a[a.length-1]!==r:0>E(a,r))a.push(r),s.push(e[o]);return s}function C(e,t){function n(){var o=arguments,u=t;return i||(e=t[r]),s.length&&(o=o.length?G.apply(s,o)
|
|
||||||
:s),this instanceof n?(d.prototype=e.prototype,u=new d,(o=e.apply(u,o))&&St[typeof o]?o:u):e.apply(u,o)}var r,i=nt.call(e)==lt;if(i){if(bt||rt&&2<arguments.length)return rt.call.apply(rt,arguments)}else r=t,t=e;var s=tt.call(arguments,2);return n}function k(e,t,s){s||(s=[]);if(e===t)return 0!==e||1/e==1/t;if(e==r||t==r)return e===t;e._chain&&(e=e._wrapped),t._chain&&(t=t._wrapped);if(e.isEqual&&nt.call(e.isEqual)==lt)return e.isEqual(t);if(t.isEqual&&nt.call(t.isEqual)==lt)return t.isEqual(e);var o=
|
|
||||||
nt.call(e);if(o!=nt.call(t))return i;switch(o){case pt:return e==""+t;case ct:return e!=+e?t!=+t:0==e?1/e==1/t:e==+t;case at:case ft:return+e==+t;case ht:return e.source==t.source&&e.global==t.global&&e.multiline==t.multiline&&e.ignoreCase==t.ignoreCase}if("object"!=typeof e||"object"!=typeof t)return i;for(var u=s.length;u--;)if(s[u]==e)return n;var u=-1,a=n,f=0;s.push(e);if(o==ut){if(f=e.length,a=f==t.length)for(;f--&&(a=k(e[f],t[f],s)););}else{if("constructor"in e!="constructor"in t||e.constructor!=
|
|
||||||
t.constructor)return i;for(var l in e)if(Y.call(e,l)&&(f++,!(a=Y.call(t,l)&&k(e[l],t[l],s))))break;if(a){for(l in t)if(Y.call(t,l)&&!(f--))break;a=!f}if(a&&mt)for(;7>++u&&(l=J[u],!Y.call(e,l)||!!(a=Y.call(t,l)&&k(e[l],t[l],s))););}return s.pop(),a}function L(e){return e}function A(e){Bt(Qt(e),function(t){var r=s[t]=e[t];o.prototype[t]=function(){var e=[this._wrapped];return arguments.length&&Z.apply(e,arguments),e=r.apply(s,e),this._chain&&(e=new o(e),e._chain=n),e}})}var n=!0,r=null,i=!1,O,M,_,D
|
|
||||||
,P="object"==typeof exports&&exports&&("object"==typeof global&&global&&global==global.global&&(e=global),exports),H=Array.prototype,B=Object.prototype,j=0,F=e._,I=/[-+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/,q=/\b__p\+='';/g,R=/\b(__p\+=)''\+/g,U=/(__e\(.*?\)|\b__t\))\+'';/g,z=/(?:__e|__t=)\(\s*(?![\d\s"']|this\.)/g,W=RegExp("^"+(B.valueOf+"").replace(/[.*+?^=!:${}()|[\]\/\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),X=/__token__(\d+)/g,V=/[&<"']/g,$=/['\n\r\t\u2028\u2029\\]/g
|
|
||||||
,J="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),K="__token__",Q=[],G=H.concat,Y=B.hasOwnProperty,Z=H.push,et=B.propertyIsEnumerable,tt=H.slice,nt=B.toString,rt=W.test(rt=tt.bind)&&rt,it=W.test(it=Array.isArray)&&it,st=e.isFinite,ot=W.test(ot=Object.keys)&&ot,ut="[object Array]",at="[object Boolean]",ft="[object Date]",lt="[object Function]",ct="[object Number]",ht="[object RegExp]",pt="[object String]",dt=e.clearTimeout,vt=e.setTimeout
|
|
||||||
,mt=!et.call({valueOf:0},"valueOf"),gt="x"!=tt.call("x")[0],yt="xx"!="x"[0]+Object("x")[0],bt=rt&&/\n|Opera/.test(rt+nt.call(e.opera)),wt=ot&&/^.+$|true/.test(ot+!!e.attachEvent),Et={"&":"&","<":"<",'"':""","'":"'"},St={"boolean":i,"function":n,object:n,number:i,string:i,"undefined":i},xt={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};s.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:"obj"
|
|
||||||
};var Tt={a:"g,e,I",j:"g",p:"if(!e){e=m}else if(I)e=r(e,I)",i:"e(p[n],n,g)"},Nt={j:"true",i:"if(!e(p[n],n,g))return!D"},Ct={q:i,r:i,a:"w",j:"w",p:"for(var q=1,s=arguments.length;q<s;q++){p=arguments[q];"+(mt?"if(p){":""),i:"D[n]=p[n]",e:(mt?"}":"")+"}"},kt={j:"[]",i:"e(p[n],n,g)&&D.push(p[n])"},Lt={p:"if(I)e=r(e,I)"},At={i:{l:Tt.i}},Ot={j:"",f:"if(!g)return[]",d:{b:"D=Array(s)",l:"D="+(wt?"Array(s)":"[]")},i:{b:"D[n]=e(p[n],n,g)",l:"D"+(wt?"[z]=":".push")+"(e(p[n],n,g))"}},Mt=a({a:"w",f:"if(!(w&&x[typeof w]))throw TypeError()"
|
|
||||||
,j:"[]",i:"D.push(n)"}),_t=a({a:"g,H",j:"false",n:i,d:{b:"if(J.call(p)==G)return g.indexOf(H)>-1"},i:"if(p[n]===H)return true"}),Dt=a(Tt,Nt),Pt=a(Tt,kt),Ht=a(Tt,Lt,{j:"",i:"if(e(p[n],n,g))return p[n]"}),Bt=a(Tt,Lt),jt=a(Tt,{j:"{}",p:"var y,o=typeof e=='function';if(o&&I)e=r(e,I)",i:"y=o?e(p[n],n,g):p[n][e];(l.call(D,y)?D[y]:D[y]=[]).push(p[n])"}),Ft=a(Ot,{a:"g,t",p:"var b=F.call(arguments,2),o=typeof t=='function'",i:{b:"D[n]=(o?t:p[n][t]).apply(p[n],b)",l:"D"+(wt?"[z]=":".push")+"((o?t:p[n][t]).apply(p[n],b))"
|
|
||||||
}}),It=a(Tt,Ot),qt=a(Ot,{a:"g,B",i:{b:"D[n]=p[n][B]",l:"D"+(wt?"[z]=":".push")+"(p[n][B])"}}),Rt=a({a:"g,e,a,I",j:"a",p:"var v=arguments.length<3;if(I)e=r(e,I)",d:{b:"if(v)D=g[++n]"},i:{b:"D=e(D,p[n],n,g)",l:"D=v?(v=false,p[n]):e(D,p[n],n,g)"}}),Ut=a(Tt,kt,{i:"!"+kt.i}),zt=a(Tt,Nt,{j:"false",i:Nt.i.replace("!","")}),Wt=a(Tt,Ot,{p:"if(typeof e=='string'){var y=e;e=function(g){return g[y]}}else if(I)e=r(e,I)",i:{b:"D[n]={a:e(p[n],n,g),b:p[n]}",l:"D"+(wt?"[z]=":".push")+"({a:e(p[n],n,g),b:p[n]})"},e
|
|
||||||
:"D.sort(h);s=D.length;while(s--){D[s]=D[s].b}"}),Xt=a({q:i,r:i,a:"w",j:"w",p:"var k=arguments,s=k.length;if(s>1){for(var n=1;n<s;n++)D[k[n]]=d(D[k[n]],D);return D}",i:"if(J.call(D[n])==j)D[n]=d(D[n],D)"}),Vt=a(Ct,{i:"if(D[n]==null)"+Ct.i}),$t=a(Ct),Jt=a(Tt,Lt,At,{q:i}),Kt=a(Tt,Lt,At),Qt=a({q:i,a:"w",j:"[]",i:"if(J.call(p[n])==j)D.push(n)",e:"D.sort()"});Bt({Arguments:"[object Arguments]",Date:ft,Function:lt,Number:ct,RegExp:ht,String:pt},function(e,t){s["is"+t]=function(t){return nt.call(t)==e}}
|
|
||||||
),s.isArguments(arguments)||(s.isArguments=function(e){return!!e&&!!Y.call(e,"callee")});var Gt=it||function(e){return nt.call(e)==ut},Yt=a({a:"K",j:"true",p:"var f=J.call(K);if(f==c||f==G)return!K.length",i:{l:"return false"}}),Zt=ot?function(e){return"function"==typeof e&&et.call(e,"prototype")?Mt(e):ot(e)}:Mt,en=a({a:"w",j:"[]",i:"D.push(p[n])"});s.VERSION="0.4.2",s.after=function(e,t){return 1>e?t():function(){if(1>--e)return t.apply(this,arguments)}},s.bind=C,s.bindAll=Xt,s.chain=function(e)
|
|
||||||
{return e=new o(e),e._chain=n,e},s.clone=function(e){return e&&St[typeof e]?Gt(e)?e.slice():$t({},e):e},s.compact=function(e){var t=[];if(!e)return t;for(var n=-1,r=e.length;++n<r;)e[n]&&t.push(e[n]);return t},s.compose=function(){var e=arguments;return function(){for(var t=arguments,n=e.length;n--;)t=[e[n].apply(this,t)];return t[0]}},s.contains=_t,s.debounce=function(e,t,n){function i(){a=r,n||e.apply(u,s)}var s,o,u,a;return function(){var r=n&&!a;return s=arguments,u=this,dt(a),a=vt(i,t),r&&(o=
|
|
||||||
e.apply(u,s)),o}},s.defaults=Vt,s.defer=function(e){var n=tt.call(arguments,1);return vt(function(){return e.apply(t,n)},1)},s.delay=function(e,n){var r=tt.call(arguments,2);return vt(function(){return e.apply(t,r)},n)},s.difference=function(e){var t=[];if(!e)return t;for(var n=-1,r=e.length,i=G.apply(t,arguments),i=u(i,r);++n<r;)i(e[n])||t.push(e[n]);return t},s.escape=function(e){return e==r?"":(e+"").replace(V,h)},s.every=Dt,s.extend=$t,s.filter=Pt,s.find=Ht,s.first=b,s.flatten=w,s.forEach=Bt,
|
|
||||||
s.forIn=Jt,s.forOwn=Kt,s.functions=Qt,s.groupBy=jt,s.has=function(e,t){return Y.call(e,t)},s.identity=L,s.indexOf=E,s.initial=function(e,t,n){return e?tt.call(e,0,-(t==r||n?1:t)):[]},s.intersection=function(e){var t=[];if(!e)return t;for(var n,r=-1,i=e.length,s=tt.call(arguments,1),o=[];++r<i;)n=e[r],0>E(t,n)&&Dt(s,function(e,t){return(o[t]||(o[t]=u(e)))(n)})&&t.push(n);return t},s.invoke=Ft,s.isArray=Gt,s.isBoolean=function(e){return e===n||e===i||nt.call(e)==at},s.isElement=function(e){return!!
|
|
||||||
e&&1==e.nodeType},s.isEmpty=Yt,s.isEqual=k,s.isFinite=function(e){return st(e)&&nt.call(e)==ct},s.isNaN=function(e){return nt.call(e)==ct&&e!=+e},s.isNull=function(e){return e===r},s.isObject=function(e){return e&&St[typeof e]},s.isUndefined=function(e){return e===t},s.keys=Zt,s.last=function(e,t,n){if(e){var i=e.length;return t==r||n?e[i-1]:tt.call(e,-t||i)}},s.lastIndexOf=function(e,t,n){if(!e)return-1;var r=e.length;for(n&&"number"==typeof n&&(r=(0>n?Math.max(0,r+n):Math.min(n,r-1))+1);r--;)if(
|
|
||||||
e[r]===t)return r;return-1},s.map=It,s.max=S,s.memoize=function(e,t){var n={};return function(){var r=t?t.apply(this,arguments):arguments[0];return Y.call(n,r)?n[r]:n[r]=e.apply(this,arguments)}},s.min=function(e,t,n){var r=Infinity,i=r;if(!e)return i;var s=-1,o=e.length;if(!t){for(;++s<o;)e[s]<i&&(i=e[s]);return i}for(n&&(t=p(t,n));++s<o;)n=t(e[s],s,e),n<r&&(r=n,i=e[s]);return i},s.mixin=A,s.noConflict=function(){return e._=F,this},s.once=function(e){var t,r=i;return function(){return r?t:(r=n,t=
|
|
||||||
e.apply(this,arguments))}},s.partial=function(e){var t=tt.call(arguments,1),n=t.length;return function(){var r;return r=arguments,r.length&&(t.length=n,Z.apply(t,r)),r=1==t.length?e.call(this,t[0]):e.apply(this,t),t.length=n,r}},s.pick=function(e){for(var t,n=0,r=G.apply(H,arguments),i=r.length,s={};++n<i;)t=r[n],t in e&&(s[t]=e[t]);return s},s.pluck=qt,s.range=function(e,t,n){n||(n=1),t==r&&(t=e||0,e=0);for(var i=-1,t=Math.max(0,Math.ceil((t-e)/n)),s=Array(t);++i<t;)s[i]=e,e+=n;return s},s.reduce=
|
|
||||||
Rt,s.reduceRight=y,s.reject=Ut,s.rest=x,s.result=function(e,t){if(!e)return r;var n=e[t];return nt.call(n)==lt?e[t]():n},s.shuffle=function(e){if(!e)return[];for(var t,n=-1,r=e.length,i=Array(r);++n<r;)t=Math.floor(Math.random()*(n+1)),i[n]=i[t],i[t]=e[n];return i},s.size=function(e){if(!e)return 0;var t=e.length;return t===t>>>0?e.length:Zt(e).length},s.some=zt,s.sortBy=Wt,s.sortedIndex=T,s.tap=function(e,t){return t(e),e},s.template=function(e,t,n){n||(n={});var i,o;i=n.escape;var u=n.evaluate,
|
|
||||||
a=n.interpolate,f=s.templateSettings,n=n.variable;i==r&&(i=f.escape),u==r&&(u=f.evaluate),a==r&&(a=f.interpolate),i&&(e=e.replace(i,v)),a&&(e=e.replace(a,g)),u!=O&&(O=u,D=RegExp((u?u.source:"($^)")+"|<e%-([\\s\\S]+?)%>|<e%=([\\s\\S]+?)%>","g")),i=Q.length,e=e.replace(D,m),i=i!=Q.length,e="__p += '"+e.replace($,c).replace(X,l)+"';",Q.length=0,n||(n=f.variable||M||"obj",i?e="with("+n+"){"+e+"}":(n!=M&&(M=n,_=RegExp("(\\(\\s*)"+n+"\\."+n+"\\b","g")),e=e.replace(z,"$&"+n+".").replace(_,"$1__d"))),e=(
|
|
||||||
i?e.replace(q,""):e).replace(R,"$1").replace(U,"$1;"),e="function("+n+"){"+n+"||("+n+"={});var __t,__p='',__e=_.escape"+(i?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":",__d="+n+"."+n+"||"+n+";")+e+"return __p}";try{o=Function("_","return "+e)(s)}catch(h){o=function(){throw h}}return t?o(t):(o.source=e,o)},s.throttle=function(e,t){function n(){a=new Date,u=r,e.apply(o,i)}var i,s,o,u,a=0;return function(){var r=new Date,f=t-(r-a);return i=arguments,o=this,0>=f?(a=r,s=e
|
|
||||||
.apply(o,i)):u||(u=vt(n,f)),s}},s.times=function(e,t,n){var r=-1;if(n)for(;++r<e;)t.call(n,r);else for(;++r<e;)t(r)},s.toArray=function(e){if(!e)return[];if(e.toArray&&nt.call(e.toArray)==lt)return e.toArray();var t=e.length;return t===t>>>0?(gt?nt.call(e)==pt:"string"==typeof e)?e.split(""):tt.call(e):en(e)},s.union=function(){for(var e=-1,t=[],n=G.apply(t,arguments),r=n.length;++e<r;)0>E(t,n[e])&&t.push(n[e]);return t},s.uniq=N,s.uniqueId=function(e){var t=j++;return e?e+t:t},s.values=en,s.without=
|
|
||||||
function(e){var t=[];if(!e)return t;for(var n=-1,r=e.length,i=u(arguments,1,20);++n<r;)i(e[n])||t.push(e[n]);return t},s.wrap=function(e,t){return function(){var n=[e];return arguments.length&&Z.apply(n,arguments),t.apply(this,n)}},s.zip=function(e){if(!e)return[];for(var t=-1,n=S(qt(arguments,"length")),r=Array(n);++t<n;)r[t]=qt(arguments,t);return r},s.zipObject=function(e,t){if(!e)return{};var n=-1,r=e.length,i={};for(t||(t=[]);++n<r;)i[e[n]]=t[n];return i},s.all=Dt,s.any=zt,s.collect=It,s.detect=
|
|
||||||
Ht,s.each=Bt,s.foldl=Rt,s.foldr=y,s.head=b,s.include=_t,s.inject=Rt,s.methods=Qt,s.select=Pt,s.tail=x,s.take=b,s.unique=N,o.prototype=s.prototype,A(s),o.prototype.chain=function(){return this._chain=n,this},o.prototype.value=function(){return this._wrapped},Bt("pop push reverse shift sort splice unshift".split(" "),function(e){var t=H[e];o.prototype[e]=function(){var e=this._wrapped;return t.apply(e,arguments),e.length===0&&delete e[0],this._chain&&(e=new o(e),e._chain=n),e}}),Bt(["concat","join"
|
|
||||||
,"slice"],function(e){var t=H[e];o.prototype[e]=function(){var e=t.apply(this._wrapped,arguments);return this._chain&&(e=new o(e),e._chain=n),e}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(e._=s,define(function(){return s})):P?"object"==typeof module&&module&&module.s==P?(module.s=s)._=s:P._=s:e._=s})(this);
|
|
||||||
59
package.json
59
package.json
@@ -1,49 +1,20 @@
|
|||||||
{
|
{
|
||||||
"name": "lodash",
|
"name": "lodash",
|
||||||
"version": "0.4.2",
|
"version": "1.0.2",
|
||||||
"description": "A drop-in replacement for Underscore.js that delivers performance improvements, bug fixes, and additional features.",
|
"description": "A utility library delivering consistency, customization, performance, and extras.",
|
||||||
"homepage": "http://lodash.com",
|
"homepage": "https://lodash.com/",
|
||||||
"main": "lodash",
|
"license": "MIT",
|
||||||
"keywords": [
|
"main": "./dist/lodash.js",
|
||||||
"browser",
|
"keywords": ["browser", "client", "functional", "performance", "server", "speed", "util"],
|
||||||
"client",
|
"author": "John-David Dalton <john.david.dalton@gmail.com> (http://allyoucanleet.com/)",
|
||||||
"functional",
|
"contributors": [
|
||||||
"performance",
|
"John-David Dalton <john.david.dalton@gmail.com> (http://allyoucanleet.com/)",
|
||||||
"server",
|
"Blaine Bublitz <blaine@iceddev.com> (http://www.iceddev.com/)",
|
||||||
"speed",
|
"Kit Cambridge <github@kitcambridge.be> (http://kitcambridge.be/)",
|
||||||
"util"
|
"Mathias Bynens <mathias@qiwi.be> (https://mathiasbynens.be/)"
|
||||||
],
|
],
|
||||||
"licenses": [
|
"repository": "lodash/lodash",
|
||||||
{
|
"jam": {
|
||||||
"type": "MIT",
|
"main": "./dist/lodash.compat.js"
|
||||||
"url": "http://lodash.com/license"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"author": {
|
|
||||||
"name": "John-David Dalton",
|
|
||||||
"email": "john@fusejs.com",
|
|
||||||
"web": "http://allyoucanleet.com/"
|
|
||||||
},
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/bestiejs/lodash/issues"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/bestiejs/lodash.git"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"lodash": "./build.js"
|
|
||||||
},
|
|
||||||
"directories": {
|
|
||||||
"doc": "./doc",
|
|
||||||
"test": "./test"
|
|
||||||
},
|
|
||||||
"engines": [
|
|
||||||
"node",
|
|
||||||
"rhino"
|
|
||||||
],
|
|
||||||
"scripts": {
|
|
||||||
"build": "node build",
|
|
||||||
"test": "node test/test"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,21 +13,40 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
left: -9999em;
|
left: -9999em;
|
||||||
}
|
}
|
||||||
|
#FirebugUI {
|
||||||
|
top: 2em;
|
||||||
|
}
|
||||||
|
#perf-toolbar {
|
||||||
|
background-color: #EEE;
|
||||||
|
color: #5E740B;
|
||||||
|
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
|
||||||
|
font-size: small;
|
||||||
|
padding: 0.5em 0 0.5em 2em;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script src="../lodash.min.js"></script>
|
<div id="perf-toolbar"></div>
|
||||||
<script>
|
|
||||||
var lodash = _.noConflict();
|
|
||||||
</script>
|
|
||||||
<script src="../vendor/underscore/underscore.js"></script>
|
|
||||||
<script src="../vendor/platform.js/platform.js"></script>
|
<script src="../vendor/platform.js/platform.js"></script>
|
||||||
<script src="../vendor/benchmark.js/benchmark.js"></script>
|
<script src="../vendor/benchmark.js/benchmark.js"></script>
|
||||||
<script src="../vendor/firebug-lite/src/firebug-lite-debug.js"></script>
|
<script src="../vendor/firebug-lite/src/firebug-lite-debug.js"></script>
|
||||||
|
<script src="perf-ui.js"></script>
|
||||||
|
<script>
|
||||||
|
document.write('<script src="../' + ui.buildPath + '"><\/script>');
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
var lodash = _.noConflict();
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
document.write('<script src="../' + ui.otherPath + '"><\/script>');
|
||||||
|
</script>
|
||||||
<script src="perf.js"></script>
|
<script src="perf.js"></script>
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function() {
|
||||||
var useApplet = !/[?&]nojava=true(?:&|$)/.test(location.search);
|
var measured,
|
||||||
|
perfNow,
|
||||||
|
begin = new Date;
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
var fbUI = document.getElementById('FirebugUI'),
|
var fbUI = document.getElementById('FirebugUI'),
|
||||||
@@ -37,19 +56,24 @@
|
|||||||
if (!fbCommandLine) {
|
if (!fbCommandLine) {
|
||||||
return setTimeout(init, 15);
|
return setTimeout(init, 15);
|
||||||
}
|
}
|
||||||
fbUI.style.height = fbDoc.body.style.height = fbDoc.documentElement.style.height = '100%';
|
fbUI.style.height = (
|
||||||
|
Math.max(document.documentElement.clientHeight, document.body.clientHeight) -
|
||||||
|
document.getElementById('perf-toolbar').clientHeight
|
||||||
|
) + 'px';
|
||||||
|
|
||||||
// give applet time to initialize
|
fbDoc.body.style.height = fbDoc.documentElement.style.height = '100%';
|
||||||
lodash.delay(run, useApplet ? 500 : 15);
|
setTimeout(run, 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useApplet) {
|
// is the applet permitted?
|
||||||
// using innerHTML avoids an alert in some versions of IE6
|
if (!/[?&]nojava=true(?:&|$)/.test(location.search)) {
|
||||||
var div = document.createElement('div');
|
// is the applet really needed?
|
||||||
div.innerHTML = '<applet code=nano archive="../vendor/benchmark.js/nano.jar">';
|
while (!(measured = new Date - begin)) { }
|
||||||
document.body.insertBefore(div.lastChild, document.body.firstChild);
|
if (measured != 1 && !((perfNow = window.performance) && typeof (perfNow.now || perfNow.webkitNow) == 'function')) {
|
||||||
|
// load applet
|
||||||
|
document.write('<applet code="nano" archive="../vendor/benchmark.js/nano.jar"></applet>');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window.onload = init;
|
window.onload = init;
|
||||||
}());
|
}());
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
136
perf/perf-ui.js
Normal file
136
perf/perf-ui.js
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
;(function(window) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/** The Lo-Dash build to load */
|
||||||
|
var build = (/build=([^&]+)/.exec(location.search) || [])[1];
|
||||||
|
|
||||||
|
/** The other library to load */
|
||||||
|
var other = (/other=([^&]+)/.exec(location.search) || [])[1];
|
||||||
|
|
||||||
|
/** The `ui` object */
|
||||||
|
var ui = {};
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers an event listener on an element.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Element} element The element.
|
||||||
|
* @param {String} eventName The name of the event.
|
||||||
|
* @param {Function} handler The event handler.
|
||||||
|
* @returns {Element} The element.
|
||||||
|
*/
|
||||||
|
function addListener(element, eventName, handler) {
|
||||||
|
if (typeof element.addEventListener != 'undefined') {
|
||||||
|
element.addEventListener(eventName, handler, false);
|
||||||
|
} else if (typeof element.attachEvent != 'undefined') {
|
||||||
|
element.attachEvent('on' + eventName, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// expose Lo-Dash build file path
|
||||||
|
ui.buildPath = (function() {
|
||||||
|
switch (build) {
|
||||||
|
case 'lodash-dev': return 'dist/lodash.compat.js';
|
||||||
|
case 'lodash-modern': return 'dist/lodash.min.js';
|
||||||
|
case 'lodash-underscore': return 'dist/lodash.underscore.min.js';
|
||||||
|
case 'lodash-custom': return 'lodash.custom.min.js';
|
||||||
|
}
|
||||||
|
return 'dist/lodash.compat.min.js';
|
||||||
|
}());
|
||||||
|
|
||||||
|
// expose other library file path
|
||||||
|
ui.otherPath = (function() {
|
||||||
|
switch (other) {
|
||||||
|
case 'lodash-dev': return 'dist/lodash.compat.js';
|
||||||
|
case 'lodash-prod': return 'dist/lodash.compat.min.js';
|
||||||
|
case 'lodash-modern': return 'dist/lodash.min.js';
|
||||||
|
case 'lodash-underscore': return 'dist/lodash.underscore.min.js';
|
||||||
|
case 'lodash-custom': return 'lodash.custom.min.js';
|
||||||
|
case 'underscore-dev': return 'vendor/underscore/underscore.js';
|
||||||
|
}
|
||||||
|
return 'vendor/underscore/underscore-min.js';
|
||||||
|
}());
|
||||||
|
|
||||||
|
// initialize controls
|
||||||
|
addListener(window, 'load', function() {
|
||||||
|
function eventHandler(event) {
|
||||||
|
var search = location.search.replace(/^\?|&?(?:build|other)=[^&]*&?/g, '');
|
||||||
|
if (event.stopPropagation) {
|
||||||
|
event.stopPropagation();
|
||||||
|
} else {
|
||||||
|
event.cancelBubble = true;
|
||||||
|
}
|
||||||
|
location.href =
|
||||||
|
location.href.split('?')[0] + '?' +
|
||||||
|
(search ? search + '&' : '') +
|
||||||
|
'build=' + buildList[buildList.selectedIndex].value + '&' +
|
||||||
|
'other=' + otherList[otherList.selectedIndex].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
var span1 = document.createElement('span');
|
||||||
|
span1.style.cssText = 'float:right';
|
||||||
|
span1.innerHTML =
|
||||||
|
'<label for="perf-build">Build: </label>' +
|
||||||
|
'<select id="perf-build">' +
|
||||||
|
'<option value="lodash-dev">Lo-Dash</option>' +
|
||||||
|
'<option value="lodash-prod">Lo-Dash (minified)</option>' +
|
||||||
|
'<option value="lodash-modern">Lo-Dash (modern)</option>' +
|
||||||
|
'<option value="lodash-underscore">Lo-Dash (underscore)</option>' +
|
||||||
|
'<option value="lodash-custom">Lo-Dash (custom)</option>' +
|
||||||
|
'</select>';
|
||||||
|
|
||||||
|
var span2 = document.createElement('span');
|
||||||
|
span2.style.cssText = 'float:right';
|
||||||
|
span2.innerHTML =
|
||||||
|
'<label for="perf-other">Other Library: </label>' +
|
||||||
|
'<select id="perf-other">' +
|
||||||
|
'<option value="underscore-dev">Underscore</option>' +
|
||||||
|
'<option value="underscore-prod">Underscore (minified)</option>' +
|
||||||
|
'<option value="lodash-dev">Lo-Dash</option>' +
|
||||||
|
'<option value="lodash-prod">Lo-Dash (minified)</option>' +
|
||||||
|
'<option value="lodash-modern">Lo-Dash (modern)</option>' +
|
||||||
|
'<option value="lodash-underscore">Lo-Dash (underscore)</option>' +
|
||||||
|
'<option value="lodash-custom">Lo-Dash (custom)</option>' +
|
||||||
|
'</select>';
|
||||||
|
|
||||||
|
var buildList = span1.lastChild,
|
||||||
|
otherList = span2.lastChild,
|
||||||
|
toolbar = document.getElementById('perf-toolbar');
|
||||||
|
|
||||||
|
toolbar.appendChild(span2);
|
||||||
|
toolbar.appendChild(span1);
|
||||||
|
|
||||||
|
buildList.selectedIndex = (function() {
|
||||||
|
switch (build) {
|
||||||
|
case 'lodash-dev': return 0;
|
||||||
|
case 'lodash-modern': return 2;
|
||||||
|
case 'lodash-underscore': return 3;
|
||||||
|
case 'lodash-custom': return 4;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}());
|
||||||
|
|
||||||
|
otherList.selectedIndex = (function() {
|
||||||
|
switch (other) {
|
||||||
|
case 'underscore-dev': return 0;
|
||||||
|
case 'lodash-dev': return 2;
|
||||||
|
case 'lodash-prod': return 3;
|
||||||
|
case 'lodash-modern': return 4;
|
||||||
|
case 'lodash-underscore': return 5;
|
||||||
|
case 'lodash-custom': return 6;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}());
|
||||||
|
|
||||||
|
addListener(buildList, 'change', eventHandler);
|
||||||
|
addListener(otherList, 'change', eventHandler);
|
||||||
|
});
|
||||||
|
|
||||||
|
// expose `ui`
|
||||||
|
window.ui = ui;
|
||||||
|
|
||||||
|
}(this));
|
||||||
2130
perf/perf.js
2130
perf/perf.js
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,14 @@
|
|||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
for cmd in node narwhal ringo rhino; do
|
|
||||||
echo ""
|
echo "Running performance suite in node..."
|
||||||
echo "Running performance suite in $cmd..."
|
node perf.js ../dist/lodash.js && node perf.js ../dist/lodash.min.js
|
||||||
$cmd perf.js
|
|
||||||
|
for cmd in rhino narwhal ringo phantomjs; do
|
||||||
|
echo ""
|
||||||
|
echo "Running performance suite in $cmd..."
|
||||||
|
$cmd perf.js ../dist/lodash.compat.js && $cmd perf.js ../dist/lodash.compat.min.js
|
||||||
done
|
done
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "Running performance suite in a browser..."
|
echo "Running performance suite in a browser..."
|
||||||
open index.html
|
open index.html
|
||||||
|
|||||||
@@ -3,33 +3,46 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Backbone Test Suite</title>
|
<title>Backbone Test Suite</title>
|
||||||
<link rel="stylesheet" href="../vendor/backbone/test/vendor/qunit.css">
|
<link rel="stylesheet" href="../vendor/qunit/qunit/qunit.css">
|
||||||
<style>
|
<style>
|
||||||
body > #qunit-header {
|
body > #qunit-header {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
#jslitmus {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="qunit"></div>
|
<div id="qunit"></div>
|
||||||
<h1 id="qunit-header"><a href="#">Backbone Speed Suite</a></h1>
|
<h1 id="qunit-header"></h1>
|
||||||
<div id="qunit-fixture">
|
<div id="qunit-fixture">
|
||||||
<div id='testElement'>
|
<div id='testElement'>
|
||||||
<h1>Test</h1>
|
<h1>Test</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script src="../vendor/backbone/test/vendor/json2.js"></script>
|
<script src="../vendor/json3/lib/json3.js"></script>
|
||||||
<script src="../vendor/backbone/test/vendor/jquery-1.7.1.js"></script>
|
<script src="../vendor/jquery/jquery.js"></script>
|
||||||
<script src="../vendor/backbone/test/vendor/qunit.js"></script>
|
<script src="../vendor/platform.js/platform.js"></script>
|
||||||
<script src="../vendor/backbone/test/vendor/jslitmus.js"></script>
|
<script src="../vendor/qunit/qunit/qunit.js"></script>
|
||||||
<script src="test-ui.js"></script>
|
<script src="test-ui.js"></script>
|
||||||
|
<script src="../lodash.js"></script>
|
||||||
<script>
|
<script>
|
||||||
document.write('<script src="../' + QUnit.config.lodashFilename + '.js"><\/script>');
|
var lodash = _.noConflict();
|
||||||
|
document.write('<script src="../' + ui.buildPath + '"><\/script>');
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
_.mixin({
|
||||||
|
'debounce': lodash.debounce,
|
||||||
|
'defer': lodash.defer
|
||||||
|
});
|
||||||
|
if (!_.chain) {
|
||||||
|
_.mixin({
|
||||||
|
'chain': function(value) {
|
||||||
|
return new _(value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<script src="../vendor/backbone/backbone.js"></script>
|
<script src="../vendor/backbone/backbone.js"></script>
|
||||||
|
<script src="../vendor/backbone/test/environment.js"></script>
|
||||||
<script src="../vendor/backbone/test/noconflict.js"></script>
|
<script src="../vendor/backbone/test/noconflict.js"></script>
|
||||||
<script src="../vendor/backbone/test/events.js"></script>
|
<script src="../vendor/backbone/test/events.js"></script>
|
||||||
<script src="../vendor/backbone/test/model.js"></script>
|
<script src="../vendor/backbone/test/model.js"></script>
|
||||||
|
|||||||
@@ -8,13 +8,7 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="qunit"></div>
|
<div id="qunit"></div>
|
||||||
<script src="../vendor/platform.js/platform.js"></script>
|
<script src="../vendor/platform.js/platform.js"></script>
|
||||||
<script>
|
<script src="../vendor/qunit/qunit/qunit.js"></script>
|
||||||
// avoid syntax errors for `QUnit.throws` in older Firefoxes
|
|
||||||
document.write(platform.name == 'Firefox' && /^1\b/.test(platform.version)
|
|
||||||
? '<script src="../vendor/qunit/qunit/qunit-1.8.0.js"><\/script>'
|
|
||||||
: '<script src="../vendor/qunit/qunit/qunit.js"><\/script>'
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
<script src="test-ui.js"></script>
|
<script src="test-ui.js"></script>
|
||||||
<script>
|
<script>
|
||||||
// set a bad shim
|
// set a bad shim
|
||||||
@@ -22,7 +16,7 @@
|
|||||||
Object.keys = function() { return []; };
|
Object.keys = function() { return []; };
|
||||||
|
|
||||||
// load Lo-Dash and expose it to the bad `Object.keys` shim
|
// load Lo-Dash and expose it to the bad `Object.keys` shim
|
||||||
document.write('<script src="../' + QUnit.config.lodashFilename + '.js"><\/script>');
|
document.write('<script src="../' + ui.buildPath + '"><\/script>');
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
// store Lo-Dash to test for bad shim detection
|
// store Lo-Dash to test for bad shim detection
|
||||||
@@ -32,11 +26,8 @@
|
|||||||
Object.keys = Object._keys;
|
Object.keys = Object._keys;
|
||||||
delete Object._keys;
|
delete Object._keys;
|
||||||
|
|
||||||
// set to test `_.noConflict`
|
|
||||||
_ = 1;
|
|
||||||
|
|
||||||
// load Lo-Dash again to overwrite the existing `_` value
|
// load Lo-Dash again to overwrite the existing `_` value
|
||||||
document.write('<script src="../' + QUnit.config.lodashFilename + '.js"><\/script>');
|
document.write('<script src="../' + ui.buildPath + '"><\/script>');
|
||||||
|
|
||||||
// load test.js if not using require.js
|
// load test.js if not using require.js
|
||||||
document.write(QUnit.urlParams.norequire
|
document.write(QUnit.urlParams.norequire
|
||||||
@@ -47,23 +38,40 @@
|
|||||||
<script>
|
<script>
|
||||||
// load Lo-Dash as a module
|
// load Lo-Dash as a module
|
||||||
var lodashModule,
|
var lodashModule,
|
||||||
|
shimmedModule,
|
||||||
underscoreModule;
|
underscoreModule;
|
||||||
|
|
||||||
window.require && require({
|
window.require && require(
|
||||||
'baseUrl': '../vendor/requirejs/',
|
(function() {
|
||||||
'urlArgs': 't=' + (+new Date),
|
var modulePath = ui.buildPath.replace(/\.js$/, '');
|
||||||
'paths': {
|
return {
|
||||||
'lodash': '../../' + QUnit.config.lodashFilename,
|
'baseUrl': '../vendor/requirejs/',
|
||||||
'underscore': './../../' + QUnit.config.lodashFilename
|
'urlArgs': 't=' + (+new Date),
|
||||||
|
'paths': {
|
||||||
|
'lodash': '../../' + modulePath,
|
||||||
|
'shimmed': './../../' + modulePath,
|
||||||
|
'underscore': '../underscore/../../' + modulePath
|
||||||
|
},
|
||||||
|
'shim': {
|
||||||
|
'shimmed': {
|
||||||
|
'exports': '_'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}()),
|
||||||
|
['lodash', 'shimmed', 'underscore'], function(lodash, shimmed, underscore) {
|
||||||
|
if (lodash && lodash.noConflict) {
|
||||||
|
lodashModule = lodash.noConflict();
|
||||||
|
lodashModule.moduleName = 'lodash';
|
||||||
|
}
|
||||||
|
if (shimmed.noConflict) {
|
||||||
|
shimmedModule = shimmed.noConflict();
|
||||||
|
shimmedModule.moduleName = 'shimmed';
|
||||||
|
}
|
||||||
|
if (underscore && underscore.noConflict) {
|
||||||
|
underscoreModule = underscore.noConflict();
|
||||||
|
underscoreModule.moduleName = 'underscore';
|
||||||
}
|
}
|
||||||
},
|
|
||||||
['lodash', 'underscore'], function(lodash, underscore) {
|
|
||||||
lodashModule = lodash.noConflict();
|
|
||||||
lodashModule.moduleName = 'lodash';
|
|
||||||
|
|
||||||
underscoreModule = underscore.noConflict();
|
|
||||||
underscoreModule.moduleName = 'underscore';
|
|
||||||
|
|
||||||
require(['test.js']);
|
require(['test.js']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,18 @@
|
|||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
for cmd in rhino ringo narwhal node; do
|
|
||||||
echo ""
|
for cmd in rhino narwhal ringo phantomjs; do
|
||||||
echo "Testing in $cmd..."
|
echo "Testing in $cmd..."
|
||||||
$cmd test.js
|
$cmd test.js ../dist/lodash.compat.js && $cmd test.js ../dist/lodash.compat.min.js
|
||||||
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
|
echo "Testing in node..."
|
||||||
|
node test.js ../dist/lodash.js && node test.js ../dist/lodash.min.js
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Testing build..."
|
||||||
|
node test-build.js
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "Testing in a browser..."
|
echo "Testing in a browser..."
|
||||||
open index.html
|
open index.html
|
||||||
|
|||||||
3
test/template/a.jst
Normal file
3
test/template/a.jst
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<ul>
|
||||||
|
<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>
|
||||||
|
</ul>
|
||||||
1
test/template/b.jst
Normal file
1
test/template/b.jst
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<% print("Hello " + epithet); %>.
|
||||||
1
test/template/c.jst
Normal file
1
test/template/c.jst
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Hello ${ name }!
|
||||||
1
test/template/d.tpl
Normal file
1
test/template/d.tpl
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Hello {{ name }}!
|
||||||
1324
test/test-build.js
Normal file
1324
test/test-build.js
Normal file
File diff suppressed because it is too large
Load Diff
@@ -10,16 +10,22 @@
|
|||||||
/** A flag to determine if RequireJS should be loaded */
|
/** A flag to determine if RequireJS should be loaded */
|
||||||
var norequire = /[?&]norequire=true(?:&|$)/.test(location.search);
|
var norequire = /[?&]norequire=true(?:&|$)/.test(location.search);
|
||||||
|
|
||||||
|
/** The `ui` object */
|
||||||
|
var ui = {};
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
// assign `QUnit.config` properties
|
// expose Lo-Dash build file path
|
||||||
QUnit.config.lodashFilename = (function() {
|
ui.buildPath = (function() {
|
||||||
switch (build) {
|
switch (build) {
|
||||||
case 'prod': return 'lodash.min';
|
case 'lodash-prod': return 'dist/lodash.compat.min.js';
|
||||||
case 'custom': return 'lodash.custom.min';
|
case 'lodash-underscore': return 'dist/lodash.underscore.min.js';
|
||||||
case 'custom-debug': return 'lodash.custom';
|
case 'lodash-modern': return 'dist/lodash.min.js';
|
||||||
|
case 'lodash-modern-debug': return 'dist/lodash.js';
|
||||||
|
case 'lodash-custom': return 'lodash.custom.min.js';
|
||||||
|
case 'lodash-custom-debug': return 'lodash.custom.js';
|
||||||
}
|
}
|
||||||
return 'lodash';
|
return 'lodash.js';
|
||||||
}());
|
}());
|
||||||
|
|
||||||
// assign `QUnit.urlParams` properties
|
// assign `QUnit.urlParams` properties
|
||||||
@@ -28,7 +34,7 @@
|
|||||||
'norequire': norequire
|
'norequire': norequire
|
||||||
});
|
});
|
||||||
|
|
||||||
// initialize the build dropdown
|
// initialize controls
|
||||||
addEvent(window, 'load', function() {
|
addEvent(window, 'load', function() {
|
||||||
function eventHandler(event) {
|
function eventHandler(event) {
|
||||||
var search = location.search.replace(/^\?|&?(?:build|norequire)=[^&]*&?/g, '');
|
var search = location.search.replace(/^\?|&?(?:build|norequire)=[^&]*&?/g, '');
|
||||||
@@ -39,52 +45,64 @@
|
|||||||
}
|
}
|
||||||
location.href =
|
location.href =
|
||||||
location.href.split('?')[0] + '?' +
|
location.href.split('?')[0] + '?' +
|
||||||
(search ? search + '&' : '') + 'build=' +
|
(search ? search + '&' : '') +
|
||||||
dropdown[dropdown.selectedIndex].value +
|
'build=' + buildList[buildList.selectedIndex].value +
|
||||||
(checkbox.checked ? '&norequire=true' : '');
|
(checkbox.checked ? '&norequire=true' : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
var toolbar = document.getElementById('qunit-testrunner-toolbar');
|
var toolbar = document.getElementById('qunit-testrunner-toolbar');
|
||||||
if (toolbar) {
|
if (toolbar) {
|
||||||
toolbar.appendChild(label1);
|
toolbar.appendChild(span1);
|
||||||
toolbar.appendChild(label2);
|
toolbar.appendChild(span2);
|
||||||
|
|
||||||
dropdown.selectedIndex = (function() {
|
buildList.selectedIndex = (function() {
|
||||||
switch (build) {
|
switch (build) {
|
||||||
case 'prod': return 1;
|
case 'lodash-prod': return 1;
|
||||||
case 'custom': return 2;
|
case 'lodash-underscore': return 2;
|
||||||
case 'custom-debug': return 3;
|
case 'lodash-modern': return 3;
|
||||||
|
case 'lodash-modern-debug': return 4;
|
||||||
|
case 'lodash-custom': return 5;
|
||||||
|
case 'lodash-custom-debug': return 6;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}());
|
}());
|
||||||
|
|
||||||
checkbox.checked = norequire;
|
checkbox.checked = norequire;
|
||||||
addEvent(checkbox, 'click', eventHandler);
|
addEvent(checkbox, 'click', eventHandler);
|
||||||
addEvent(dropdown, 'change', eventHandler);
|
addEvent(buildList, 'change', eventHandler);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setTimeout(init, 15);
|
setTimeout(init, 15);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var label1 = document.createElement('label');
|
var span1 = document.createElement('span');
|
||||||
label1.innerHTML =
|
span1.innerHTML =
|
||||||
'<input name="norequire" type="checkbox">No RequireJS</label>';
|
'<input id="qunit-norequire" type="checkbox">' +
|
||||||
|
'<label for="qunit-norequire">No RequireJS</label>';
|
||||||
|
|
||||||
var label2 = document.createElement('label');
|
var span2 = document.createElement('span');
|
||||||
label2.innerHTML = ' ' +
|
span2.style.cssText = 'float:right';
|
||||||
'<select name="build">' +
|
span2.innerHTML =
|
||||||
'<option value="dev">Developement</option>' +
|
'<label for="qunit-build">Build: </label>' +
|
||||||
'<option value="prod">Production</option>' +
|
'<select id="qunit-build">' +
|
||||||
'<option value="custom">Custom</option>' +
|
'<option value="lodash-dev">Developement</option>' +
|
||||||
'<option value="custom-debug">Custom (debug)</option>' +
|
'<option value="lodash-prod">Production</option>' +
|
||||||
'</select> Build';
|
'<option value="lodash-underscore">Underscore</option>' +
|
||||||
|
'<option value="lodash-modern">Modern</option>' +
|
||||||
|
'<option value="lodash-modern-debug">Modern (debug)</option>' +
|
||||||
|
'<option value="lodash-custom">Custom</option>' +
|
||||||
|
'<option value="lodash-custom-debug">Custom (debug)</option>' +
|
||||||
|
'</select>';
|
||||||
|
|
||||||
var checkbox = label1.firstChild,
|
var checkbox = span1.firstChild,
|
||||||
dropdown = label2.getElementsByTagName('select')[0];
|
buildList = span2.lastChild;
|
||||||
|
|
||||||
init();
|
init();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// expose `ui`
|
||||||
|
window.ui = ui;
|
||||||
|
|
||||||
}(this));
|
}(this));
|
||||||
|
|||||||
2384
test/test.js
2384
test/test.js
File diff suppressed because it is too large
Load Diff
@@ -3,9 +3,9 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Underscore Test Suite</title>
|
<title>Underscore Test Suite</title>
|
||||||
<link rel="stylesheet" href="../vendor/underscore/test/vendor/qunit.css">
|
<link rel="stylesheet" href="../vendor/qunit/qunit/qunit.css">
|
||||||
<style>
|
<style>
|
||||||
#jslitmus, iframe {
|
iframe {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -17,14 +17,74 @@
|
|||||||
<div id="id1"></div>
|
<div id="id1"></div>
|
||||||
<div id="id2"></div>
|
<div id="id2"></div>
|
||||||
</div>
|
</div>
|
||||||
|
<img id="chart_image" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==">
|
||||||
</div>
|
</div>
|
||||||
<script src="../vendor/backbone/test/vendor/json2.js"></script>
|
<script src="../vendor/jquery/jquery.js"></script>
|
||||||
<script src="../vendor/underscore/test/vendor/jquery.js"></script>
|
<script src="../vendor/platform.js/platform.js"></script>
|
||||||
<script src="../vendor/underscore/test/vendor/qunit.js"></script>
|
<script src="../vendor/qunit/qunit/qunit.js"></script>
|
||||||
<script src="../vendor/underscore/test/vendor/jslitmus.js"></script>
|
|
||||||
<script src="test-ui.js"></script>
|
<script src="test-ui.js"></script>
|
||||||
<script>
|
<script>
|
||||||
document.write('<script src="../' + QUnit.config.lodashFilename + '.js"><\/script>');
|
document.write('<script src="../' + ui.buildPath + '"><\/script>');
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
var arrayProto = Array.prototype,
|
||||||
|
concat = arrayProto.concat,
|
||||||
|
pop = arrayProto.pop,
|
||||||
|
push = arrayProto.push,
|
||||||
|
slice = arrayProto.slice;
|
||||||
|
|
||||||
|
if (_.chain) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_.mixin = function(object) {
|
||||||
|
_.forEach(_.functions(object), function(methodName) {
|
||||||
|
var func = _[methodName] = object[methodName];
|
||||||
|
_.prototype[methodName] = function() {
|
||||||
|
var args = [this.__wrapped__];
|
||||||
|
push.apply(args, arguments);
|
||||||
|
|
||||||
|
var result = func.apply(_, args);
|
||||||
|
if (this.__chain__) {
|
||||||
|
result = new _(result);
|
||||||
|
result.__chain__ = true;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
_.mixin(_);
|
||||||
|
|
||||||
|
_.mixin({
|
||||||
|
'findWhere': _.find
|
||||||
|
});
|
||||||
|
|
||||||
|
_.chain = function(value) {
|
||||||
|
value = new _(value);
|
||||||
|
value.__chain__ = true;
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
_.prototype.chain = function() {
|
||||||
|
this.__chain__ = true;
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
_.prototype.concat = function() {
|
||||||
|
var result = concat.apply(this.__wrapped__, arguments);
|
||||||
|
if (this.__chain__) {
|
||||||
|
result = new _(result);
|
||||||
|
result.__chain__ = true;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
_.prototype.pop = function() {
|
||||||
|
pop.apply(this.__wrapped__, arguments);
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
}());
|
||||||
</script>
|
</script>
|
||||||
<script src="../vendor/underscore/test/collections.js"></script>
|
<script src="../vendor/underscore/test/collections.js"></script>
|
||||||
<script src="../vendor/underscore/test/arrays.js"></script>
|
<script src="../vendor/underscore/test/arrays.js"></script>
|
||||||
|
|||||||
1143
vendor/backbone/backbone.js
vendored
1143
vendor/backbone/backbone.js
vendored
File diff suppressed because it is too large
Load Diff
621
vendor/backbone/test/collection.js
vendored
621
vendor/backbone/test/collection.js
vendored
@@ -1,13 +1,12 @@
|
|||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
||||||
var lastRequest = null;
|
|
||||||
var sync = Backbone.sync;
|
|
||||||
|
|
||||||
var a, b, c, d, e, col, otherCol;
|
var a, b, c, d, e, col, otherCol;
|
||||||
|
|
||||||
module("Backbone.Collection", {
|
module("Backbone.Collection", _.extend(new Environment, {
|
||||||
|
|
||||||
setup: function() {
|
setup: function() {
|
||||||
|
Environment.prototype.setup.apply(this, arguments);
|
||||||
|
|
||||||
a = new Backbone.Model({id: 3, label: 'a'});
|
a = new Backbone.Model({id: 3, label: 'a'});
|
||||||
b = new Backbone.Model({id: 2, label: 'b'});
|
b = new Backbone.Model({id: 2, label: 'b'});
|
||||||
c = new Backbone.Model({id: 1, label: 'c'});
|
c = new Backbone.Model({id: 1, label: 'c'});
|
||||||
@@ -15,45 +14,63 @@ $(document).ready(function() {
|
|||||||
e = null;
|
e = null;
|
||||||
col = new Backbone.Collection([a,b,c,d]);
|
col = new Backbone.Collection([a,b,c,d]);
|
||||||
otherCol = new Backbone.Collection();
|
otherCol = new Backbone.Collection();
|
||||||
|
|
||||||
Backbone.sync = function(method, model, options) {
|
|
||||||
lastRequest = {
|
|
||||||
method: method,
|
|
||||||
model: model,
|
|
||||||
options: options
|
|
||||||
};
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
teardown: function() {
|
|
||||||
Backbone.sync = sync;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}));
|
||||||
|
|
||||||
test("Collection: new and sort", 7, function() {
|
test("new and sort", 9, function() {
|
||||||
|
var counter = 0;
|
||||||
|
col.on('sort', function(){ counter++; });
|
||||||
equal(col.first(), a, "a should be first");
|
equal(col.first(), a, "a should be first");
|
||||||
equal(col.last(), d, "d should be last");
|
equal(col.last(), d, "d should be last");
|
||||||
col.comparator = function(a, b) {
|
col.comparator = function(a, b) {
|
||||||
return a.id > b.id ? -1 : 1;
|
return a.id > b.id ? -1 : 1;
|
||||||
};
|
};
|
||||||
col.sort();
|
col.sort();
|
||||||
|
equal(counter, 1);
|
||||||
equal(col.first(), a, "a should be first");
|
equal(col.first(), a, "a should be first");
|
||||||
equal(col.last(), d, "d should be last");
|
equal(col.last(), d, "d should be last");
|
||||||
col.comparator = function(model) { return model.id; };
|
col.comparator = function(model) { return model.id; };
|
||||||
col.sort();
|
col.sort();
|
||||||
|
equal(counter, 2);
|
||||||
equal(col.first(), d, "d should be first");
|
equal(col.first(), d, "d should be first");
|
||||||
equal(col.last(), a, "a should be last");
|
equal(col.last(), a, "a should be last");
|
||||||
equal(col.length, 4);
|
equal(col.length, 4);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: get, getByCid", 3, function() {
|
test("String comparator.", 1, function() {
|
||||||
equal(col.get(0), d);
|
var collection = new Backbone.Collection([
|
||||||
equal(col.get(2), b);
|
{id: 3},
|
||||||
equal(col.getByCid(col.first().cid), col.first());
|
{id: 1},
|
||||||
|
{id: 2}
|
||||||
|
], {comparator: 'id'});
|
||||||
|
deepEqual(collection.pluck('id'), [1, 2, 3]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: get with non-default ids", 2, function() {
|
test("new and parse", 3, function() {
|
||||||
|
var Collection = Backbone.Collection.extend({
|
||||||
|
parse : function(data) {
|
||||||
|
return _.filter(data, function(datum) {
|
||||||
|
return datum.a % 2 === 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var models = [{a: 1}, {a: 2}, {a: 3}, {a: 4}];
|
||||||
|
var collection = new Collection(models, {parse: true});
|
||||||
|
strictEqual(collection.length, 2);
|
||||||
|
strictEqual(collection.first().get('a'), 2);
|
||||||
|
strictEqual(collection.last().get('a'), 4);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("get", 5, function() {
|
||||||
|
equal(col.get(0), d);
|
||||||
|
equal(col.get(2), b);
|
||||||
|
equal(col.get({id: 1}), c);
|
||||||
|
equal(col.get(c.clone()), c);
|
||||||
|
equal(col.get(col.first().cid), col.first());
|
||||||
|
});
|
||||||
|
|
||||||
|
test("get with non-default ids", 4, function() {
|
||||||
var col = new Backbone.Collection();
|
var col = new Backbone.Collection();
|
||||||
var MongoModel = Backbone.Model.extend({
|
var MongoModel = Backbone.Model.extend({
|
||||||
idAttribute: '_id'
|
idAttribute: '_id'
|
||||||
@@ -63,9 +80,15 @@ $(document).ready(function() {
|
|||||||
equal(col.get(100), model);
|
equal(col.get(100), model);
|
||||||
model.set({_id: 101});
|
model.set({_id: 101});
|
||||||
equal(col.get(101), model);
|
equal(col.get(101), model);
|
||||||
|
|
||||||
|
var Col2 = Backbone.Collection.extend({ model: MongoModel });
|
||||||
|
var col2 = new Col2();
|
||||||
|
col2.push(model);
|
||||||
|
equal(col2.get({_id: 101}), model);
|
||||||
|
equal(col2.get(model.clone()), model);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: update index when id changes", 3, function() {
|
test("update index when id changes", 3, function() {
|
||||||
var col = new Backbone.Collection();
|
var col = new Backbone.Collection();
|
||||||
col.add([
|
col.add([
|
||||||
{id : 0, name : 'one'},
|
{id : 0, name : 'one'},
|
||||||
@@ -78,15 +101,15 @@ $(document).ready(function() {
|
|||||||
equal(col.get(101).get('name'), 'one');
|
equal(col.get(101).get('name'), 'one');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: at", 1, function() {
|
test("at", 1, function() {
|
||||||
equal(col.at(2), c);
|
equal(col.at(2), c);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: pluck", 1, function() {
|
test("pluck", 1, function() {
|
||||||
equal(col.pluck('label').join(' '), 'a b c d');
|
equal(col.pluck('label').join(' '), 'a b c d');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: add", 11, function() {
|
test("add", 10, function() {
|
||||||
var added, opts, secondAdded;
|
var added, opts, secondAdded;
|
||||||
added = opts = secondAdded = null;
|
added = opts = secondAdded = null;
|
||||||
e = new Backbone.Model({id: 10, label : 'e'});
|
e = new Backbone.Model({id: 10, label : 'e'});
|
||||||
@@ -96,7 +119,6 @@ $(document).ready(function() {
|
|||||||
});
|
});
|
||||||
col.on('add', function(model, collection, options){
|
col.on('add', function(model, collection, options){
|
||||||
added = model.get('label');
|
added = model.get('label');
|
||||||
equal(options.index, 4);
|
|
||||||
opts = options;
|
opts = options;
|
||||||
});
|
});
|
||||||
col.add(e, {amazing: true});
|
col.add(e, {amazing: true});
|
||||||
@@ -118,7 +140,7 @@ $(document).ready(function() {
|
|||||||
equal(atCol.last(), h);
|
equal(atCol.last(), h);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: add multiple models", 6, function() {
|
test("add multiple models", 6, function() {
|
||||||
var col = new Backbone.Collection([{at: 0}, {at: 1}, {at: 9}]);
|
var col = new Backbone.Collection([{at: 0}, {at: 1}, {at: 9}]);
|
||||||
col.add([{at: 2}, {at: 3}, {at: 4}, {at: 5}, {at: 6}, {at: 7}, {at: 8}], {at: 2});
|
col.add([{at: 2}, {at: 3}, {at: 4}, {at: 5}, {at: 6}, {at: 7}, {at: 8}], {at: 2});
|
||||||
for (var i = 0; i <= 5; i++) {
|
for (var i = 0; i <= 5; i++) {
|
||||||
@@ -126,7 +148,7 @@ $(document).ready(function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: add; at should have preference over comparator", 1, function() {
|
test("add; at should have preference over comparator", 1, function() {
|
||||||
var Col = Backbone.Collection.extend({
|
var Col = Backbone.Collection.extend({
|
||||||
comparator: function(a,b) {
|
comparator: function(a,b) {
|
||||||
return a.id > b.id ? -1 : 1;
|
return a.id > b.id ? -1 : 1;
|
||||||
@@ -139,19 +161,19 @@ $(document).ready(function() {
|
|||||||
equal(col.pluck('id').join(' '), '3 1 2');
|
equal(col.pluck('id').join(' '), '3 1 2');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: can't add model to collection twice", function() {
|
test("can't add model to collection twice", function() {
|
||||||
var col = new Backbone.Collection([{id: 1}, {id: 2}, {id: 1}, {id: 2}, {id: 3}]);
|
var col = new Backbone.Collection([{id: 1}, {id: 2}, {id: 1}, {id: 2}, {id: 3}]);
|
||||||
equal(col.pluck('id').join(' '), '1 2 3');
|
equal(col.pluck('id').join(' '), '1 2 3');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: can't add different model with same id to collection twice", 1, function() {
|
test("can't add different model with same id to collection twice", 1, function() {
|
||||||
var col = new Backbone.Collection;
|
var col = new Backbone.Collection;
|
||||||
col.unshift({id: 101});
|
col.unshift({id: 101});
|
||||||
col.add({id: 101});
|
col.add({id: 101});
|
||||||
equal(col.length, 1);
|
equal(col.length, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: merge in duplicate models with {merge: true}", 3, function() {
|
test("merge in duplicate models with {merge: true}", 3, function() {
|
||||||
var col = new Backbone.Collection;
|
var col = new Backbone.Collection;
|
||||||
col.add([{id: 1, name: 'Moe'}, {id: 2, name: 'Curly'}, {id: 3, name: 'Larry'}]);
|
col.add([{id: 1, name: 'Moe'}, {id: 2, name: 'Curly'}, {id: 3, name: 'Larry'}]);
|
||||||
col.add({id: 1, name: 'Moses'});
|
col.add({id: 1, name: 'Moses'});
|
||||||
@@ -162,7 +184,7 @@ $(document).ready(function() {
|
|||||||
equal(col.first().get('name'), 'Tim');
|
equal(col.first().get('name'), 'Tim');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: add model to multiple collections", 10, function() {
|
test("add model to multiple collections", 10, function() {
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var e = new Backbone.Model({id: 10, label : 'e'});
|
var e = new Backbone.Model({id: 10, label : 'e'});
|
||||||
e.on('add', function(model, collection) {
|
e.on('add', function(model, collection) {
|
||||||
@@ -190,7 +212,7 @@ $(document).ready(function() {
|
|||||||
equal(e.collection, colE);
|
equal(e.collection, colE);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: add model with parse", 1, function() {
|
test("add model with parse", 1, function() {
|
||||||
var Model = Backbone.Model.extend({
|
var Model = Backbone.Model.extend({
|
||||||
parse: function(obj) {
|
parse: function(obj) {
|
||||||
obj.value += 1;
|
obj.value += 1;
|
||||||
@@ -204,7 +226,7 @@ $(document).ready(function() {
|
|||||||
equal(col.at(0).get('value'), 2);
|
equal(col.at(0).get('value'), 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: add model to collection with sort()-style comparator", 3, function() {
|
test("add model to collection with sort()-style comparator", 3, function() {
|
||||||
var col = new Backbone.Collection;
|
var col = new Backbone.Collection;
|
||||||
col.comparator = function(a, b) {
|
col.comparator = function(a, b) {
|
||||||
return a.get('name') < b.get('name') ? -1 : 1;
|
return a.get('name') < b.get('name') ? -1 : 1;
|
||||||
@@ -220,7 +242,7 @@ $(document).ready(function() {
|
|||||||
equal(col.indexOf(tom), 2);
|
equal(col.indexOf(tom), 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: comparator that depends on `this`", 1, function() {
|
test("comparator that depends on `this`", 2, function() {
|
||||||
var col = new Backbone.Collection;
|
var col = new Backbone.Collection;
|
||||||
col.negative = function(num) {
|
col.negative = function(num) {
|
||||||
return -num;
|
return -num;
|
||||||
@@ -229,10 +251,15 @@ $(document).ready(function() {
|
|||||||
return this.negative(a.id);
|
return this.negative(a.id);
|
||||||
};
|
};
|
||||||
col.add([{id: 1}, {id: 2}, {id: 3}]);
|
col.add([{id: 1}, {id: 2}, {id: 3}]);
|
||||||
equal(col.pluck('id').join(' '), '3 2 1');
|
deepEqual(col.pluck('id'), [3, 2, 1]);
|
||||||
|
col.comparator = function(a, b) {
|
||||||
|
return this.negative(b.id) - this.negative(a.id);
|
||||||
|
};
|
||||||
|
col.sort();
|
||||||
|
deepEqual(col.pluck('id'), [1, 2, 3]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: remove", 5, function() {
|
test("remove", 5, function() {
|
||||||
var removed = null;
|
var removed = null;
|
||||||
var otherRemoved = null;
|
var otherRemoved = null;
|
||||||
col.on('remove', function(model, col, options) {
|
col.on('remove', function(model, col, options) {
|
||||||
@@ -249,20 +276,20 @@ $(document).ready(function() {
|
|||||||
equal(otherRemoved, null);
|
equal(otherRemoved, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: shift and pop", 2, function() {
|
test("shift and pop", 2, function() {
|
||||||
var col = new Backbone.Collection([{a: 'a'}, {b: 'b'}, {c: 'c'}]);
|
var col = new Backbone.Collection([{a: 'a'}, {b: 'b'}, {c: 'c'}]);
|
||||||
equal(col.shift().get('a'), 'a');
|
equal(col.shift().get('a'), 'a');
|
||||||
equal(col.pop().get('c'), 'c');
|
equal(col.pop().get('c'), 'c');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: slice", 2, function() {
|
test("slice", 2, function() {
|
||||||
var col = new Backbone.Collection([{a: 'a'}, {b: 'b'}, {c: 'c'}]);
|
var col = new Backbone.Collection([{a: 'a'}, {b: 'b'}, {c: 'c'}]);
|
||||||
var array = col.slice(1, 3);
|
var array = col.slice(1, 3);
|
||||||
equal(array.length, 2);
|
equal(array.length, 2);
|
||||||
equal(array[0].get('b'), 'b');
|
equal(array[0].get('b'), 'b');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: events are unbound on remove", 3, function() {
|
test("events are unbound on remove", 3, function() {
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var dj = new Backbone.Model();
|
var dj = new Backbone.Model();
|
||||||
var emcees = new Backbone.Collection([dj]);
|
var emcees = new Backbone.Collection([dj]);
|
||||||
@@ -275,7 +302,7 @@ $(document).ready(function() {
|
|||||||
equal(counter, 1);
|
equal(counter, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: remove in multiple collections", 7, function() {
|
test("remove in multiple collections", 7, function() {
|
||||||
var modelData = {
|
var modelData = {
|
||||||
id : 5,
|
id : 5,
|
||||||
title : 'Othello'
|
title : 'Othello'
|
||||||
@@ -289,17 +316,17 @@ $(document).ready(function() {
|
|||||||
var colE = new Backbone.Collection([e]);
|
var colE = new Backbone.Collection([e]);
|
||||||
var colF = new Backbone.Collection([f]);
|
var colF = new Backbone.Collection([f]);
|
||||||
ok(e != f);
|
ok(e != f);
|
||||||
ok(colE.length == 1);
|
ok(colE.length === 1);
|
||||||
ok(colF.length == 1);
|
ok(colF.length === 1);
|
||||||
colE.remove(e);
|
colE.remove(e);
|
||||||
equal(passed, false);
|
equal(passed, false);
|
||||||
ok(colE.length == 0);
|
ok(colE.length === 0);
|
||||||
colF.remove(e);
|
colF.remove(e);
|
||||||
ok(colF.length == 0);
|
ok(colF.length === 0);
|
||||||
equal(passed, true);
|
equal(passed, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: remove same model in multiple collection", 16, function() {
|
test("remove same model in multiple collection", 16, function() {
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var e = new Backbone.Model({id: 5, title: 'Othello'});
|
var e = new Backbone.Model({id: 5, title: 'Othello'});
|
||||||
e.on('remove', function(model, collection) {
|
e.on('remove', function(model, collection) {
|
||||||
@@ -323,24 +350,26 @@ $(document).ready(function() {
|
|||||||
});
|
});
|
||||||
equal(colE, e.collection);
|
equal(colE, e.collection);
|
||||||
colF.remove(e);
|
colF.remove(e);
|
||||||
ok(colF.length == 0);
|
ok(colF.length === 0);
|
||||||
ok(colE.length == 1);
|
ok(colE.length === 1);
|
||||||
equal(counter, 1);
|
equal(counter, 1);
|
||||||
equal(colE, e.collection);
|
equal(colE, e.collection);
|
||||||
colE.remove(e);
|
colE.remove(e);
|
||||||
equal(null, e.collection);
|
equal(null, e.collection);
|
||||||
ok(colE.length == 0);
|
ok(colE.length === 0);
|
||||||
equal(counter, 2);
|
equal(counter, 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: model destroy removes from all collections", 3, function() {
|
test("model destroy removes from all collections", 3, function() {
|
||||||
var e = new Backbone.Model({id: 5, title: 'Othello'});
|
var e = new Backbone.Model({id: 5, title: 'Othello'});
|
||||||
e.sync = function(method, model, options) { options.success({}); };
|
e.sync = function(method, model, options) {
|
||||||
|
options.success(model, [], options);
|
||||||
|
};
|
||||||
var colE = new Backbone.Collection([e]);
|
var colE = new Backbone.Collection([e]);
|
||||||
var colF = new Backbone.Collection([e]);
|
var colF = new Backbone.Collection([e]);
|
||||||
e.destroy();
|
e.destroy();
|
||||||
ok(colE.length == 0);
|
ok(colE.length === 0);
|
||||||
ok(colF.length == 0);
|
ok(colF.length === 0);
|
||||||
equal(undefined, e.collection);
|
equal(undefined, e.collection);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -350,30 +379,47 @@ $(document).ready(function() {
|
|||||||
var colE = new Backbone.Collection([e]);
|
var colE = new Backbone.Collection([e]);
|
||||||
var colF = new Backbone.Collection([e]);
|
var colF = new Backbone.Collection([e]);
|
||||||
e.destroy();
|
e.destroy();
|
||||||
ok(colE.length == 0);
|
ok(colE.length === 0);
|
||||||
ok(colF.length == 0);
|
ok(colF.length === 0);
|
||||||
equal(undefined, e.collection);
|
equal(undefined, e.collection);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: fetch", 4, function() {
|
test("fetch", 4, function() {
|
||||||
col.fetch();
|
var collection = new Backbone.Collection;
|
||||||
equal(lastRequest.method, 'read');
|
collection.url = '/test';
|
||||||
equal(lastRequest.model, col);
|
collection.fetch();
|
||||||
equal(lastRequest.options.parse, true);
|
equal(this.syncArgs.method, 'read');
|
||||||
|
equal(this.syncArgs.model, collection);
|
||||||
|
equal(this.syncArgs.options.parse, true);
|
||||||
|
|
||||||
col.fetch({parse: false});
|
collection.fetch({parse: false});
|
||||||
equal(lastRequest.options.parse, false);
|
equal(this.syncArgs.options.parse, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: create", 4, function() {
|
test("ensure fetch only parses once", 1, function() {
|
||||||
var model = col.create({label: 'f'}, {wait: true});
|
var collection = new Backbone.Collection;
|
||||||
equal(lastRequest.method, 'create');
|
var counter = 0;
|
||||||
equal(lastRequest.model, model);
|
collection.parse = function(models) {
|
||||||
|
counter++;
|
||||||
|
return models;
|
||||||
|
};
|
||||||
|
collection.url = '/test';
|
||||||
|
collection.fetch();
|
||||||
|
this.syncArgs.options.success([]);
|
||||||
|
equal(counter, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("create", 4, function() {
|
||||||
|
var collection = new Backbone.Collection;
|
||||||
|
collection.url = '/test';
|
||||||
|
var model = collection.create({label: 'f'}, {wait: true});
|
||||||
|
equal(this.syncArgs.method, 'create');
|
||||||
|
equal(this.syncArgs.model, model);
|
||||||
equal(model.get('label'), 'f');
|
equal(model.get('label'), 'f');
|
||||||
equal(model.collection, col);
|
equal(model.collection, collection);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: create enforces validation", 1, function() {
|
test("create with validate:true enforces validation", 1, function() {
|
||||||
var ValidatingModel = Backbone.Model.extend({
|
var ValidatingModel = Backbone.Model.extend({
|
||||||
validate: function(attrs) {
|
validate: function(attrs) {
|
||||||
return "fail";
|
return "fail";
|
||||||
@@ -383,10 +429,10 @@ $(document).ready(function() {
|
|||||||
model: ValidatingModel
|
model: ValidatingModel
|
||||||
});
|
});
|
||||||
var col = new ValidatingCollection();
|
var col = new ValidatingCollection();
|
||||||
equal(col.create({"foo":"bar"}), false);
|
equal(col.create({"foo":"bar"}, {validate:true}), false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: a failing create runs the error callback", 1, function() {
|
test("a failing create returns model with errors", function() {
|
||||||
var ValidatingModel = Backbone.Model.extend({
|
var ValidatingModel = Backbone.Model.extend({
|
||||||
validate: function(attrs) {
|
validate: function(attrs) {
|
||||||
return "fail";
|
return "fail";
|
||||||
@@ -395,14 +441,13 @@ $(document).ready(function() {
|
|||||||
var ValidatingCollection = Backbone.Collection.extend({
|
var ValidatingCollection = Backbone.Collection.extend({
|
||||||
model: ValidatingModel
|
model: ValidatingModel
|
||||||
});
|
});
|
||||||
var flag = false;
|
|
||||||
var callback = function(model, error) { flag = true; };
|
|
||||||
var col = new ValidatingCollection();
|
var col = new ValidatingCollection();
|
||||||
col.create({"foo":"bar"}, { error: callback });
|
var m = col.create({"foo":"bar"});
|
||||||
equal(flag, true);
|
equal(m.validationError, 'fail');
|
||||||
|
equal(col.length, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("collection: initialize", 1, function() {
|
test("initialize", 1, function() {
|
||||||
var Collection = Backbone.Collection.extend({
|
var Collection = Backbone.Collection.extend({
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
this.one = 1;
|
this.one = 1;
|
||||||
@@ -412,11 +457,11 @@ $(document).ready(function() {
|
|||||||
equal(coll.one, 1);
|
equal(coll.one, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: toJSON", 1, function() {
|
test("toJSON", 1, function() {
|
||||||
equal(JSON.stringify(col), '[{"id":3,"label":"a"},{"id":2,"label":"b"},{"id":1,"label":"c"},{"id":0,"label":"d"}]');
|
equal(JSON.stringify(col), '[{"id":3,"label":"a"},{"id":2,"label":"b"},{"id":1,"label":"c"},{"id":0,"label":"d"}]');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: where", 6, function() {
|
test("where", 6, function() {
|
||||||
var coll = new Backbone.Collection([
|
var coll = new Backbone.Collection([
|
||||||
{a: 1},
|
{a: 1},
|
||||||
{a: 1},
|
{a: 1},
|
||||||
@@ -432,7 +477,7 @@ $(document).ready(function() {
|
|||||||
equal(coll.where({a: 1, b: 2}).length, 1);
|
equal(coll.where({a: 1, b: 2}).length, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: Underscore methods", 13, function() {
|
test("Underscore methods", 13, function() {
|
||||||
equal(col.map(function(model){ return model.get('label'); }).join(' '), 'a b c d');
|
equal(col.map(function(model){ return model.get('label'); }).join(' '), 'a b c d');
|
||||||
equal(col.any(function(model){ return model.id === 100; }), false);
|
equal(col.any(function(model){ return model.id === 100; }), false);
|
||||||
equal(col.any(function(model){ return model.id === 0; }), true);
|
equal(col.any(function(model){ return model.id === 0; }), true);
|
||||||
@@ -452,9 +497,21 @@ $(document).ready(function() {
|
|||||||
[4, 0]);
|
[4, 0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: reset", 10, function() {
|
test("sortedIndex", function () {
|
||||||
|
var model = new Backbone.Model({key: 2});
|
||||||
|
var collection = new (Backbone.Collection.extend({
|
||||||
|
comparator: 'key'
|
||||||
|
}))([model, {key: 1}]);
|
||||||
|
equal(collection.sortedIndex(model), 1);
|
||||||
|
equal(collection.sortedIndex(model, 'key'), 1);
|
||||||
|
equal(collection.sortedIndex(model, function (model) {
|
||||||
|
return model.get('key');
|
||||||
|
}), 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("reset", 10, function() {
|
||||||
var resetCount = 0;
|
var resetCount = 0;
|
||||||
var models = col.models;
|
var models = col.models.slice();
|
||||||
col.on('reset', function() { resetCount += 1; });
|
col.on('reset', function() { resetCount += 1; });
|
||||||
col.reset([]);
|
col.reset([]);
|
||||||
equal(resetCount, 1);
|
equal(resetCount, 1);
|
||||||
@@ -471,7 +528,7 @@ $(document).ready(function() {
|
|||||||
ok(_.isEqual(col.last().attributes, d.attributes));
|
ok(_.isEqual(col.last().attributes, d.attributes));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: reset passes caller options", 3, function() {
|
test("reset passes caller options", 3, function() {
|
||||||
var Model = Backbone.Model.extend({
|
var Model = Backbone.Model.extend({
|
||||||
initialize: function(attrs, options) {
|
initialize: function(attrs, options) {
|
||||||
this.model_parameter = options.model_parameter;
|
this.model_parameter = options.model_parameter;
|
||||||
@@ -485,14 +542,14 @@ $(document).ready(function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: trigger custom events on models", 1, function() {
|
test("trigger custom events on models", 1, function() {
|
||||||
var fired = null;
|
var fired = null;
|
||||||
a.on("custom", function() { fired = true; });
|
a.on("custom", function() { fired = true; });
|
||||||
a.trigger("custom");
|
a.trigger("custom");
|
||||||
equal(fired, true);
|
equal(fired, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: add does not alter arguments", 2, function(){
|
test("add does not alter arguments", 2, function(){
|
||||||
var attrs = {};
|
var attrs = {};
|
||||||
var models = [attrs];
|
var models = [attrs];
|
||||||
new Backbone.Collection().add(models);
|
new Backbone.Collection().add(models);
|
||||||
@@ -501,16 +558,17 @@ $(document).ready(function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("#714: access `model.collection` in a brand new model.", 2, function() {
|
test("#714: access `model.collection` in a brand new model.", 2, function() {
|
||||||
var col = new Backbone.Collection;
|
var collection = new Backbone.Collection;
|
||||||
|
collection.url = '/test';
|
||||||
var Model = Backbone.Model.extend({
|
var Model = Backbone.Model.extend({
|
||||||
set: function(attrs) {
|
set: function(attrs) {
|
||||||
equal(attrs.prop, 'value');
|
equal(attrs.prop, 'value');
|
||||||
equal(this.collection, col);
|
equal(this.collection, collection);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
col.model = Model;
|
collection.model = Model;
|
||||||
col.create({prop: 'value'});
|
collection.create({prop: 'value'});
|
||||||
});
|
});
|
||||||
|
|
||||||
test("#574, remove its own reference to the .models array.", 2, function() {
|
test("#574, remove its own reference to the .models array.", 2, function() {
|
||||||
@@ -522,8 +580,7 @@ $(document).ready(function() {
|
|||||||
equal(col.length, 0);
|
equal(col.length, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("#861, adding models to a collection which do not pass validation", 1, function() {
|
test("#861, adding models to a collection which do not pass validation, with validate:true", function() {
|
||||||
raises(function() {
|
|
||||||
var Model = Backbone.Model.extend({
|
var Model = Backbone.Model.extend({
|
||||||
validate: function(attrs) {
|
validate: function(attrs) {
|
||||||
if (attrs.id == 3) return "id can't be 3";
|
if (attrs.id == 3) return "id can't be 3";
|
||||||
@@ -534,46 +591,29 @@ $(document).ready(function() {
|
|||||||
model: Model
|
model: Model
|
||||||
});
|
});
|
||||||
|
|
||||||
var col = new Collection;
|
var collection = new Collection;
|
||||||
|
collection.on("error", function() { ok(true); });
|
||||||
|
|
||||||
col.add([{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}, {id: 6}]);
|
collection.add([{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}, {id: 6}], {validate:true});
|
||||||
}, function(e) {
|
deepEqual(collection.pluck('id'), [1, 2, 4, 5, 6]);
|
||||||
return e.message === "Can't add an invalid model to a collection";
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: index with comparator", 4, function() {
|
test("Invalid models are discarded with validate:true.", 5, function() {
|
||||||
var counter = 0;
|
var collection = new Backbone.Collection;
|
||||||
var col = new Backbone.Collection([{id: 2}, {id: 4}], {
|
collection.on('test', function() { ok(true); });
|
||||||
comparator: function(model){ return model.id; }
|
collection.model = Backbone.Model.extend({
|
||||||
}).on('add', function(model, colleciton, options){
|
|
||||||
if (model.id == 1) {
|
|
||||||
equal(options.index, 0);
|
|
||||||
equal(counter++, 0);
|
|
||||||
}
|
|
||||||
if (model.id == 3) {
|
|
||||||
equal(options.index, 2);
|
|
||||||
equal(counter++, 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
col.add([{id: 3}, {id: 1}]);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("Collection: throwing during add leaves consistent state", 4, function() {
|
|
||||||
var col = new Backbone.Collection();
|
|
||||||
col.on('test', function() { ok(false); });
|
|
||||||
col.model = Backbone.Model.extend({
|
|
||||||
validate: function(attrs){ if (!attrs.valid) return 'invalid'; }
|
validate: function(attrs){ if (!attrs.valid) return 'invalid'; }
|
||||||
});
|
});
|
||||||
var model = new col.model({id: 1, valid: true});
|
var model = new collection.model({id: 1, valid: true});
|
||||||
raises(function() { col.add([model, {id: 2}]); });
|
collection.add([model, {id: 2}], {validate:true});
|
||||||
model.trigger('test');
|
model.trigger('test');
|
||||||
ok(!col.getByCid(model.cid));
|
ok(collection.get(model.cid));
|
||||||
ok(!col.get(1));
|
ok(collection.get(1));
|
||||||
equal(col.length, 0);
|
ok(!collection.get(2));
|
||||||
|
equal(collection.length, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: multiple copies of the same model", 3, function() {
|
test("multiple copies of the same model", 3, function() {
|
||||||
var col = new Backbone.Collection();
|
var col = new Backbone.Collection();
|
||||||
var model = new Backbone.Model();
|
var model = new Backbone.Model();
|
||||||
col.add([model, model]);
|
col.add([model, model]);
|
||||||
@@ -606,7 +646,7 @@ $(document).ready(function() {
|
|||||||
ok(!collection.get('undefined'));
|
ok(!collection.get('undefined'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Collection: falsy comparator", 4, function(){
|
test("falsy comparator", 4, function(){
|
||||||
var Col = Backbone.Collection.extend({
|
var Col = Backbone.Collection.extend({
|
||||||
comparator: function(model){ return model.id; }
|
comparator: function(model){ return model.id; }
|
||||||
});
|
});
|
||||||
@@ -629,35 +669,47 @@ $(document).ready(function() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
col.sync = m.sync = function( method, collection, options ){
|
col.sync = m.sync = function( method, collection, options ){
|
||||||
options.success();
|
options.success(collection, [], options);
|
||||||
};
|
};
|
||||||
col.fetch(opts);
|
col.fetch(opts);
|
||||||
col.create(m, opts);
|
col.create(m, opts);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("#1412 - Trigger 'sync' event.", 2, function() {
|
test("#1412 - Trigger 'request' and 'sync' events.", 4, function() {
|
||||||
var collection = new Backbone.Collection([], {
|
var collection = new Backbone.Collection;
|
||||||
model: Backbone.Model.extend({
|
collection.url = '/test';
|
||||||
sync: function(method, model, options) {
|
Backbone.ajax = function(settings){ settings.success(); };
|
||||||
options.success();
|
|
||||||
}
|
collection.on('request', function(obj, xhr, options) {
|
||||||
})
|
ok(obj === collection, "collection has correct 'request' event after fetching");
|
||||||
|
});
|
||||||
|
collection.on('sync', function(obj, response, options) {
|
||||||
|
ok(obj === collection, "collection has correct 'sync' event after fetching");
|
||||||
});
|
});
|
||||||
collection.sync = function(method, model, options) { options.success(); };
|
|
||||||
collection.on('sync', function() { ok(true); });
|
|
||||||
collection.fetch();
|
collection.fetch();
|
||||||
|
collection.off();
|
||||||
|
|
||||||
|
collection.on('request', function(obj, xhr, options) {
|
||||||
|
ok(obj === collection.get(1), "collection has correct 'request' event after one of its models save");
|
||||||
|
});
|
||||||
|
collection.on('sync', function(obj, response, options) {
|
||||||
|
ok(obj === collection.get(1), "collection has correct 'sync' event after one of its models save");
|
||||||
|
});
|
||||||
collection.create({id: 1});
|
collection.create({id: 1});
|
||||||
|
collection.off();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("#1447 - create with wait adds model.", function() {
|
test("#1447 - create with wait adds model.", 1, function() {
|
||||||
var collection = new Backbone.Collection;
|
var collection = new Backbone.Collection;
|
||||||
var model = new Backbone.Model;
|
var model = new Backbone.Model;
|
||||||
model.sync = function(method, model, options){ options.success(); };
|
model.sync = function(method, model, options){
|
||||||
|
options.success(model, [], options);
|
||||||
|
};
|
||||||
collection.on('add', function(){ ok(true); });
|
collection.on('add', function(){ ok(true); });
|
||||||
collection.create(model, {wait: true});
|
collection.create(model, {wait: true});
|
||||||
});
|
});
|
||||||
|
|
||||||
test("#1448 - add sorts collection after merge.", function() {
|
test("#1448 - add sorts collection after merge.", 1, function() {
|
||||||
var collection = new Backbone.Collection([
|
var collection = new Backbone.Collection([
|
||||||
{id: 1, x: 1},
|
{id: 1, x: 1},
|
||||||
{id: 2, x: 2}
|
{id: 2, x: 2}
|
||||||
@@ -666,4 +718,299 @@ $(document).ready(function() {
|
|||||||
collection.add({id: 1, x: 3}, {merge: true});
|
collection.add({id: 1, x: 3}, {merge: true});
|
||||||
deepEqual(collection.pluck('id'), [2, 1]);
|
deepEqual(collection.pluck('id'), [2, 1]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("#1655 - groupBy can be used with a string argument.", 3, function() {
|
||||||
|
var collection = new Backbone.Collection([{x: 1}, {x: 2}]);
|
||||||
|
var grouped = collection.groupBy('x');
|
||||||
|
strictEqual(_.keys(grouped).length, 2);
|
||||||
|
strictEqual(grouped[1][0].get('x'), 1);
|
||||||
|
strictEqual(grouped[2][0].get('x'), 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1655 - sortBy can be used with a string argument.", 1, function() {
|
||||||
|
var collection = new Backbone.Collection([{x: 3}, {x: 1}, {x: 2}]);
|
||||||
|
var values = _.map(collection.sortBy('x'), function(model) {
|
||||||
|
return model.get('x');
|
||||||
|
});
|
||||||
|
deepEqual(values, [1, 2, 3]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1604 - Removal during iteration.", 0, function() {
|
||||||
|
var collection = new Backbone.Collection([{}, {}]);
|
||||||
|
collection.on('add', function() {
|
||||||
|
collection.at(0).destroy();
|
||||||
|
});
|
||||||
|
collection.add({}, {at: 0});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1638 - `sort` during `add` triggers correctly.", function() {
|
||||||
|
var collection = new Backbone.Collection;
|
||||||
|
collection.comparator = function(model) { return model.get('x'); };
|
||||||
|
var added = [];
|
||||||
|
collection.on('add', function(model) {
|
||||||
|
model.set({x: 3});
|
||||||
|
collection.sort();
|
||||||
|
added.push(model.id);
|
||||||
|
});
|
||||||
|
collection.add([{id: 1, x: 1}, {id: 2, x: 2}]);
|
||||||
|
deepEqual(added, [1, 2]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("fetch parses models by default", 1, function() {
|
||||||
|
var model = {};
|
||||||
|
var Collection = Backbone.Collection.extend({
|
||||||
|
url: 'test',
|
||||||
|
model: Backbone.Model.extend({
|
||||||
|
parse: function(resp) {
|
||||||
|
strictEqual(resp, model);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
new Collection().fetch();
|
||||||
|
this.ajaxSettings.success([model]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("`sort` shouldn't always fire on `add`", 1, function() {
|
||||||
|
var c = new Backbone.Collection([{id: 1}, {id: 2}, {id: 3}], {
|
||||||
|
comparator: 'id'
|
||||||
|
});
|
||||||
|
c.sort = function(){ ok(true); };
|
||||||
|
c.add([]);
|
||||||
|
c.add({id: 1});
|
||||||
|
c.add([{id: 2}, {id: 3}]);
|
||||||
|
c.add({id: 4});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1407 parse option on constructor parses collection and models", 2, function() {
|
||||||
|
var model = {
|
||||||
|
namespace : [{id: 1}, {id:2}]
|
||||||
|
};
|
||||||
|
var Collection = Backbone.Collection.extend({
|
||||||
|
model: Backbone.Model.extend({
|
||||||
|
parse: function(model) {
|
||||||
|
model.name = 'test';
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
parse: function(model) {
|
||||||
|
return model.namespace;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var c = new Collection(model, {parse:true});
|
||||||
|
|
||||||
|
equal(c.length, 2);
|
||||||
|
equal(c.at(0).get('name'), 'test');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1407 parse option on reset parses collection and models", 2, function() {
|
||||||
|
var model = {
|
||||||
|
namespace : [{id: 1}, {id:2}]
|
||||||
|
};
|
||||||
|
var Collection = Backbone.Collection.extend({
|
||||||
|
model: Backbone.Model.extend({
|
||||||
|
parse: function(model) {
|
||||||
|
model.name = 'test';
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
parse: function(model) {
|
||||||
|
return model.namespace;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var c = new Collection();
|
||||||
|
c.reset(model, {parse:true});
|
||||||
|
|
||||||
|
equal(c.length, 2);
|
||||||
|
equal(c.at(0).get('name'), 'test');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test("Reset includes previous models in triggered event.", 1, function() {
|
||||||
|
var model = new Backbone.Model();
|
||||||
|
var collection = new Backbone.Collection([model])
|
||||||
|
.on('reset', function(collection, options) {
|
||||||
|
deepEqual(options.previousModels, [model]);
|
||||||
|
});
|
||||||
|
collection.reset([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("update", function() {
|
||||||
|
var m1 = new Backbone.Model();
|
||||||
|
var m2 = new Backbone.Model({id: 2});
|
||||||
|
var m3 = new Backbone.Model();
|
||||||
|
var c = new Backbone.Collection([m1, m2]);
|
||||||
|
|
||||||
|
// Test add/change/remove events
|
||||||
|
c.on('add', function(model) {
|
||||||
|
strictEqual(model, m3);
|
||||||
|
});
|
||||||
|
c.on('change', function(model) {
|
||||||
|
strictEqual(model, m2);
|
||||||
|
});
|
||||||
|
c.on('remove', function(model) {
|
||||||
|
strictEqual(model, m1);
|
||||||
|
});
|
||||||
|
|
||||||
|
// remove: false doesn't remove any models
|
||||||
|
c.update([], {remove: false});
|
||||||
|
strictEqual(c.length, 2);
|
||||||
|
|
||||||
|
// add: false doesn't add any models
|
||||||
|
c.update([m1, m2, m3], {add: false});
|
||||||
|
strictEqual(c.length, 2);
|
||||||
|
|
||||||
|
// merge: false doesn't change any models
|
||||||
|
c.update([m1, {id: 2, a: 1}], {merge: false});
|
||||||
|
strictEqual(m2.get('a'), void 0);
|
||||||
|
|
||||||
|
// add: false, remove: false only merges existing models
|
||||||
|
c.update([m1, {id: 2, a: 0}, m3, {id: 4}], {add: false, remove: false});
|
||||||
|
strictEqual(c.length, 2);
|
||||||
|
strictEqual(m2.get('a'), 0);
|
||||||
|
|
||||||
|
// default options add/remove/merge as appropriate
|
||||||
|
c.update([{id: 2, a: 1}, m3]);
|
||||||
|
strictEqual(c.length, 2);
|
||||||
|
strictEqual(m2.get('a'), 1);
|
||||||
|
|
||||||
|
// Test removing models not passing an argument
|
||||||
|
c.off('remove').on('remove', function(model) {
|
||||||
|
ok(model === m2 || model === m3);
|
||||||
|
});
|
||||||
|
c.update([]);
|
||||||
|
strictEqual(c.length, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("update with only cids", 3, function() {
|
||||||
|
var m1 = new Backbone.Model;
|
||||||
|
var m2 = new Backbone.Model;
|
||||||
|
var c = new Backbone.Collection;
|
||||||
|
c.update([m1, m2]);
|
||||||
|
equal(c.length, 2);
|
||||||
|
c.update([m1]);
|
||||||
|
equal(c.length, 1);
|
||||||
|
c.update([m1, m1, m1, m2, m2], {remove: false});
|
||||||
|
equal(c.length, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("update with only idAttribute", 3, function() {
|
||||||
|
var m1 = { _id: 1 };
|
||||||
|
var m2 = { _id: 2 };
|
||||||
|
var col = Backbone.Collection.extend({
|
||||||
|
model: Backbone.Model.extend({
|
||||||
|
idAttribute: '_id'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
var c = new col;
|
||||||
|
c.update([m1, m2]);
|
||||||
|
equal(c.length, 2);
|
||||||
|
c.update([m1]);
|
||||||
|
equal(c.length, 1);
|
||||||
|
c.update([m1, m1, m1, m2, m2], {remove: false});
|
||||||
|
equal(c.length, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("update + merge with default values defined", function() {
|
||||||
|
var Model = Backbone.Model.extend({
|
||||||
|
defaults: {
|
||||||
|
key: 'value'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var m = new Model({id: 1});
|
||||||
|
var col = new Backbone.Collection([m], {model: Model});
|
||||||
|
equal(col.first().get('key'), 'value');
|
||||||
|
|
||||||
|
col.update({id: 1, key: 'other'});
|
||||||
|
equal(col.first().get('key'), 'other');
|
||||||
|
|
||||||
|
col.update({id: 1, other: 'value'});
|
||||||
|
equal(col.first().get('key'), 'other');
|
||||||
|
equal(col.length, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1894 - Push should not trigger a sort", 0, function() {
|
||||||
|
var Collection = Backbone.Collection.extend({
|
||||||
|
comparator: 'id',
|
||||||
|
sort: function() {
|
||||||
|
ok(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
new Collection().push({id: 1});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("`update` with non-normal id", function() {
|
||||||
|
var Collection = Backbone.Collection.extend({
|
||||||
|
model: Backbone.Model.extend({idAttribute: '_id'})
|
||||||
|
});
|
||||||
|
var collection = new Collection({_id: 1});
|
||||||
|
collection.update([{_id: 1, a: 1}], {add: false});
|
||||||
|
equal(collection.first().get('a'), 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1894 - `sort` can optionally be turned off", 0, function() {
|
||||||
|
var Collection = Backbone.Collection.extend({
|
||||||
|
comparator: 'id',
|
||||||
|
sort: function() { ok(true); }
|
||||||
|
});
|
||||||
|
new Collection().add({id: 1}, {sort: false});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1915 - `parse` data in the right order in `update`", function() {
|
||||||
|
var collection = new (Backbone.Collection.extend({
|
||||||
|
parse: function (data) {
|
||||||
|
strictEqual(data.status, 'ok');
|
||||||
|
return data.data;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
var res = {status: 'ok', data:[{id: 1}]};
|
||||||
|
collection.update(res, {parse: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest("#1939 - `parse` is passed `options`", 1, function () {
|
||||||
|
var collection = new (Backbone.Collection.extend({
|
||||||
|
url: '/',
|
||||||
|
parse: function (data, options) {
|
||||||
|
strictEqual(options.xhr.someHeader, 'headerValue');
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
var ajax = Backbone.ajax;
|
||||||
|
Backbone.ajax = function (params) {
|
||||||
|
_.defer(params.success);
|
||||||
|
return {someHeader: 'headerValue'};
|
||||||
|
};
|
||||||
|
collection.fetch({
|
||||||
|
success: function () { start(); }
|
||||||
|
});
|
||||||
|
Backbone.ajax = ajax;
|
||||||
|
});
|
||||||
|
|
||||||
|
test("`add` only `sort`s when necessary", 2, function () {
|
||||||
|
var collection = new (Backbone.Collection.extend({
|
||||||
|
comparator: 'a'
|
||||||
|
}))([{id: 1}, {id: 2}, {id: 3}]);
|
||||||
|
collection.on('sort', function () { ok(true); });
|
||||||
|
collection.add({id: 4}); // do sort, new model
|
||||||
|
collection.add({id: 1, a: 1}, {merge: true}); // do sort, comparator change
|
||||||
|
collection.add({id: 1, b: 1}, {merge: true}); // don't sort, no comparator change
|
||||||
|
collection.add({id: 1, a: 1}, {merge: true}); // don't sort, no comparator change
|
||||||
|
collection.add(collection.models); // don't sort, nothing new
|
||||||
|
collection.add(collection.models, {merge: true}); // don't sort
|
||||||
|
});
|
||||||
|
|
||||||
|
test("`add` only `sort`s when necessary with comparator function", 3, function () {
|
||||||
|
var collection = new (Backbone.Collection.extend({
|
||||||
|
comparator: function(a, b) {
|
||||||
|
a.get('a') > b.get('a') ? 1 : (a.get('a') < b.get('a') ? -1 : 0);
|
||||||
|
}
|
||||||
|
}))([{id: 1}, {id: 2}, {id: 3}]);
|
||||||
|
collection.on('sort', function () { ok(true); });
|
||||||
|
collection.add({id: 4}); // do sort, new model
|
||||||
|
collection.add({id: 1, a: 1}, {merge: true}); // do sort, model change
|
||||||
|
collection.add({id: 1, b: 1}, {merge: true}); // do sort, model change
|
||||||
|
collection.add({id: 1, a: 1}, {merge: true}); // don't sort, no model change
|
||||||
|
collection.add(collection.models); // don't sort, nothing new
|
||||||
|
collection.add(collection.models, {merge: true}); // don't sort
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
45
vendor/backbone/test/environment.js
vendored
Normal file
45
vendor/backbone/test/environment.js
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
(function() {
|
||||||
|
|
||||||
|
var Environment = this.Environment = function(){};
|
||||||
|
|
||||||
|
_.extend(Environment.prototype, {
|
||||||
|
|
||||||
|
ajax: Backbone.ajax,
|
||||||
|
|
||||||
|
sync: Backbone.sync,
|
||||||
|
|
||||||
|
emulateHTTP: Backbone.emulateHTTP,
|
||||||
|
|
||||||
|
emulateJSON: Backbone.emulateJSON,
|
||||||
|
|
||||||
|
setup: function() {
|
||||||
|
var env = this;
|
||||||
|
|
||||||
|
// Capture ajax settings for comparison.
|
||||||
|
Backbone.ajax = function(settings) {
|
||||||
|
env.ajaxSettings = settings;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Capture the arguments to Backbone.sync for comparison.
|
||||||
|
Backbone.sync = function(method, model, options) {
|
||||||
|
env.syncArgs = {
|
||||||
|
method: method,
|
||||||
|
model: model,
|
||||||
|
options: options
|
||||||
|
};
|
||||||
|
env.sync.apply(this, arguments);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
teardown: function() {
|
||||||
|
this.syncArgs = null;
|
||||||
|
this.ajaxSettings = null;
|
||||||
|
Backbone.sync = this.sync;
|
||||||
|
Backbone.ajax = this.ajax;
|
||||||
|
Backbone.emulateHTTP = this.emulateHTTP;
|
||||||
|
Backbone.emulateJSON = this.emulateJSON;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
})();
|
||||||
230
vendor/backbone/test/events.js
vendored
230
vendor/backbone/test/events.js
vendored
@@ -2,7 +2,7 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
module("Backbone.Events");
|
module("Backbone.Events");
|
||||||
|
|
||||||
test("Events: on and trigger", 2, function() {
|
test("on and trigger", 2, function() {
|
||||||
var obj = { counter: 0 };
|
var obj = { counter: 0 };
|
||||||
_.extend(obj,Backbone.Events);
|
_.extend(obj,Backbone.Events);
|
||||||
obj.on('event', function() { obj.counter += 1; });
|
obj.on('event', function() { obj.counter += 1; });
|
||||||
@@ -15,9 +15,9 @@ $(document).ready(function() {
|
|||||||
equal(obj.counter, 5, 'counter should be incremented five times.');
|
equal(obj.counter, 5, 'counter should be incremented five times.');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Events: binding and triggering multiple events", 4, function() {
|
test("binding and triggering multiple events", 4, function() {
|
||||||
var obj = { counter: 0 };
|
var obj = { counter: 0 };
|
||||||
_.extend(obj,Backbone.Events);
|
_.extend(obj, Backbone.Events);
|
||||||
|
|
||||||
obj.on('a b c', function() { obj.counter += 1; });
|
obj.on('a b c', function() { obj.counter += 1; });
|
||||||
|
|
||||||
@@ -35,7 +35,94 @@ $(document).ready(function() {
|
|||||||
equal(obj.counter, 5);
|
equal(obj.counter, 5);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Events: trigger all for each event", 3, function() {
|
test("binding and triggering with event maps", function() {
|
||||||
|
var obj = { counter: 0 };
|
||||||
|
_.extend(obj, Backbone.Events);
|
||||||
|
|
||||||
|
var increment = function() {
|
||||||
|
this.counter += 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.on({
|
||||||
|
a: increment,
|
||||||
|
b: increment,
|
||||||
|
c: increment
|
||||||
|
}, obj);
|
||||||
|
|
||||||
|
obj.trigger('a');
|
||||||
|
equal(obj.counter, 1);
|
||||||
|
|
||||||
|
obj.trigger('a b');
|
||||||
|
equal(obj.counter, 3);
|
||||||
|
|
||||||
|
obj.trigger('c');
|
||||||
|
equal(obj.counter, 4);
|
||||||
|
|
||||||
|
obj.off({
|
||||||
|
a: increment,
|
||||||
|
c: increment
|
||||||
|
}, obj);
|
||||||
|
obj.trigger('a b c');
|
||||||
|
equal(obj.counter, 5);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("listenTo and stopListening", 1, function() {
|
||||||
|
var a = _.extend({}, Backbone.Events);
|
||||||
|
var b = _.extend({}, Backbone.Events);
|
||||||
|
a.listenTo(b, 'all', function(){ ok(true); });
|
||||||
|
b.trigger('anything');
|
||||||
|
a.listenTo(b, 'all', function(){ ok(false); });
|
||||||
|
a.stopListening();
|
||||||
|
b.trigger('anything');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("listenTo and stopListening with event maps", 4, function() {
|
||||||
|
var a = _.extend({}, Backbone.Events);
|
||||||
|
var b = _.extend({}, Backbone.Events);
|
||||||
|
var cb = function(){ ok(true); };
|
||||||
|
a.listenTo(b, {event: cb});
|
||||||
|
b.trigger('event');
|
||||||
|
a.listenTo(b, {event2: cb});
|
||||||
|
b.on('event2', cb);
|
||||||
|
a.stopListening(b, {event2: cb});
|
||||||
|
b.trigger('event event2');
|
||||||
|
a.stopListening();
|
||||||
|
b.trigger('event event2');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("stopListening with omitted args", 2, function () {
|
||||||
|
var a = _.extend({}, Backbone.Events);
|
||||||
|
var b = _.extend({}, Backbone.Events);
|
||||||
|
var cb = function () { ok(true); };
|
||||||
|
a.listenTo(b, 'event', cb);
|
||||||
|
b.on('event', cb);
|
||||||
|
a.listenTo(b, 'event2', cb);
|
||||||
|
a.stopListening(null, {event: cb});
|
||||||
|
b.trigger('event event2');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("listenTo yourself", 1, function(){
|
||||||
|
var e = _.extend({}, Backbone.Events);
|
||||||
|
e.listenTo(e, "foo", function(){ ok(true); });
|
||||||
|
e.trigger("foo");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("listenTo yourself cleans yourself up with stopListening", 1, function(){
|
||||||
|
var e = _.extend({}, Backbone.Events);
|
||||||
|
e.listenTo(e, "foo", function(){ ok(true); });
|
||||||
|
e.trigger("foo");
|
||||||
|
e.stopListening();
|
||||||
|
e.trigger("foo");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("listenTo with empty callback doesn't throw an error", 1, function(){
|
||||||
|
var e = _.extend({}, Backbone.Events);
|
||||||
|
e.listenTo(e, "foo", null);
|
||||||
|
e.trigger("foo");
|
||||||
|
ok(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("trigger all for each event", 3, function() {
|
||||||
var a, b, obj = { counter: 0 };
|
var a, b, obj = { counter: 0 };
|
||||||
_.extend(obj, Backbone.Events);
|
_.extend(obj, Backbone.Events);
|
||||||
obj.on('all', function(event) {
|
obj.on('all', function(event) {
|
||||||
@@ -49,7 +136,7 @@ $(document).ready(function() {
|
|||||||
equal(obj.counter, 2);
|
equal(obj.counter, 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Events: on, then unbind all functions", 1, function() {
|
test("on, then unbind all functions", 1, function() {
|
||||||
var obj = { counter: 0 };
|
var obj = { counter: 0 };
|
||||||
_.extend(obj,Backbone.Events);
|
_.extend(obj,Backbone.Events);
|
||||||
var callback = function() { obj.counter += 1; };
|
var callback = function() { obj.counter += 1; };
|
||||||
@@ -60,7 +147,7 @@ $(document).ready(function() {
|
|||||||
equal(obj.counter, 1, 'counter should have only been incremented once.');
|
equal(obj.counter, 1, 'counter should have only been incremented once.');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Events: bind two callbacks, unbind only one", 2, function() {
|
test("bind two callbacks, unbind only one", 2, function() {
|
||||||
var obj = { counterA: 0, counterB: 0 };
|
var obj = { counterA: 0, counterB: 0 };
|
||||||
_.extend(obj,Backbone.Events);
|
_.extend(obj,Backbone.Events);
|
||||||
var callback = function() { obj.counterA += 1; };
|
var callback = function() { obj.counterA += 1; };
|
||||||
@@ -73,7 +160,7 @@ $(document).ready(function() {
|
|||||||
equal(obj.counterB, 2, 'counterB should have been incremented twice.');
|
equal(obj.counterB, 2, 'counterB should have been incremented twice.');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Events: unbind a callback in the midst of it firing", 1, function() {
|
test("unbind a callback in the midst of it firing", 1, function() {
|
||||||
var obj = {counter: 0};
|
var obj = {counter: 0};
|
||||||
_.extend(obj, Backbone.Events);
|
_.extend(obj, Backbone.Events);
|
||||||
var callback = function() {
|
var callback = function() {
|
||||||
@@ -87,7 +174,7 @@ $(document).ready(function() {
|
|||||||
equal(obj.counter, 1, 'the callback should have been unbound.');
|
equal(obj.counter, 1, 'the callback should have been unbound.');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Events: two binds that unbind themeselves", 2, function() {
|
test("two binds that unbind themeselves", 2, function() {
|
||||||
var obj = { counterA: 0, counterB: 0 };
|
var obj = { counterA: 0, counterB: 0 };
|
||||||
_.extend(obj,Backbone.Events);
|
_.extend(obj,Backbone.Events);
|
||||||
var incrA = function(){ obj.counterA += 1; obj.off('event', incrA); };
|
var incrA = function(){ obj.counterA += 1; obj.off('event', incrA); };
|
||||||
@@ -101,7 +188,7 @@ $(document).ready(function() {
|
|||||||
equal(obj.counterB, 1, 'counterB should have only been incremented once.');
|
equal(obj.counterB, 1, 'counterB should have only been incremented once.');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Events: bind a callback with a supplied context", 1, function () {
|
test("bind a callback with a supplied context", 1, function () {
|
||||||
var TestClass = function () {
|
var TestClass = function () {
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
@@ -114,7 +201,7 @@ $(document).ready(function() {
|
|||||||
obj.trigger('event');
|
obj.trigger('event');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Events: nested trigger with unbind", 1, function () {
|
test("nested trigger with unbind", 1, function () {
|
||||||
var obj = { counter: 0 };
|
var obj = { counter: 0 };
|
||||||
_.extend(obj, Backbone.Events);
|
_.extend(obj, Backbone.Events);
|
||||||
var incr1 = function(){ obj.counter += 1; obj.off('event', incr1); obj.trigger('event'); };
|
var incr1 = function(){ obj.counter += 1; obj.off('event', incr1); obj.trigger('event'); };
|
||||||
@@ -125,7 +212,7 @@ $(document).ready(function() {
|
|||||||
equal(obj.counter, 3, 'counter should have been incremented three times');
|
equal(obj.counter, 3, 'counter should have been incremented three times');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Events: callback list is not altered during trigger", 2, function () {
|
test("callback list is not altered during trigger", 2, function () {
|
||||||
var counter = 0, obj = _.extend({}, Backbone.Events);
|
var counter = 0, obj = _.extend({}, Backbone.Events);
|
||||||
var incr = function(){ counter++; };
|
var incr = function(){ counter++; };
|
||||||
obj.on('event', function(){ obj.on('event', incr).on('all', incr); })
|
obj.on('event', function(){ obj.on('event', incr).on('all', incr); })
|
||||||
@@ -192,4 +279,125 @@ $(document).ready(function() {
|
|||||||
obj.trigger('event');
|
obj.trigger('event');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("once", 2, function() {
|
||||||
|
// Same as the previous test, but we use once rather than having to explicitly unbind
|
||||||
|
var obj = { counterA: 0, counterB: 0 };
|
||||||
|
_.extend(obj, Backbone.Events);
|
||||||
|
var incrA = function(){ obj.counterA += 1; obj.trigger('event'); };
|
||||||
|
var incrB = function(){ obj.counterB += 1; };
|
||||||
|
obj.once('event', incrA);
|
||||||
|
obj.once('event', incrB);
|
||||||
|
obj.trigger('event');
|
||||||
|
equal(obj.counterA, 1, 'counterA should have only been incremented once.');
|
||||||
|
equal(obj.counterB, 1, 'counterB should have only been incremented once.');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("once variant one", 3, function() {
|
||||||
|
var f = function(){ ok(true); };
|
||||||
|
|
||||||
|
var a = _.extend({}, Backbone.Events).once('event', f);
|
||||||
|
var b = _.extend({}, Backbone.Events).on('event', f);
|
||||||
|
|
||||||
|
a.trigger('event');
|
||||||
|
|
||||||
|
b.trigger('event');
|
||||||
|
b.trigger('event');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("once variant two", 3, function() {
|
||||||
|
var f = function(){ ok(true); };
|
||||||
|
var obj = _.extend({}, Backbone.Events);
|
||||||
|
|
||||||
|
obj
|
||||||
|
.once('event', f)
|
||||||
|
.on('event', f)
|
||||||
|
.trigger('event')
|
||||||
|
.trigger('event');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("once with off", 0, function() {
|
||||||
|
var f = function(){ ok(true); };
|
||||||
|
var obj = _.extend({}, Backbone.Events);
|
||||||
|
|
||||||
|
obj.once('event', f);
|
||||||
|
obj.off('event', f);
|
||||||
|
obj.trigger('event');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("once with event maps", function() {
|
||||||
|
var obj = { counter: 0 };
|
||||||
|
_.extend(obj, Backbone.Events);
|
||||||
|
|
||||||
|
var increment = function() {
|
||||||
|
this.counter += 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.once({
|
||||||
|
a: increment,
|
||||||
|
b: increment,
|
||||||
|
c: increment
|
||||||
|
}, obj);
|
||||||
|
|
||||||
|
obj.trigger('a');
|
||||||
|
equal(obj.counter, 1);
|
||||||
|
|
||||||
|
obj.trigger('a b');
|
||||||
|
equal(obj.counter, 2);
|
||||||
|
|
||||||
|
obj.trigger('c');
|
||||||
|
equal(obj.counter, 3);
|
||||||
|
|
||||||
|
obj.trigger('a b c');
|
||||||
|
equal(obj.counter, 3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("once with off only by context", 0, function() {
|
||||||
|
var context = {};
|
||||||
|
var obj = _.extend({}, Backbone.Events);
|
||||||
|
obj.once('event', function(){ ok(false); }, context);
|
||||||
|
obj.off(null, null, context);
|
||||||
|
obj.trigger('event');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Backbone object inherits Events", function() {
|
||||||
|
ok(Backbone.on === Backbone.Events.on);
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest("once with asynchronous events", 1, function() {
|
||||||
|
var func = _.debounce(function() { ok(true); start(); }, 50);
|
||||||
|
var obj = _.extend({}, Backbone.Events).once('async', func);
|
||||||
|
|
||||||
|
obj.trigger('async');
|
||||||
|
obj.trigger('async');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("once with multiple events.", 2, function() {
|
||||||
|
var obj = _.extend({}, Backbone.Events);
|
||||||
|
obj.once('x y', function() { ok(true); });
|
||||||
|
obj.trigger('x y');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Off during iteration with once.", 2, function() {
|
||||||
|
var obj = _.extend({}, Backbone.Events);
|
||||||
|
var f = function(){ this.off('event', f); };
|
||||||
|
obj.on('event', f);
|
||||||
|
obj.once('event', function(){});
|
||||||
|
obj.on('event', function(){ ok(true); });
|
||||||
|
|
||||||
|
obj.trigger('event');
|
||||||
|
obj.trigger('event');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("`once` on `all` should work as expected", 1, function() {
|
||||||
|
Backbone.once('all', function() {
|
||||||
|
ok(true);
|
||||||
|
Backbone.trigger('all');
|
||||||
|
});
|
||||||
|
Backbone.trigger('all');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("once without a callback is a noop", 0, function() {
|
||||||
|
_.extend({}, Backbone.Events).once('event').trigger('event');
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
606
vendor/backbone/test/model.js
vendored
606
vendor/backbone/test/model.js
vendored
File diff suppressed because it is too large
Load Diff
2
vendor/backbone/test/noconflict.js
vendored
2
vendor/backbone/test/noconflict.js
vendored
@@ -2,7 +2,7 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
module("Backbone.noConflict");
|
module("Backbone.noConflict");
|
||||||
|
|
||||||
test('Backbone.noConflict', 2, function() {
|
test('noConflict', 2, function() {
|
||||||
var noconflictBackbone = Backbone.noConflict();
|
var noconflictBackbone = Backbone.noConflict();
|
||||||
equal(window.Backbone, undefined, 'Returned window.Backbone');
|
equal(window.Backbone, undefined, 'Returned window.Backbone');
|
||||||
window.Backbone = noconflictBackbone;
|
window.Backbone = noconflictBackbone;
|
||||||
|
|||||||
287
vendor/backbone/test/router.js
vendored
287
vendor/backbone/test/router.js
vendored
@@ -20,9 +20,11 @@ $(document).ready(function() {
|
|||||||
_.extend(this, _.pick($('<a></a>', {href: href})[0],
|
_.extend(this, _.pick($('<a></a>', {href: href})[0],
|
||||||
'href',
|
'href',
|
||||||
'hash',
|
'hash',
|
||||||
|
'host',
|
||||||
'search',
|
'search',
|
||||||
'fragment',
|
'fragment',
|
||||||
'pathname'
|
'pathname',
|
||||||
|
'protocol'
|
||||||
));
|
));
|
||||||
// In IE, anchor.pathname does not contain a leading slash though
|
// In IE, anchor.pathname does not contain a leading slash though
|
||||||
// window.location.pathname does.
|
// window.location.pathname does.
|
||||||
@@ -39,7 +41,7 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
setup: function() {
|
setup: function() {
|
||||||
location = new Location('http://example.com');
|
location = new Location('http://example.com');
|
||||||
Backbone.history = new Backbone.History({location: location});
|
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||||
router = new Router({testing: 101});
|
router = new Router({testing: 101});
|
||||||
Backbone.history.interval = 9;
|
Backbone.history.interval = 9;
|
||||||
Backbone.history.start({pushState: false});
|
Backbone.history.start({pushState: false});
|
||||||
@@ -67,6 +69,9 @@ $(document).ready(function() {
|
|||||||
"contacts": "contacts",
|
"contacts": "contacts",
|
||||||
"contacts/new": "newContact",
|
"contacts/new": "newContact",
|
||||||
"contacts/:id": "loadContact",
|
"contacts/:id": "loadContact",
|
||||||
|
"route-event/:arg": "routeEvent",
|
||||||
|
"optional(/:item)": "optionalItem",
|
||||||
|
"named/optional/(y:z)": "namedOptional",
|
||||||
"splat/*args/end": "splat",
|
"splat/*args/end": "splat",
|
||||||
"*first/complex-:part/*rest": "complex",
|
"*first/complex-:part/*rest": "complex",
|
||||||
":entity?*args": "query",
|
":entity?*args": "query",
|
||||||
@@ -103,60 +108,71 @@ $(document).ready(function() {
|
|||||||
this.contact = 'load';
|
this.contact = 'load';
|
||||||
},
|
},
|
||||||
|
|
||||||
splat : function(args) {
|
optionalItem: function(arg){
|
||||||
|
this.arg = arg != void 0 ? arg : null;
|
||||||
|
},
|
||||||
|
|
||||||
|
splat: function(args) {
|
||||||
this.args = args;
|
this.args = args;
|
||||||
},
|
},
|
||||||
|
|
||||||
complex : function(first, part, rest) {
|
complex: function(first, part, rest) {
|
||||||
this.first = first;
|
this.first = first;
|
||||||
this.part = part;
|
this.part = part;
|
||||||
this.rest = rest;
|
this.rest = rest;
|
||||||
},
|
},
|
||||||
|
|
||||||
query : function(entity, args) {
|
query: function(entity, args) {
|
||||||
this.entity = entity;
|
this.entity = entity;
|
||||||
this.queryArgs = args;
|
this.queryArgs = args;
|
||||||
},
|
},
|
||||||
|
|
||||||
anything : function(whatever) {
|
anything: function(whatever) {
|
||||||
this.anything = whatever;
|
this.anything = whatever;
|
||||||
|
},
|
||||||
|
|
||||||
|
namedOptional: function(z) {
|
||||||
|
this.z = z;
|
||||||
|
},
|
||||||
|
|
||||||
|
routeEvent: function(arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Router: initialize", 1, function() {
|
test("initialize", 1, function() {
|
||||||
equal(router.testing, 101);
|
equal(router.testing, 101);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Router: routes (simple)", 4, function() {
|
test("routes (simple)", 4, function() {
|
||||||
location.replace('http://example.com#search/news');
|
location.replace('http://example.com#search/news');
|
||||||
Backbone.history.checkUrl();
|
Backbone.history.checkUrl();
|
||||||
equal(router.query, 'news');
|
equal(router.query, 'news');
|
||||||
equal(router.page, undefined);
|
equal(router.page, void 0);
|
||||||
equal(lastRoute, 'search');
|
equal(lastRoute, 'search');
|
||||||
equal(lastArgs[0], 'news');
|
equal(lastArgs[0], 'news');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Router: routes (two part)", 2, function() {
|
test("routes (two part)", 2, function() {
|
||||||
location.replace('http://example.com#search/nyc/p10');
|
location.replace('http://example.com#search/nyc/p10');
|
||||||
Backbone.history.checkUrl();
|
Backbone.history.checkUrl();
|
||||||
equal(router.query, 'nyc');
|
equal(router.query, 'nyc');
|
||||||
equal(router.page, '10');
|
equal(router.page, '10');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Router: routes via navigate", 2, function() {
|
test("routes via navigate", 2, function() {
|
||||||
Backbone.history.navigate('search/manhattan/p20', {trigger: true});
|
Backbone.history.navigate('search/manhattan/p20', {trigger: true});
|
||||||
equal(router.query, 'manhattan');
|
equal(router.query, 'manhattan');
|
||||||
equal(router.page, '20');
|
equal(router.page, '20');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Router: routes via navigate for backwards-compatibility", 2, function() {
|
test("routes via navigate for backwards-compatibility", 2, function() {
|
||||||
Backbone.history.navigate('search/manhattan/p20', true);
|
Backbone.history.navigate('search/manhattan/p20', true);
|
||||||
equal(router.query, 'manhattan');
|
equal(router.query, 'manhattan');
|
||||||
equal(router.page, '20');
|
equal(router.page, '20');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Router: route precedence via navigate", 6, function(){
|
test("route precedence via navigate", 6, function(){
|
||||||
// check both 0.9.x and backwards-compatibility options
|
// check both 0.9.x and backwards-compatibility options
|
||||||
_.each([ { trigger: true }, true ], function( options ){
|
_.each([ { trigger: true }, true ], function( options ){
|
||||||
Backbone.history.navigate('contacts', options);
|
Backbone.history.navigate('contacts', options);
|
||||||
@@ -176,13 +192,13 @@ $(document).ready(function() {
|
|||||||
Backbone.history.navigate('/route');
|
Backbone.history.navigate('/route');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Router: use implicit callback if none provided", 1, function() {
|
test("use implicit callback if none provided", 1, function() {
|
||||||
router.count = 0;
|
router.count = 0;
|
||||||
router.navigate('implicit', {trigger: true});
|
router.navigate('implicit', {trigger: true});
|
||||||
equal(router.count, 1);
|
equal(router.count, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Router: routes via navigate with {replace: true}", 1, function() {
|
test("routes via navigate with {replace: true}", 1, function() {
|
||||||
location.replace('http://example.com#start_here');
|
location.replace('http://example.com#start_here');
|
||||||
Backbone.history.checkUrl();
|
Backbone.history.checkUrl();
|
||||||
location.replace = function(href) {
|
location.replace = function(href) {
|
||||||
@@ -191,13 +207,22 @@ $(document).ready(function() {
|
|||||||
Backbone.history.navigate('end_here', {replace: true});
|
Backbone.history.navigate('end_here', {replace: true});
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Router: routes (splats)", 1, function() {
|
test("routes (splats)", 1, function() {
|
||||||
location.replace('http://example.com#splat/long-list/of/splatted_99args/end');
|
location.replace('http://example.com#splat/long-list/of/splatted_99args/end');
|
||||||
Backbone.history.checkUrl();
|
Backbone.history.checkUrl();
|
||||||
equal(router.args, 'long-list/of/splatted_99args');
|
equal(router.args, 'long-list/of/splatted_99args');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Router: routes (complex)", 3, function() {
|
test("routes (optional)", 2, function() {
|
||||||
|
location.replace('http://example.com#optional');
|
||||||
|
Backbone.history.checkUrl();
|
||||||
|
ok(!router.arg);
|
||||||
|
location.replace('http://example.com#optional/thing');
|
||||||
|
Backbone.history.checkUrl();
|
||||||
|
equal(router.arg, 'thing');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("routes (complex)", 3, function() {
|
||||||
location.replace('http://example.com#one/two/three/complex-part/four/five/six/seven');
|
location.replace('http://example.com#one/two/three/complex-part/four/five/six/seven');
|
||||||
Backbone.history.checkUrl();
|
Backbone.history.checkUrl();
|
||||||
equal(router.first, 'one/two/three');
|
equal(router.first, 'one/two/three');
|
||||||
@@ -205,7 +230,7 @@ $(document).ready(function() {
|
|||||||
equal(router.rest, 'four/five/six/seven');
|
equal(router.rest, 'four/five/six/seven');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Router: routes (query)", 5, function() {
|
test("routes (query)", 5, function() {
|
||||||
location.replace('http://example.com#mandel?a=b&c=d');
|
location.replace('http://example.com#mandel?a=b&c=d');
|
||||||
Backbone.history.checkUrl();
|
Backbone.history.checkUrl();
|
||||||
equal(router.entity, 'mandel');
|
equal(router.entity, 'mandel');
|
||||||
@@ -215,13 +240,13 @@ $(document).ready(function() {
|
|||||||
equal(lastArgs[1], 'a=b&c=d');
|
equal(lastArgs[1], 'a=b&c=d');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Router: routes (anything)", 1, function() {
|
test("routes (anything)", 1, function() {
|
||||||
location.replace('http://example.com#doesnt-match-a-route');
|
location.replace('http://example.com#doesnt-match-a-route');
|
||||||
Backbone.history.checkUrl();
|
Backbone.history.checkUrl();
|
||||||
equal(router.anything, 'doesnt-match-a-route');
|
equal(router.anything, 'doesnt-match-a-route');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Router: fires event when router doesn't have callback on it", 1, function() {
|
test("fires event when router doesn't have callback on it", 1, function() {
|
||||||
router.on("route:noCallback", function(){ ok(true); });
|
router.on("route:noCallback", function(){ ok(true); });
|
||||||
location.replace('http://example.com#noCallback');
|
location.replace('http://example.com#noCallback');
|
||||||
Backbone.history.checkUrl();
|
Backbone.history.checkUrl();
|
||||||
@@ -231,49 +256,46 @@ $(document).ready(function() {
|
|||||||
location.replace('http://example.com/root/foo');
|
location.replace('http://example.com/root/foo');
|
||||||
|
|
||||||
Backbone.history.stop();
|
Backbone.history.stop();
|
||||||
Backbone.history = new Backbone.History({location: location});
|
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||||
Backbone.history.start({root: '/root', hashChange: false, silent: true});
|
Backbone.history.start({root: '/root', hashChange: false, silent: true});
|
||||||
strictEqual(Backbone.history.getFragment(), 'foo');
|
strictEqual(Backbone.history.getFragment(), 'foo');
|
||||||
|
|
||||||
Backbone.history.stop();
|
Backbone.history.stop();
|
||||||
Backbone.history = new Backbone.History({location: location});
|
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||||
Backbone.history.start({root: '/root/', hashChange: false, silent: true});
|
Backbone.history.start({root: '/root/', hashChange: false, silent: true});
|
||||||
strictEqual(Backbone.history.getFragment(), 'foo');
|
strictEqual(Backbone.history.getFragment(), 'foo');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("#1003 - History is started before navigate is called", 1, function() {
|
test("#1003 - History is started before navigate is called", 1, function() {
|
||||||
var history = new Backbone.History();
|
|
||||||
history.navigate = function(){
|
|
||||||
ok(Backbone.History.started);
|
|
||||||
};
|
|
||||||
Backbone.history.stop();
|
Backbone.history.stop();
|
||||||
history.start();
|
Backbone.history.navigate = function(){ ok(Backbone.History.started); };
|
||||||
|
Backbone.history.start();
|
||||||
// If this is not an old IE navigate will not be called.
|
// If this is not an old IE navigate will not be called.
|
||||||
if (!history.iframe) ok(true);
|
if (!Backbone.history.iframe) ok(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Router: route callback gets passed decoded values", 3, function() {
|
test("#967 - Route callback gets passed encoded values.", 3, function() {
|
||||||
var route = 'has%2Fslash/complex-has%23hash/has%20space';
|
var route = 'has%2Fslash/complex-has%23hash/has%20space';
|
||||||
Backbone.history.navigate(route, {trigger: true});
|
Backbone.history.navigate(route, {trigger: true});
|
||||||
equal(router.first, 'has/slash');
|
strictEqual(router.first, 'has%2Fslash');
|
||||||
equal(router.part, 'has#hash');
|
strictEqual(router.part, 'has%23hash');
|
||||||
equal(router.rest, 'has space');
|
strictEqual(router.rest, 'has%20space');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Router: correctly handles URLs with % (#868)", 3, function() {
|
test("correctly handles URLs with % (#868)", 3, function() {
|
||||||
location.replace('http://example.com#search/fat%3A1.5%25');
|
location.replace('http://example.com#search/fat%3A1.5%25');
|
||||||
Backbone.history.checkUrl();
|
Backbone.history.checkUrl();
|
||||||
location.replace('http://example.com#search/fat');
|
location.replace('http://example.com#search/fat');
|
||||||
Backbone.history.checkUrl();
|
Backbone.history.checkUrl();
|
||||||
equal(router.query, 'fat');
|
equal(router.query, 'fat');
|
||||||
equal(router.page, undefined);
|
equal(router.page, void 0);
|
||||||
equal(lastRoute, 'search');
|
equal(lastRoute, 'search');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("#1185 - Use pathname when hashChange is not wanted.", 1, function() {
|
test("#1185 - Use pathname when hashChange is not wanted.", 1, function() {
|
||||||
Backbone.history.stop();
|
Backbone.history.stop();
|
||||||
location.replace('http://example.com/path/name#hash');
|
location.replace('http://example.com/path/name#hash');
|
||||||
Backbone.history = new Backbone.History({location: location});
|
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||||
Backbone.history.start({hashChange: false});
|
Backbone.history.start({hashChange: false});
|
||||||
var fragment = Backbone.history.getFragment();
|
var fragment = Backbone.history.getFragment();
|
||||||
strictEqual(fragment, location.pathname.replace(/^\//, ''));
|
strictEqual(fragment, location.pathname.replace(/^\//, ''));
|
||||||
@@ -282,7 +304,7 @@ $(document).ready(function() {
|
|||||||
test("#1206 - Strip leading slash before location.assign.", 1, function() {
|
test("#1206 - Strip leading slash before location.assign.", 1, function() {
|
||||||
Backbone.history.stop();
|
Backbone.history.stop();
|
||||||
location.replace('http://example.com/root/');
|
location.replace('http://example.com/root/');
|
||||||
Backbone.history = new Backbone.History({location: location});
|
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||||
Backbone.history.start({hashChange: false, root: '/root/'});
|
Backbone.history.start({hashChange: false, root: '/root/'});
|
||||||
location.assign = function(pathname) {
|
location.assign = function(pathname) {
|
||||||
strictEqual(pathname, '/root/fragment');
|
strictEqual(pathname, '/root/fragment');
|
||||||
@@ -293,7 +315,7 @@ $(document).ready(function() {
|
|||||||
test("#1387 - Root fragment without trailing slash.", 1, function() {
|
test("#1387 - Root fragment without trailing slash.", 1, function() {
|
||||||
Backbone.history.stop();
|
Backbone.history.stop();
|
||||||
location.replace('http://example.com/root');
|
location.replace('http://example.com/root');
|
||||||
Backbone.history = new Backbone.History({location: location});
|
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||||
Backbone.history.start({hashChange: false, root: '/root/', silent: true});
|
Backbone.history.start({hashChange: false, root: '/root/', silent: true});
|
||||||
strictEqual(Backbone.history.getFragment(), '');
|
strictEqual(Backbone.history.getFragment(), '');
|
||||||
});
|
});
|
||||||
@@ -301,7 +323,7 @@ $(document).ready(function() {
|
|||||||
test("#1366 - History does not prepend root to fragment.", 2, function() {
|
test("#1366 - History does not prepend root to fragment.", 2, function() {
|
||||||
Backbone.history.stop();
|
Backbone.history.stop();
|
||||||
location.replace('http://example.com/root/');
|
location.replace('http://example.com/root/');
|
||||||
Backbone.history = new Backbone.History({
|
Backbone.history = _.extend(new Backbone.History, {
|
||||||
location: location,
|
location: location,
|
||||||
history: {
|
history: {
|
||||||
pushState: function(state, title, url) {
|
pushState: function(state, title, url) {
|
||||||
@@ -318,4 +340,193 @@ $(document).ready(function() {
|
|||||||
strictEqual(Backbone.history.fragment, 'x');
|
strictEqual(Backbone.history.fragment, 'x');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Normalize root.", 1, function() {
|
||||||
|
Backbone.history.stop();
|
||||||
|
location.replace('http://example.com/root');
|
||||||
|
Backbone.history = _.extend(new Backbone.History, {
|
||||||
|
location: location,
|
||||||
|
history: {
|
||||||
|
pushState: function(state, title, url) {
|
||||||
|
strictEqual(url, '/root/fragment');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Backbone.history.start({
|
||||||
|
pushState: true,
|
||||||
|
root: '/root',
|
||||||
|
hashChange: false
|
||||||
|
});
|
||||||
|
Backbone.history.navigate('fragment');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Normalize root.", 1, function() {
|
||||||
|
Backbone.history.stop();
|
||||||
|
location.replace('http://example.com/root#fragment');
|
||||||
|
Backbone.history = _.extend(new Backbone.History, {
|
||||||
|
location: location,
|
||||||
|
history: {
|
||||||
|
pushState: function(state, title, url) {},
|
||||||
|
replaceState: function(state, title, url) {
|
||||||
|
strictEqual(url, '/root/fragment');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Backbone.history.start({
|
||||||
|
pushState: true,
|
||||||
|
root: '/root'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Normalize root.", 1, function() {
|
||||||
|
Backbone.history.stop();
|
||||||
|
location.replace('http://example.com/root');
|
||||||
|
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||||
|
Backbone.history.loadUrl = function() { ok(true); };
|
||||||
|
Backbone.history.start({
|
||||||
|
pushState: true,
|
||||||
|
root: '/root'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Normalize root - leading slash.", 1, function() {
|
||||||
|
Backbone.history.stop();
|
||||||
|
location.replace('http://example.com/root');
|
||||||
|
Backbone.history = _.extend(new Backbone.History, {
|
||||||
|
location: location,
|
||||||
|
history: {
|
||||||
|
pushState: function(){},
|
||||||
|
replaceState: function(){}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Backbone.history.start({root: 'root'});
|
||||||
|
strictEqual(Backbone.history.root, '/root/');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Transition from hashChange to pushState.", 1, function() {
|
||||||
|
Backbone.history.stop();
|
||||||
|
location.replace('http://example.com/root#x/y');
|
||||||
|
Backbone.history = _.extend(new Backbone.History, {
|
||||||
|
location: location,
|
||||||
|
history: {
|
||||||
|
pushState: function(){},
|
||||||
|
replaceState: function(state, title, url){
|
||||||
|
strictEqual(url, '/root/x/y');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Backbone.history.start({
|
||||||
|
root: 'root',
|
||||||
|
pushState: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1619: Router: Normalize empty root", 1, function() {
|
||||||
|
Backbone.history.stop();
|
||||||
|
location.replace('http://example.com/');
|
||||||
|
Backbone.history = _.extend(new Backbone.History, {
|
||||||
|
location: location,
|
||||||
|
history: {
|
||||||
|
pushState: function(){},
|
||||||
|
replaceState: function(){}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Backbone.history.start({root: ''});
|
||||||
|
strictEqual(Backbone.history.root, '/');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1619: Router: nagivate with empty root", 1, function() {
|
||||||
|
Backbone.history.stop();
|
||||||
|
location.replace('http://example.com/');
|
||||||
|
Backbone.history = _.extend(new Backbone.History, {
|
||||||
|
location: location,
|
||||||
|
history: {
|
||||||
|
pushState: function(state, title, url) {
|
||||||
|
strictEqual(url, '/fragment');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Backbone.history.start({
|
||||||
|
pushState: true,
|
||||||
|
root: '',
|
||||||
|
hashChange: false
|
||||||
|
});
|
||||||
|
Backbone.history.navigate('fragment');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Transition from pushState to hashChange.", 1, function() {
|
||||||
|
Backbone.history.stop();
|
||||||
|
location.replace('http://example.com/root/x/y?a=b');
|
||||||
|
location.replace = function(url) {
|
||||||
|
strictEqual(url, '/root/?a=b#x/y');
|
||||||
|
};
|
||||||
|
Backbone.history = _.extend(new Backbone.History, {
|
||||||
|
location: location,
|
||||||
|
history: {
|
||||||
|
pushState: null,
|
||||||
|
replaceState: null
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Backbone.history.start({
|
||||||
|
root: 'root',
|
||||||
|
pushState: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1695 - hashChange to pushState with search.", 1, function() {
|
||||||
|
Backbone.history.stop();
|
||||||
|
location.replace('http://example.com/root?a=b#x/y');
|
||||||
|
Backbone.history = _.extend(new Backbone.History, {
|
||||||
|
location: location,
|
||||||
|
history: {
|
||||||
|
pushState: function(){},
|
||||||
|
replaceState: function(state, title, url){
|
||||||
|
strictEqual(url, '/root/x/y?a=b');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Backbone.history.start({
|
||||||
|
root: 'root',
|
||||||
|
pushState: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1746 - Router allows empty route.", 1, function() {
|
||||||
|
var Router = Backbone.Router.extend({
|
||||||
|
routes: {'': 'empty'},
|
||||||
|
empty: function(){},
|
||||||
|
route: function(route){
|
||||||
|
strictEqual(route, '');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
new Router;
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1794 - Trailing space in fragments.", 1, function() {
|
||||||
|
var history = new Backbone.History;
|
||||||
|
strictEqual(history.getFragment('fragment '), 'fragment');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1820 - Leading slash and trailing space.", 1, function() {
|
||||||
|
var history = new Backbone.History;
|
||||||
|
strictEqual(history.getFragment('/fragment '), 'fragment');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1980 - Optional parameters.", 2, function() {
|
||||||
|
location.replace('http://example.com#named/optional/y');
|
||||||
|
Backbone.history.checkUrl();
|
||||||
|
strictEqual(router.z, undefined);
|
||||||
|
location.replace('http://example.com#named/optional/y123');
|
||||||
|
Backbone.history.checkUrl();
|
||||||
|
strictEqual(router.z, '123');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#2062 - Trigger 'route' event on router instance.", 2, function() {
|
||||||
|
router.on('route', function(name, args) {
|
||||||
|
strictEqual(name, 'routeEvent');
|
||||||
|
deepEqual(args, ['x']);
|
||||||
|
});
|
||||||
|
location.replace('http://example.com#route-event/x');
|
||||||
|
Backbone.history.checkUrl();
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
194
vendor/backbone/test/sync.js
vendored
194
vendor/backbone/test/sync.js
vendored
@@ -1,8 +1,5 @@
|
|||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
|
|
||||||
var ajax = Backbone.ajax;
|
|
||||||
var lastRequest = null;
|
|
||||||
|
|
||||||
var Library = Backbone.Collection.extend({
|
var Library = Backbone.Collection.extend({
|
||||||
url : function() { return '/library'; }
|
url : function() { return '/library'; }
|
||||||
});
|
});
|
||||||
@@ -14,132 +11,133 @@ $(document).ready(function() {
|
|||||||
length : 123
|
length : 123
|
||||||
};
|
};
|
||||||
|
|
||||||
module("Backbone.sync", {
|
module("Backbone.sync", _.extend(new Environment, {
|
||||||
|
|
||||||
setup : function() {
|
setup : function() {
|
||||||
library = new Library();
|
Environment.prototype.setup.apply(this, arguments);
|
||||||
Backbone.ajax = function(obj) {
|
library = new Library;
|
||||||
lastRequest = obj;
|
|
||||||
};
|
|
||||||
library.create(attrs, {wait: false});
|
library.create(attrs, {wait: false});
|
||||||
},
|
},
|
||||||
|
|
||||||
teardown: function() {
|
teardown: function() {
|
||||||
Backbone.ajax = ajax;
|
Environment.prototype.teardown.apply(this, arguments);
|
||||||
|
Backbone.emulateHTTP = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}));
|
||||||
|
|
||||||
test("sync: read", 4, function() {
|
test("read", 4, function() {
|
||||||
library.fetch();
|
library.fetch();
|
||||||
equal(lastRequest.url, '/library');
|
equal(this.ajaxSettings.url, '/library');
|
||||||
equal(lastRequest.type, 'GET');
|
equal(this.ajaxSettings.type, 'GET');
|
||||||
equal(lastRequest.dataType, 'json');
|
equal(this.ajaxSettings.dataType, 'json');
|
||||||
ok(_.isEmpty(lastRequest.data));
|
ok(_.isEmpty(this.ajaxSettings.data));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("sync: passing data", 3, function() {
|
test("passing data", 3, function() {
|
||||||
library.fetch({data: {a: 'a', one: 1}});
|
library.fetch({data: {a: 'a', one: 1}});
|
||||||
equal(lastRequest.url, '/library');
|
equal(this.ajaxSettings.url, '/library');
|
||||||
equal(lastRequest.data.a, 'a');
|
equal(this.ajaxSettings.data.a, 'a');
|
||||||
equal(lastRequest.data.one, 1);
|
equal(this.ajaxSettings.data.one, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("sync: create", 6, function() {
|
test("create", 6, function() {
|
||||||
equal(lastRequest.url, '/library');
|
equal(this.ajaxSettings.url, '/library');
|
||||||
equal(lastRequest.type, 'POST');
|
equal(this.ajaxSettings.type, 'POST');
|
||||||
equal(lastRequest.dataType, 'json');
|
equal(this.ajaxSettings.dataType, 'json');
|
||||||
var data = JSON.parse(lastRequest.data);
|
var data = JSON.parse(this.ajaxSettings.data);
|
||||||
equal(data.title, 'The Tempest');
|
equal(data.title, 'The Tempest');
|
||||||
equal(data.author, 'Bill Shakespeare');
|
equal(data.author, 'Bill Shakespeare');
|
||||||
equal(data.length, 123);
|
equal(data.length, 123);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("sync: update", 7, function() {
|
test("update", 7, function() {
|
||||||
library.first().save({id: '1-the-tempest', author: 'William Shakespeare'});
|
library.first().save({id: '1-the-tempest', author: 'William Shakespeare'});
|
||||||
equal(lastRequest.url, '/library/1-the-tempest');
|
equal(this.ajaxSettings.url, '/library/1-the-tempest');
|
||||||
equal(lastRequest.type, 'PUT');
|
equal(this.ajaxSettings.type, 'PUT');
|
||||||
equal(lastRequest.dataType, 'json');
|
equal(this.ajaxSettings.dataType, 'json');
|
||||||
var data = JSON.parse(lastRequest.data);
|
var data = JSON.parse(this.ajaxSettings.data);
|
||||||
equal(data.id, '1-the-tempest');
|
equal(data.id, '1-the-tempest');
|
||||||
equal(data.title, 'The Tempest');
|
equal(data.title, 'The Tempest');
|
||||||
equal(data.author, 'William Shakespeare');
|
equal(data.author, 'William Shakespeare');
|
||||||
equal(data.length, 123);
|
equal(data.length, 123);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("sync: update with emulateHTTP and emulateJSON", 7, function() {
|
test("update with emulateHTTP and emulateJSON", 7, function() {
|
||||||
Backbone.emulateHTTP = Backbone.emulateJSON = true;
|
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, {
|
||||||
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
emulateHTTP: true,
|
||||||
equal(lastRequest.url, '/library/2-the-tempest');
|
emulateJSON: true
|
||||||
equal(lastRequest.type, 'POST');
|
});
|
||||||
equal(lastRequest.dataType, 'json');
|
equal(this.ajaxSettings.url, '/library/2-the-tempest');
|
||||||
equal(lastRequest.data._method, 'PUT');
|
equal(this.ajaxSettings.type, 'POST');
|
||||||
var data = JSON.parse(lastRequest.data.model);
|
equal(this.ajaxSettings.dataType, 'json');
|
||||||
|
equal(this.ajaxSettings.data._method, 'PUT');
|
||||||
|
var data = JSON.parse(this.ajaxSettings.data.model);
|
||||||
equal(data.id, '2-the-tempest');
|
equal(data.id, '2-the-tempest');
|
||||||
equal(data.author, 'Tim Shakespeare');
|
equal(data.author, 'Tim Shakespeare');
|
||||||
equal(data.length, 123);
|
equal(data.length, 123);
|
||||||
Backbone.emulateHTTP = Backbone.emulateJSON = false;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("sync: update with just emulateHTTP", 6, function() {
|
test("update with just emulateHTTP", 6, function() {
|
||||||
Backbone.emulateHTTP = true;
|
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, {
|
||||||
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
emulateHTTP: true
|
||||||
equal(lastRequest.url, '/library/2-the-tempest');
|
});
|
||||||
equal(lastRequest.type, 'POST');
|
equal(this.ajaxSettings.url, '/library/2-the-tempest');
|
||||||
equal(lastRequest.contentType, 'application/json');
|
equal(this.ajaxSettings.type, 'POST');
|
||||||
var data = JSON.parse(lastRequest.data);
|
equal(this.ajaxSettings.contentType, 'application/json');
|
||||||
|
var data = JSON.parse(this.ajaxSettings.data);
|
||||||
equal(data.id, '2-the-tempest');
|
equal(data.id, '2-the-tempest');
|
||||||
equal(data.author, 'Tim Shakespeare');
|
equal(data.author, 'Tim Shakespeare');
|
||||||
equal(data.length, 123);
|
equal(data.length, 123);
|
||||||
Backbone.emulateHTTP = false;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("sync: update with just emulateJSON", 6, function() {
|
test("update with just emulateJSON", 6, function() {
|
||||||
Backbone.emulateJSON = true;
|
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'}, {
|
||||||
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
emulateJSON: true
|
||||||
equal(lastRequest.url, '/library/2-the-tempest');
|
});
|
||||||
equal(lastRequest.type, 'PUT');
|
equal(this.ajaxSettings.url, '/library/2-the-tempest');
|
||||||
equal(lastRequest.contentType, 'application/x-www-form-urlencoded');
|
equal(this.ajaxSettings.type, 'PUT');
|
||||||
var data = JSON.parse(lastRequest.data.model);
|
equal(this.ajaxSettings.contentType, 'application/x-www-form-urlencoded');
|
||||||
|
var data = JSON.parse(this.ajaxSettings.data.model);
|
||||||
equal(data.id, '2-the-tempest');
|
equal(data.id, '2-the-tempest');
|
||||||
equal(data.author, 'Tim Shakespeare');
|
equal(data.author, 'Tim Shakespeare');
|
||||||
equal(data.length, 123);
|
equal(data.length, 123);
|
||||||
Backbone.emulateJSON = false;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("sync: read model", 3, function() {
|
test("read model", 3, function() {
|
||||||
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
||||||
library.first().fetch();
|
library.first().fetch();
|
||||||
equal(lastRequest.url, '/library/2-the-tempest');
|
equal(this.ajaxSettings.url, '/library/2-the-tempest');
|
||||||
equal(lastRequest.type, 'GET');
|
equal(this.ajaxSettings.type, 'GET');
|
||||||
ok(_.isEmpty(lastRequest.data));
|
ok(_.isEmpty(this.ajaxSettings.data));
|
||||||
});
|
});
|
||||||
|
|
||||||
test("sync: destroy", 3, function() {
|
test("destroy", 3, function() {
|
||||||
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
||||||
library.first().destroy({wait: true});
|
library.first().destroy({wait: true});
|
||||||
equal(lastRequest.url, '/library/2-the-tempest');
|
equal(this.ajaxSettings.url, '/library/2-the-tempest');
|
||||||
equal(lastRequest.type, 'DELETE');
|
equal(this.ajaxSettings.type, 'DELETE');
|
||||||
equal(lastRequest.data, null);
|
equal(this.ajaxSettings.data, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("sync: destroy with emulateHTTP", 3, function() {
|
test("destroy with emulateHTTP", 3, function() {
|
||||||
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
||||||
Backbone.emulateHTTP = Backbone.emulateJSON = true;
|
library.first().destroy({
|
||||||
library.first().destroy();
|
emulateHTTP: true,
|
||||||
equal(lastRequest.url, '/library/2-the-tempest');
|
emulateJSON: true
|
||||||
equal(lastRequest.type, 'POST');
|
});
|
||||||
equal(JSON.stringify(lastRequest.data), '{"_method":"DELETE"}');
|
equal(this.ajaxSettings.url, '/library/2-the-tempest');
|
||||||
Backbone.emulateHTTP = Backbone.emulateJSON = false;
|
equal(this.ajaxSettings.type, 'POST');
|
||||||
|
equal(JSON.stringify(this.ajaxSettings.data), '{"_method":"DELETE"}');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("sync: urlError", 2, function() {
|
test("urlError", 2, function() {
|
||||||
var model = new Backbone.Model();
|
var model = new Backbone.Model();
|
||||||
raises(function() {
|
raises(function() {
|
||||||
model.fetch();
|
model.fetch();
|
||||||
});
|
});
|
||||||
model.fetch({url: '/one/two'});
|
model.fetch({url: '/one/two'});
|
||||||
equal(lastRequest.url, '/one/two');
|
equal(this.ajaxSettings.url, '/one/two');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("#1052 - `options` is optional.", 0, function() {
|
test("#1052 - `options` is optional.", 0, function() {
|
||||||
@@ -157,4 +155,58 @@ $(document).ready(function() {
|
|||||||
Backbone.sync('create', model);
|
Backbone.sync('create', model);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Call provided error callback on error.", 1, function() {
|
||||||
|
var model = new Backbone.Model;
|
||||||
|
model.url = '/test';
|
||||||
|
Backbone.sync('read', model, {
|
||||||
|
error: function() { ok(true); }
|
||||||
|
});
|
||||||
|
this.ajaxSettings.error();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Use Backbone.emulateHTTP as default.', 2, function() {
|
||||||
|
var model = new Backbone.Model;
|
||||||
|
model.url = '/test';
|
||||||
|
|
||||||
|
Backbone.emulateHTTP = true;
|
||||||
|
model.sync('create', model);
|
||||||
|
strictEqual(this.ajaxSettings.emulateHTTP, true);
|
||||||
|
|
||||||
|
Backbone.emulateHTTP = false;
|
||||||
|
model.sync('create', model);
|
||||||
|
strictEqual(this.ajaxSettings.emulateHTTP, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Use Backbone.emulateJSON as default.', 2, function() {
|
||||||
|
var model = new Backbone.Model;
|
||||||
|
model.url = '/test';
|
||||||
|
|
||||||
|
Backbone.emulateJSON = true;
|
||||||
|
model.sync('create', model);
|
||||||
|
strictEqual(this.ajaxSettings.emulateJSON, true);
|
||||||
|
|
||||||
|
Backbone.emulateJSON = false;
|
||||||
|
model.sync('create', model);
|
||||||
|
strictEqual(this.ajaxSettings.emulateJSON, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("#1756 - Call user provided beforeSend function.", 4, function() {
|
||||||
|
Backbone.emulateHTTP = true;
|
||||||
|
var model = new Backbone.Model;
|
||||||
|
model.url = '/test';
|
||||||
|
var xhr = {
|
||||||
|
setRequestHeader: function(header, value) {
|
||||||
|
strictEqual(header, 'X-HTTP-Method-Override');
|
||||||
|
strictEqual(value, 'DELETE');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
model.sync('delete', model, {
|
||||||
|
beforeSend: function(_xhr) {
|
||||||
|
ok(_xhr === xhr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
strictEqual(this.ajaxSettings.beforeSend(xhr), false);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
9266
vendor/backbone/test/vendor/jquery-1.7.1.js
vendored
9266
vendor/backbone/test/vendor/jquery-1.7.1.js
vendored
File diff suppressed because it is too large
Load Diff
649
vendor/backbone/test/vendor/jslitmus.js
vendored
649
vendor/backbone/test/vendor/jslitmus.js
vendored
@@ -1,649 +0,0 @@
|
|||||||
// JSLitmus.js
|
|
||||||
//
|
|
||||||
// Copyright (c) 2010, Robert Kieffer, http://broofa.com
|
|
||||||
// Available under MIT license (http://en.wikipedia.org/wiki/MIT_License)
|
|
||||||
|
|
||||||
(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 : '∞';
|
|
||||||
cell.title = 'Looped ' + test.count + ' times in ' + test.time + ' seconds';
|
|
||||||
} 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();
|
|
||||||
})();
|
|
||||||
481
vendor/backbone/test/vendor/json2.js
vendored
481
vendor/backbone/test/vendor/json2.js
vendored
@@ -1,481 +0,0 @@
|
|||||||
/*
|
|
||||||
http://www.JSON.org/json2.js
|
|
||||||
2009-09-29
|
|
||||||
|
|
||||||
Public Domain.
|
|
||||||
|
|
||||||
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
|
|
||||||
|
|
||||||
See http://www.JSON.org/js.html
|
|
||||||
|
|
||||||
|
|
||||||
This code should be minified before deployment.
|
|
||||||
See http://javascript.crockford.com/jsmin.html
|
|
||||||
|
|
||||||
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
|
|
||||||
NOT CONTROL.
|
|
||||||
|
|
||||||
|
|
||||||
This file creates a global JSON object containing two methods: stringify
|
|
||||||
and parse.
|
|
||||||
|
|
||||||
JSON.stringify(value, replacer, space)
|
|
||||||
value any JavaScript value, usually an object or array.
|
|
||||||
|
|
||||||
replacer an optional parameter that determines how object
|
|
||||||
values are stringified for objects. It can be a
|
|
||||||
function or an array of strings.
|
|
||||||
|
|
||||||
space an optional parameter that specifies the indentation
|
|
||||||
of nested structures. If it is omitted, the text will
|
|
||||||
be packed without extra whitespace. If it is a number,
|
|
||||||
it will specify the number of spaces to indent at each
|
|
||||||
level. If it is a string (such as '\t' or ' '),
|
|
||||||
it contains the characters used to indent at each level.
|
|
||||||
|
|
||||||
This method produces a JSON text from a JavaScript value.
|
|
||||||
|
|
||||||
When an object value is found, if the object contains a toJSON
|
|
||||||
method, its toJSON method will be called and the result will be
|
|
||||||
stringified. A toJSON method does not serialize: it returns the
|
|
||||||
value represented by the name/value pair that should be serialized,
|
|
||||||
or undefined if nothing should be serialized. The toJSON method
|
|
||||||
will be passed the key associated with the value, and this will be
|
|
||||||
bound to the value
|
|
||||||
|
|
||||||
For example, this would serialize Dates as ISO strings.
|
|
||||||
|
|
||||||
Date.prototype.toJSON = function (key) {
|
|
||||||
function f(n) {
|
|
||||||
// Format integers to have at least two digits.
|
|
||||||
return n < 10 ? '0' + n : n;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.getUTCFullYear() + '-' +
|
|
||||||
f(this.getUTCMonth() + 1) + '-' +
|
|
||||||
f(this.getUTCDate()) + 'T' +
|
|
||||||
f(this.getUTCHours()) + ':' +
|
|
||||||
f(this.getUTCMinutes()) + ':' +
|
|
||||||
f(this.getUTCSeconds()) + 'Z';
|
|
||||||
};
|
|
||||||
|
|
||||||
You can provide an optional replacer method. It will be passed the
|
|
||||||
key and value of each member, with this bound to the containing
|
|
||||||
object. The value that is returned from your method will be
|
|
||||||
serialized. If your method returns undefined, then the member will
|
|
||||||
be excluded from the serialization.
|
|
||||||
|
|
||||||
If the replacer parameter is an array of strings, then it will be
|
|
||||||
used to select the members to be serialized. It filters the results
|
|
||||||
such that only members with keys listed in the replacer array are
|
|
||||||
stringified.
|
|
||||||
|
|
||||||
Values that do not have JSON representations, such as undefined or
|
|
||||||
functions, will not be serialized. Such values in objects will be
|
|
||||||
dropped; in arrays they will be replaced with null. You can use
|
|
||||||
a replacer function to replace those with JSON values.
|
|
||||||
JSON.stringify(undefined) returns undefined.
|
|
||||||
|
|
||||||
The optional space parameter produces a stringification of the
|
|
||||||
value that is filled with line breaks and indentation to make it
|
|
||||||
easier to read.
|
|
||||||
|
|
||||||
If the space parameter is a non-empty string, then that string will
|
|
||||||
be used for indentation. If the space parameter is a number, then
|
|
||||||
the indentation will be that many spaces.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
text = JSON.stringify(['e', {pluribus: 'unum'}]);
|
|
||||||
// text is '["e",{"pluribus":"unum"}]'
|
|
||||||
|
|
||||||
|
|
||||||
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
|
|
||||||
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
|
|
||||||
|
|
||||||
text = JSON.stringify([new Date()], function (key, value) {
|
|
||||||
return this[key] instanceof Date ?
|
|
||||||
'Date(' + this[key] + ')' : value;
|
|
||||||
});
|
|
||||||
// text is '["Date(---current time---)"]'
|
|
||||||
|
|
||||||
|
|
||||||
JSON.parse(text, reviver)
|
|
||||||
This method parses a JSON text to produce an object or array.
|
|
||||||
It can throw a SyntaxError exception.
|
|
||||||
|
|
||||||
The optional reviver parameter is a function that can filter and
|
|
||||||
transform the results. It receives each of the keys and values,
|
|
||||||
and its return value is used instead of the original value.
|
|
||||||
If it returns what it received, then the structure is not modified.
|
|
||||||
If it returns undefined then the member is deleted.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
// Parse the text. Values that look like ISO date strings will
|
|
||||||
// be converted to Date objects.
|
|
||||||
|
|
||||||
myData = JSON.parse(text, function (key, value) {
|
|
||||||
var a;
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
a =
|
|
||||||
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
|
|
||||||
if (a) {
|
|
||||||
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
|
|
||||||
+a[5], +a[6]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
});
|
|
||||||
|
|
||||||
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
|
|
||||||
var d;
|
|
||||||
if (typeof value === 'string' &&
|
|
||||||
value.slice(0, 5) === 'Date(' &&
|
|
||||||
value.slice(-1) === ')') {
|
|
||||||
d = new Date(value.slice(5, -1));
|
|
||||||
if (d) {
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
This is a reference implementation. You are free to copy, modify, or
|
|
||||||
redistribute.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*jslint evil: true, strict: false */
|
|
||||||
|
|
||||||
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
|
||||||
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
|
||||||
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
|
|
||||||
lastIndex, length, parse, prototype, push, replace, slice, stringify,
|
|
||||||
test, toJSON, toString, valueOf
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
// Create a JSON object only if one does not already exist. We create the
|
|
||||||
// methods in a closure to avoid creating global variables.
|
|
||||||
|
|
||||||
if (!this.JSON) {
|
|
||||||
this.JSON = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
(function () {
|
|
||||||
|
|
||||||
function f(n) {
|
|
||||||
// Format integers to have at least two digits.
|
|
||||||
return n < 10 ? '0' + n : n;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof Date.prototype.toJSON !== 'function') {
|
|
||||||
|
|
||||||
Date.prototype.toJSON = function (key) {
|
|
||||||
|
|
||||||
return isFinite(this.valueOf()) ?
|
|
||||||
this.getUTCFullYear() + '-' +
|
|
||||||
f(this.getUTCMonth() + 1) + '-' +
|
|
||||||
f(this.getUTCDate()) + 'T' +
|
|
||||||
f(this.getUTCHours()) + ':' +
|
|
||||||
f(this.getUTCMinutes()) + ':' +
|
|
||||||
f(this.getUTCSeconds()) + 'Z' : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
String.prototype.toJSON =
|
|
||||||
Number.prototype.toJSON =
|
|
||||||
Boolean.prototype.toJSON = function (key) {
|
|
||||||
return this.valueOf();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
|
||||||
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
|
||||||
gap,
|
|
||||||
indent,
|
|
||||||
meta = { // table of character substitutions
|
|
||||||
'\b': '\\b',
|
|
||||||
'\t': '\\t',
|
|
||||||
'\n': '\\n',
|
|
||||||
'\f': '\\f',
|
|
||||||
'\r': '\\r',
|
|
||||||
'"' : '\\"',
|
|
||||||
'\\': '\\\\'
|
|
||||||
},
|
|
||||||
rep;
|
|
||||||
|
|
||||||
|
|
||||||
function quote(string) {
|
|
||||||
|
|
||||||
// If the string contains no control characters, no quote characters, and no
|
|
||||||
// backslash characters, then we can safely slap some quotes around it.
|
|
||||||
// Otherwise we must also replace the offending characters with safe escape
|
|
||||||
// sequences.
|
|
||||||
|
|
||||||
escapable.lastIndex = 0;
|
|
||||||
return escapable.test(string) ?
|
|
||||||
'"' + string.replace(escapable, function (a) {
|
|
||||||
var c = meta[a];
|
|
||||||
return typeof c === 'string' ? c :
|
|
||||||
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
|
||||||
}) + '"' :
|
|
||||||
'"' + string + '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function str(key, holder) {
|
|
||||||
|
|
||||||
// Produce a string from holder[key].
|
|
||||||
|
|
||||||
var i, // The loop counter.
|
|
||||||
k, // The member key.
|
|
||||||
v, // The member value.
|
|
||||||
length,
|
|
||||||
mind = gap,
|
|
||||||
partial,
|
|
||||||
value = holder[key];
|
|
||||||
|
|
||||||
// If the value has a toJSON method, call it to obtain a replacement value.
|
|
||||||
|
|
||||||
if (value && typeof value === 'object' &&
|
|
||||||
typeof value.toJSON === 'function') {
|
|
||||||
value = value.toJSON(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we were called with a replacer function, then call the replacer to
|
|
||||||
// obtain a replacement value.
|
|
||||||
|
|
||||||
if (typeof rep === 'function') {
|
|
||||||
value = rep.call(holder, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// What happens next depends on the value's type.
|
|
||||||
|
|
||||||
switch (typeof value) {
|
|
||||||
case 'string':
|
|
||||||
return quote(value);
|
|
||||||
|
|
||||||
case 'number':
|
|
||||||
|
|
||||||
// JSON numbers must be finite. Encode non-finite numbers as null.
|
|
||||||
|
|
||||||
return isFinite(value) ? String(value) : 'null';
|
|
||||||
|
|
||||||
case 'boolean':
|
|
||||||
case 'null':
|
|
||||||
|
|
||||||
// If the value is a boolean or null, convert it to a string. Note:
|
|
||||||
// typeof null does not produce 'null'. The case is included here in
|
|
||||||
// the remote chance that this gets fixed someday.
|
|
||||||
|
|
||||||
return String(value);
|
|
||||||
|
|
||||||
// If the type is 'object', we might be dealing with an object or an array or
|
|
||||||
// null.
|
|
||||||
|
|
||||||
case 'object':
|
|
||||||
|
|
||||||
// Due to a specification blunder in ECMAScript, typeof null is 'object',
|
|
||||||
// so watch out for that case.
|
|
||||||
|
|
||||||
if (!value) {
|
|
||||||
return 'null';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make an array to hold the partial results of stringifying this object value.
|
|
||||||
|
|
||||||
gap += indent;
|
|
||||||
partial = [];
|
|
||||||
|
|
||||||
// Is the value an array?
|
|
||||||
|
|
||||||
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
|
||||||
|
|
||||||
// The value is an array. Stringify every element. Use null as a placeholder
|
|
||||||
// for non-JSON values.
|
|
||||||
|
|
||||||
length = value.length;
|
|
||||||
for (i = 0; i < length; i += 1) {
|
|
||||||
partial[i] = str(i, value) || 'null';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join all of the elements together, separated with commas, and wrap them in
|
|
||||||
// brackets.
|
|
||||||
|
|
||||||
v = partial.length === 0 ? '[]' :
|
|
||||||
gap ? '[\n' + gap +
|
|
||||||
partial.join(',\n' + gap) + '\n' +
|
|
||||||
mind + ']' :
|
|
||||||
'[' + partial.join(',') + ']';
|
|
||||||
gap = mind;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the replacer is an array, use it to select the members to be stringified.
|
|
||||||
|
|
||||||
if (rep && typeof rep === 'object') {
|
|
||||||
length = rep.length;
|
|
||||||
for (i = 0; i < length; i += 1) {
|
|
||||||
k = rep[i];
|
|
||||||
if (typeof k === 'string') {
|
|
||||||
v = str(k, value);
|
|
||||||
if (v) {
|
|
||||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// Otherwise, iterate through all of the keys in the object.
|
|
||||||
|
|
||||||
for (k in value) {
|
|
||||||
if (Object.hasOwnProperty.call(value, k)) {
|
|
||||||
v = str(k, value);
|
|
||||||
if (v) {
|
|
||||||
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Join all of the member texts together, separated with commas,
|
|
||||||
// and wrap them in braces.
|
|
||||||
|
|
||||||
v = partial.length === 0 ? '{}' :
|
|
||||||
gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
|
|
||||||
mind + '}' : '{' + partial.join(',') + '}';
|
|
||||||
gap = mind;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the JSON object does not yet have a stringify method, give it one.
|
|
||||||
|
|
||||||
if (typeof JSON.stringify !== 'function') {
|
|
||||||
JSON.stringify = function (value, replacer, space) {
|
|
||||||
|
|
||||||
// The stringify method takes a value and an optional replacer, and an optional
|
|
||||||
// space parameter, and returns a JSON text. The replacer can be a function
|
|
||||||
// that can replace values, or an array of strings that will select the keys.
|
|
||||||
// A default replacer method can be provided. Use of the space parameter can
|
|
||||||
// produce text that is more easily readable.
|
|
||||||
|
|
||||||
var i;
|
|
||||||
gap = '';
|
|
||||||
indent = '';
|
|
||||||
|
|
||||||
// If the space parameter is a number, make an indent string containing that
|
|
||||||
// many spaces.
|
|
||||||
|
|
||||||
if (typeof space === 'number') {
|
|
||||||
for (i = 0; i < space; i += 1) {
|
|
||||||
indent += ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the space parameter is a string, it will be used as the indent string.
|
|
||||||
|
|
||||||
} else if (typeof space === 'string') {
|
|
||||||
indent = space;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is a replacer, it must be a function or an array.
|
|
||||||
// Otherwise, throw an error.
|
|
||||||
|
|
||||||
rep = replacer;
|
|
||||||
if (replacer && typeof replacer !== 'function' &&
|
|
||||||
(typeof replacer !== 'object' ||
|
|
||||||
typeof replacer.length !== 'number')) {
|
|
||||||
throw new Error('JSON.stringify');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a fake root object containing our value under the key of ''.
|
|
||||||
// Return the result of stringifying the value.
|
|
||||||
|
|
||||||
return str('', {'': value});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// If the JSON object does not yet have a parse method, give it one.
|
|
||||||
|
|
||||||
if (typeof JSON.parse !== 'function') {
|
|
||||||
JSON.parse = function (text, reviver) {
|
|
||||||
|
|
||||||
// The parse method takes a text and an optional reviver function, and returns
|
|
||||||
// a JavaScript value if the text is a valid JSON text.
|
|
||||||
|
|
||||||
var j;
|
|
||||||
|
|
||||||
function walk(holder, key) {
|
|
||||||
|
|
||||||
// The walk method is used to recursively walk the resulting structure so
|
|
||||||
// that modifications can be made.
|
|
||||||
|
|
||||||
var k, v, value = holder[key];
|
|
||||||
if (value && typeof value === 'object') {
|
|
||||||
for (k in value) {
|
|
||||||
if (Object.hasOwnProperty.call(value, k)) {
|
|
||||||
v = walk(value, k);
|
|
||||||
if (v !== undefined) {
|
|
||||||
value[k] = v;
|
|
||||||
} else {
|
|
||||||
delete value[k];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return reviver.call(holder, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Parsing happens in four stages. In the first stage, we replace certain
|
|
||||||
// Unicode characters with escape sequences. JavaScript handles many characters
|
|
||||||
// incorrectly, either silently deleting them, or treating them as line endings.
|
|
||||||
|
|
||||||
cx.lastIndex = 0;
|
|
||||||
if (cx.test(text)) {
|
|
||||||
text = text.replace(cx, function (a) {
|
|
||||||
return '\\u' +
|
|
||||||
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// In the second stage, we run the text against regular expressions that look
|
|
||||||
// for non-JSON patterns. We are especially concerned with '()' and 'new'
|
|
||||||
// because they can cause invocation, and '=' because it can cause mutation.
|
|
||||||
// But just to be safe, we want to reject all unexpected forms.
|
|
||||||
|
|
||||||
// We split the second stage into 4 regexp operations in order to work around
|
|
||||||
// crippling inefficiencies in IE's and Safari's regexp engines. First we
|
|
||||||
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
|
|
||||||
// replace all simple value tokens with ']' characters. Third, we delete all
|
|
||||||
// open brackets that follow a colon or comma or that begin the text. Finally,
|
|
||||||
// we look to see that the remaining characters are only whitespace or ']' or
|
|
||||||
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
|
|
||||||
|
|
||||||
if (/^[\],:{}\s]*$/.
|
|
||||||
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
|
|
||||||
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
|
|
||||||
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
|
||||||
|
|
||||||
// In the third stage we use the eval function to compile the text into a
|
|
||||||
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
|
||||||
// in JavaScript: it can begin a block or an object literal. We wrap the text
|
|
||||||
// in parens to eliminate the ambiguity.
|
|
||||||
|
|
||||||
j = eval('(' + text + ')');
|
|
||||||
|
|
||||||
// In the optional fourth stage, we recursively walk the new structure, passing
|
|
||||||
// each name/value pair to a reviver function for possible transformation.
|
|
||||||
|
|
||||||
return typeof reviver === 'function' ?
|
|
||||||
walk({'': j}, '') : j;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
|
||||||
|
|
||||||
throw new SyntaxError('JSON.parse');
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}());
|
|
||||||
236
vendor/backbone/test/vendor/qunit.css
vendored
236
vendor/backbone/test/vendor/qunit.css
vendored
@@ -1,236 +0,0 @@
|
|||||||
/**
|
|
||||||
* QUnit v1.8.0 - A JavaScript Unit Testing Framework
|
|
||||||
*
|
|
||||||
* http://docs.jquery.com/QUnit
|
|
||||||
*
|
|
||||||
* Copyright (c) 2012 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-header label {
|
|
||||||
display: inline-block;
|
|
||||||
padding-left: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
#qunit-testresult .module-name {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Fixture */
|
|
||||||
|
|
||||||
#qunit-fixture {
|
|
||||||
position: absolute;
|
|
||||||
top: -10000px;
|
|
||||||
left: -10000px;
|
|
||||||
width: 1000px;
|
|
||||||
height: 1000px;
|
|
||||||
}
|
|
||||||
1863
vendor/backbone/test/vendor/qunit.js
vendored
1863
vendor/backbone/test/vendor/qunit.js
vendored
File diff suppressed because it is too large
Load Diff
332
vendor/backbone/test/view.js
vendored
332
vendor/backbone/test/view.js
vendored
@@ -7,176 +7,224 @@ $(document).ready(function() {
|
|||||||
setup: function() {
|
setup: function() {
|
||||||
view = new Backbone.View({
|
view = new Backbone.View({
|
||||||
id : 'test-view',
|
id : 'test-view',
|
||||||
className : 'test-view'
|
className : 'test-view',
|
||||||
|
other : 'non-special-option'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("View: constructor", 4, function() {
|
test("constructor", 6, function() {
|
||||||
equal(view.el.id, 'test-view');
|
equal(view.el.id, 'test-view');
|
||||||
equal(view.el.className, 'test-view');
|
equal(view.el.className, 'test-view');
|
||||||
|
equal(view.el.other, void 0);
|
||||||
equal(view.options.id, 'test-view');
|
equal(view.options.id, 'test-view');
|
||||||
equal(view.options.className, 'test-view');
|
equal(view.options.className, 'test-view');
|
||||||
|
equal(view.options.other, 'non-special-option');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("View: jQuery", 2, function() {
|
test("jQuery", 1, function() {
|
||||||
view.setElement(document.body);
|
var view = new Backbone.View;
|
||||||
ok(view.$('#qunit-header a').get(0).innerHTML.match(/Backbone Test Suite/));
|
view.setElement('<p><a><b>test</b></a></p>');
|
||||||
ok(view.$('#qunit-header a').get(1).innerHTML.match(/Backbone Speed Suite/));
|
strictEqual(view.$('a b').html(), 'test');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("View: make", 3, function() {
|
test("initialize", 1, function() {
|
||||||
var div = view.make('div', {id: 'test-div'}, "one two three");
|
|
||||||
equal(div.tagName.toLowerCase(), 'div');
|
|
||||||
equal(div.id, 'test-div');
|
|
||||||
equal($(div).text(), 'one two three');
|
|
||||||
});
|
|
||||||
|
|
||||||
test("View: make can take falsy values for content", 2, function() {
|
|
||||||
var div = view.make('div', {id: 'test-div'}, 0);
|
|
||||||
equal($(div).text(), '0');
|
|
||||||
|
|
||||||
var div = view.make('div', {id: 'test-div'}, '');
|
|
||||||
equal($(div).text(), '');
|
|
||||||
});
|
|
||||||
|
|
||||||
test("View: initialize", 1, function() {
|
|
||||||
var View = Backbone.View.extend({
|
var View = Backbone.View.extend({
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
this.one = 1;
|
this.one = 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var view = new View;
|
|
||||||
equal(view.one, 1);
|
strictEqual(new View().one, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("View: delegateEvents", 6, function() {
|
test("delegateEvents", 6, function() {
|
||||||
var counter = 0;
|
var counter1 = 0, counter2 = 0;
|
||||||
var counter2 = 0;
|
|
||||||
view.setElement(document.body);
|
var view = new Backbone.View({el: '<p><a id="test"></a></p>'});
|
||||||
view.increment = function(){ counter++; };
|
view.increment = function(){ counter1++; };
|
||||||
view.$el.bind('click', function(){ counter2++; });
|
view.$el.on('click', function(){ counter2++; });
|
||||||
var events = {"click #qunit-banner": "increment"};
|
|
||||||
|
var events = {'click #test': 'increment'};
|
||||||
|
|
||||||
view.delegateEvents(events);
|
view.delegateEvents(events);
|
||||||
$('#qunit-banner').trigger('click');
|
view.$('#test').trigger('click');
|
||||||
equal(counter, 1);
|
equal(counter1, 1);
|
||||||
equal(counter2, 1);
|
equal(counter2, 1);
|
||||||
$('#qunit-banner').trigger('click');
|
|
||||||
equal(counter, 2);
|
view.$('#test').trigger('click');
|
||||||
|
equal(counter1, 2);
|
||||||
equal(counter2, 2);
|
equal(counter2, 2);
|
||||||
|
|
||||||
view.delegateEvents(events);
|
view.delegateEvents(events);
|
||||||
$('#qunit-banner').trigger('click');
|
view.$('#test').trigger('click');
|
||||||
equal(counter, 3);
|
equal(counter1, 3);
|
||||||
equal(counter2, 3);
|
equal(counter2, 3);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("View: delegateEvents allows functions for callbacks", 3, function() {
|
test("delegateEvents allows functions for callbacks", 3, function() {
|
||||||
|
var view = new Backbone.View({el: '<p></p>'});
|
||||||
view.counter = 0;
|
view.counter = 0;
|
||||||
view.setElement("#qunit-banner");
|
|
||||||
var events = {"click": function() { this.counter++; }};
|
var events = {
|
||||||
|
click: function() {
|
||||||
|
this.counter++;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
view.delegateEvents(events);
|
view.delegateEvents(events);
|
||||||
$('#qunit-banner').trigger('click');
|
view.$el.trigger('click');
|
||||||
equal(view.counter, 1);
|
equal(view.counter, 1);
|
||||||
$('#qunit-banner').trigger('click');
|
|
||||||
|
view.$el.trigger('click');
|
||||||
equal(view.counter, 2);
|
equal(view.counter, 2);
|
||||||
|
|
||||||
view.delegateEvents(events);
|
view.delegateEvents(events);
|
||||||
$('#qunit-banner').trigger('click');
|
view.$el.trigger('click');
|
||||||
equal(view.counter, 3);
|
equal(view.counter, 3);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("View: undelegateEvents", 6, function() {
|
test("undelegateEvents", 6, function() {
|
||||||
var counter = 0;
|
var counter1 = 0, counter2 = 0;
|
||||||
var counter2 = 0;
|
|
||||||
view.setElement(document.body);
|
var view = new Backbone.View({el: '<p><a id="test"></a></p>'});
|
||||||
view.increment = function(){ counter++; };
|
view.increment = function(){ counter1++; };
|
||||||
$(view.el).unbind('click');
|
view.$el.on('click', function(){ counter2++; });
|
||||||
$(view.el).bind('click', function(){ counter2++; });
|
|
||||||
var events = {"click #qunit-userAgent": "increment"};
|
var events = {'click #test': 'increment'};
|
||||||
|
|
||||||
view.delegateEvents(events);
|
view.delegateEvents(events);
|
||||||
$('#qunit-userAgent').trigger('click');
|
view.$('#test').trigger('click');
|
||||||
equal(counter, 1);
|
equal(counter1, 1);
|
||||||
equal(counter2, 1);
|
equal(counter2, 1);
|
||||||
|
|
||||||
view.undelegateEvents();
|
view.undelegateEvents();
|
||||||
$('#qunit-userAgent').trigger('click');
|
view.$('#test').trigger('click');
|
||||||
equal(counter, 1);
|
equal(counter1, 1);
|
||||||
equal(counter2, 2);
|
equal(counter2, 2);
|
||||||
|
|
||||||
view.delegateEvents(events);
|
view.delegateEvents(events);
|
||||||
$('#qunit-userAgent').trigger('click');
|
view.$('#test').trigger('click');
|
||||||
equal(counter, 2);
|
equal(counter1, 2);
|
||||||
equal(counter2, 3);
|
equal(counter2, 3);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("View: _ensureElement with DOM node el", 1, function() {
|
test("_ensureElement with DOM node el", 1, function() {
|
||||||
var ViewClass = Backbone.View.extend({
|
var View = Backbone.View.extend({
|
||||||
el: document.body
|
el: document.body
|
||||||
});
|
});
|
||||||
var view = new ViewClass;
|
|
||||||
equal(view.el, document.body);
|
equal(new View().el, document.body);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("View: _ensureElement with string el", 3, function() {
|
test("_ensureElement with string el", 3, function() {
|
||||||
var ViewClass = Backbone.View.extend({
|
var View = Backbone.View.extend({
|
||||||
el: "body"
|
el: "body"
|
||||||
});
|
});
|
||||||
var view = new ViewClass;
|
strictEqual(new View().el, document.body);
|
||||||
strictEqual(view.el, document.body);
|
|
||||||
|
|
||||||
ViewClass = Backbone.View.extend({
|
View = Backbone.View.extend({
|
||||||
el: "#testElement > h1"
|
el: "#testElement > h1"
|
||||||
});
|
});
|
||||||
view = new ViewClass;
|
strictEqual(new View().el, $("#testElement > h1").get(0));
|
||||||
strictEqual(view.el, $("#testElement > h1").get(0));
|
|
||||||
|
|
||||||
ViewClass = Backbone.View.extend({
|
View = Backbone.View.extend({
|
||||||
el: "#nonexistent"
|
el: "#nonexistent"
|
||||||
});
|
});
|
||||||
view = new ViewClass;
|
ok(!new View().el);
|
||||||
ok(!view.el);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("View: with attributes", 2, function() {
|
test("with className and id functions", 2, function() {
|
||||||
var view = new Backbone.View({attributes : {'class': 'one', id: 'two'}});
|
var View = Backbone.View.extend({
|
||||||
equal(view.el.className, 'one');
|
className: function() {
|
||||||
equal(view.el.id, 'two');
|
return 'className';
|
||||||
|
},
|
||||||
|
id: function() {
|
||||||
|
return 'id';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
strictEqual(new View().el.className, 'className');
|
||||||
|
strictEqual(new View().el.id, 'id');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("View: with attributes as a function", 1, function() {
|
test("with options function", 3, function() {
|
||||||
var viewClass = Backbone.View.extend({
|
var View1 = Backbone.View.extend({
|
||||||
|
options: function() {
|
||||||
|
return {
|
||||||
|
title: 'title1',
|
||||||
|
acceptText: 'confirm'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var View2 = View1.extend({
|
||||||
|
options: function() {
|
||||||
|
return _.extend(View1.prototype.options.call(this), {
|
||||||
|
title: 'title2',
|
||||||
|
fixed: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
strictEqual(new View2().options.title, 'title2');
|
||||||
|
strictEqual(new View2().options.acceptText, 'confirm');
|
||||||
|
strictEqual(new View2().options.fixed, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("with attributes", 2, function() {
|
||||||
|
var View = Backbone.View.extend({
|
||||||
|
attributes: {
|
||||||
|
id: 'id',
|
||||||
|
'class': 'class'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
strictEqual(new View().el.className, 'class');
|
||||||
|
strictEqual(new View().el.id, 'id');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("with attributes as a function", 1, function() {
|
||||||
|
var View = Backbone.View.extend({
|
||||||
attributes: function() {
|
attributes: function() {
|
||||||
return {'class': 'dynamic'};
|
return {'class': 'dynamic'};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
equal((new viewClass).el.className, 'dynamic');
|
|
||||||
|
strictEqual(new View().el.className, 'dynamic');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("View: multiple views per element", 3, function() {
|
test("multiple views per element", 3, function() {
|
||||||
var count = 0, ViewClass = Backbone.View.extend({
|
var count = 0;
|
||||||
el: $("body"),
|
var $el = $('<p></p>');
|
||||||
|
|
||||||
|
var View = Backbone.View.extend({
|
||||||
|
el: $el,
|
||||||
events: {
|
events: {
|
||||||
"click": "click"
|
click: function() {
|
||||||
},
|
count++;
|
||||||
click: function() {
|
}
|
||||||
count++;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var view1 = new ViewClass;
|
var view1 = new View;
|
||||||
$("body").trigger("click");
|
$el.trigger("click");
|
||||||
equal(1, count);
|
equal(1, count);
|
||||||
|
|
||||||
var view2 = new ViewClass;
|
var view2 = new View;
|
||||||
$("body").trigger("click");
|
$el.trigger("click");
|
||||||
equal(3, count);
|
equal(3, count);
|
||||||
|
|
||||||
view1.delegateEvents();
|
view1.delegateEvents();
|
||||||
$("body").trigger("click");
|
$el.trigger("click");
|
||||||
equal(5, count);
|
equal(5, count);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("View: custom events, with namespaces", 2, function() {
|
test("custom events, with namespaces", 2, function() {
|
||||||
var count = 0;
|
var count = 0;
|
||||||
var ViewClass = Backbone.View.extend({
|
|
||||||
|
var View = Backbone.View.extend({
|
||||||
el: $('body'),
|
el: $('body'),
|
||||||
events: function() {
|
events: function() {
|
||||||
return {"fake$event.namespaced": "run"};
|
return {"fake$event.namespaced": "run"};
|
||||||
@@ -186,9 +234,10 @@ $(document).ready(function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var view = new ViewClass;
|
var view = new View;
|
||||||
$('body').trigger('fake$event').trigger('fake$event');
|
$('body').trigger('fake$event').trigger('fake$event');
|
||||||
equal(count, 2);
|
equal(count, 2);
|
||||||
|
|
||||||
$('body').unbind('.namespaced');
|
$('body').unbind('.namespaced');
|
||||||
$('body').trigger('fake$event');
|
$('body').trigger('fake$event');
|
||||||
equal(count, 2);
|
equal(count, 2);
|
||||||
@@ -196,35 +245,106 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
test("#1048 - setElement uses provided object.", 2, function() {
|
test("#1048 - setElement uses provided object.", 2, function() {
|
||||||
var $el = $('body');
|
var $el = $('body');
|
||||||
|
|
||||||
var view = new Backbone.View({el: $el});
|
var view = new Backbone.View({el: $el});
|
||||||
ok(view.$el === $el);
|
ok(view.$el === $el);
|
||||||
|
|
||||||
view.setElement($el = $($el));
|
view.setElement($el = $($el));
|
||||||
ok(view.$el === $el);
|
ok(view.$el === $el);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("#986 - Undelegate before changing element.", 1, function() {
|
test("#986 - Undelegate before changing element.", 1, function() {
|
||||||
var a = $('<button></button>');
|
var button1 = $('<button></button>');
|
||||||
var b = $('<button></button>');
|
var button2 = $('<button></button>');
|
||||||
|
|
||||||
var View = Backbone.View.extend({
|
var View = Backbone.View.extend({
|
||||||
events: {click: function(e) { ok(view.el === e.target); }}
|
events: {
|
||||||
|
click: function(e) {
|
||||||
|
ok(view.el === e.target);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
var view = new View({el: a});
|
|
||||||
view.setElement(b);
|
var view = new View({el: button1});
|
||||||
a.trigger('click');
|
view.setElement(button2);
|
||||||
b.trigger('click');
|
|
||||||
|
button1.trigger('click');
|
||||||
|
button2.trigger('click');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("#1172 - Clone attributes object", 2, function() {
|
test("#1172 - Clone attributes object", 2, function() {
|
||||||
var View = Backbone.View.extend({attributes: {foo: 'bar'}});
|
var View = Backbone.View.extend({
|
||||||
var v1 = new View({id: 'foo'});
|
attributes: {foo: 'bar'}
|
||||||
strictEqual(v1.el.id, 'foo');
|
});
|
||||||
var v2 = new View();
|
|
||||||
ok(!v2.el.id);
|
var view1 = new View({id: 'foo'});
|
||||||
|
strictEqual(view1.el.id, 'foo');
|
||||||
|
|
||||||
|
var view2 = new View();
|
||||||
|
ok(!view2.el.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("#1228 - tagName can be provided as a function", 1, function() {
|
test("#1228 - tagName can be provided as a function", 1, function() {
|
||||||
var View = Backbone.View.extend({tagName: function(){ return 'p'; }});
|
var View = Backbone.View.extend({
|
||||||
|
tagName: function() {
|
||||||
|
return 'p';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
ok(new View().$el.is('p'));
|
ok(new View().$el.is('p'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("views stopListening", 0, function() {
|
||||||
|
var View = Backbone.View.extend({
|
||||||
|
initialize: function() {
|
||||||
|
this.listenTo(this.model, 'all x', function(){ ok(false); }, this);
|
||||||
|
this.listenTo(this.collection, 'all x', function(){ ok(false); }, this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var view = new View({
|
||||||
|
model: new Backbone.Model,
|
||||||
|
collection: new Backbone.Collection
|
||||||
|
});
|
||||||
|
|
||||||
|
view.stopListening();
|
||||||
|
view.model.trigger('x');
|
||||||
|
view.collection.trigger('x');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Provide function for el.", 1, function() {
|
||||||
|
var View = Backbone.View.extend({
|
||||||
|
el: function() {
|
||||||
|
return "<p><a></a></p>";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var view = new View;
|
||||||
|
ok(view.$el.is('p:has(a)'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test("events passed in options", 2, function() {
|
||||||
|
var counter = 0;
|
||||||
|
|
||||||
|
var View = Backbone.View.extend({
|
||||||
|
el: '<p><a id="test"></a></p>',
|
||||||
|
increment: function() {
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var view = new View({events:{'click #test':'increment'}});
|
||||||
|
var view2 = new View({events:function(){
|
||||||
|
return {'click #test':'increment'};
|
||||||
|
}});
|
||||||
|
|
||||||
|
view.$('#test').trigger('click');
|
||||||
|
view2.$('#test').trigger('click');
|
||||||
|
equal(counter, 2);
|
||||||
|
|
||||||
|
view.$('#test').trigger('click');
|
||||||
|
view2.$('#test').trigger('click');
|
||||||
|
equal(counter, 4);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
4
vendor/benchmark.js/LICENSE.txt
vendored
4
vendor/benchmark.js/LICENSE.txt
vendored
@@ -1,4 +1,4 @@
|
|||||||
Copyright 2010-2012 Mathias Bynens <http://mathiasbynens.be/>
|
Copyright 2010-2013 Mathias Bynens <http://mathiasbynens.be/>
|
||||||
Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
|
Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
|
||||||
Modified by John-David Dalton <http://allyoucanleet.com/>
|
Modified by John-David Dalton <http://allyoucanleet.com/>
|
||||||
|
|
||||||
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
58
vendor/benchmark.js/README.md
vendored
58
vendor/benchmark.js/README.md
vendored
@@ -1,30 +1,35 @@
|
|||||||
# Benchmark.js <sup>v1.0.0-pre</sup>
|
# Benchmark.js <sup>v1.0.0</sup>
|
||||||
|
[](http://travis-ci.org/bestiejs/benchmark.js)
|
||||||
|
|
||||||
A [robust](http://calendar.perfplanet.com/2010/bulletproof-javascript-benchmarks/ "Bulletproof JavaScript benchmarks") benchmarking library that works on nearly all JavaScript platforms<sup><a name="fnref1" href="#fn1">1</a></sup>, supports high-resolution timers, and returns statistically significant results. As seen on [jsPerf](http://jsperf.com/).
|
A [robust](http://calendar.perfplanet.com/2010/bulletproof-javascript-benchmarks/ "Bulletproof JavaScript benchmarks") benchmarking library that works on nearly all JavaScript platforms<sup><a name="fnref1" href="#fn1">1</a></sup>, supports high-resolution timers, and returns statistically significant results. As seen on [jsPerf](http://jsperf.com/).
|
||||||
|
|
||||||
## BestieJS
|
## Download
|
||||||
|
|
||||||
Benchmark.js 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.
|
* [Development source](https://raw.github.com/bestiejs/benchmark.js/v1.0.0/benchmark.js)
|
||||||
|
|
||||||
## Documentation
|
## Dive in
|
||||||
|
|
||||||
The documentation for Benchmark.js can be viewed here: <http://benchmarkjs.com/docs>
|
We’ve got [API docs](http://benchmarkjs.com/docs) and [unit tests](http://benchmarkjs.com/tests).
|
||||||
|
|
||||||
For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/benchmark.js/wiki/Roadmap).
|
For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/benchmark.js/wiki/Roadmap).
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
Benchmark.js has been tested in at least Adobe AIR 3.1, Chrome 5-21, Firefox 1-15, IE 6-9, Opera 9.25-12, Safari 3-6, Node.js 0.8.8, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC5.
|
||||||
|
|
||||||
## Installation and usage
|
## Installation and usage
|
||||||
|
|
||||||
In a browser or Adobe AIR:
|
In a browser or Adobe AIR:
|
||||||
|
|
||||||
~~~ html
|
```html
|
||||||
<script src="benchmark.js"></script>
|
<script src="benchmark.js"></script>
|
||||||
~~~
|
```
|
||||||
|
|
||||||
Optionally, expose Java’s nanosecond timer by adding the `nano` applet to the `<body>`:
|
Optionally, expose Java’s nanosecond timer by adding the `nano` applet to the `<body>`:
|
||||||
|
|
||||||
~~~ html
|
```html
|
||||||
<applet code="nano" archive="nano.jar"></applet>
|
<applet code="nano" archive="nano.jar"></applet>
|
||||||
~~~
|
```
|
||||||
|
|
||||||
Or enable Chrome’s microsecond timer by using the [command line switch](http://peter.sh/experiments/chromium-command-line-switches/#enable-benchmarking):
|
Or enable Chrome’s microsecond timer by using the [command line switch](http://peter.sh/experiments/chromium-command-line-switches/#enable-benchmarking):
|
||||||
|
|
||||||
@@ -32,37 +37,37 @@ Or enable Chrome’s microsecond timer by using the [command line switch](http:/
|
|||||||
|
|
||||||
Via [npm](http://npmjs.org/):
|
Via [npm](http://npmjs.org/):
|
||||||
|
|
||||||
~~~ bash
|
```bash
|
||||||
npm install benchmark
|
npm install benchmark
|
||||||
~~~
|
```
|
||||||
|
|
||||||
In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
|
In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
var Benchmark = require('benchmark');
|
var Benchmark = require('benchmark');
|
||||||
~~~
|
```
|
||||||
|
|
||||||
Optionally, use the [microtime module](https://github.com/wadey/node-microtime) by Wade Simmons:
|
Optionally, use the [microtime module](https://github.com/wadey/node-microtime) by Wade Simmons:
|
||||||
|
|
||||||
~~~ bash
|
```bash
|
||||||
npm install microtime
|
npm install microtime
|
||||||
~~~
|
```
|
||||||
|
|
||||||
In [Narwhal](http://narwhaljs.org/) and [RingoJS v0.7.0-](http://ringojs.org/):
|
In [RingoJS v0.7.0-](http://ringojs.org/):
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
var Benchmark = require('benchmark').Benchmark;
|
var Benchmark = require('benchmark').Benchmark;
|
||||||
~~~
|
```
|
||||||
|
|
||||||
In [Rhino](http://www.mozilla.org/rhino/):
|
In [Rhino](http://www.mozilla.org/rhino/):
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
load('benchmark.js');
|
load('benchmark.js');
|
||||||
~~~
|
```
|
||||||
|
|
||||||
In an AMD loader like [RequireJS](http://requirejs.org/):
|
In an AMD loader like [RequireJS](http://requirejs.org/):
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
require({
|
require({
|
||||||
'paths': {
|
'paths': {
|
||||||
'benchmark': 'path/to/benchmark'
|
'benchmark': 'path/to/benchmark'
|
||||||
@@ -84,11 +89,11 @@ require({
|
|||||||
Benchmark.platform = platform;
|
Benchmark.platform = platform;
|
||||||
console.log(Benchmark.platform.name);
|
console.log(Benchmark.platform.name);
|
||||||
});
|
});
|
||||||
~~~
|
```
|
||||||
|
|
||||||
Usage example:
|
Usage example:
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
var suite = new Benchmark.Suite;
|
var suite = new Benchmark.Suite;
|
||||||
|
|
||||||
// add tests
|
// add tests
|
||||||
@@ -112,12 +117,11 @@ suite.add('RegExp#test', function() {
|
|||||||
// > RegExp#test x 4,161,532 +-0.99% (59 cycles)
|
// > RegExp#test x 4,161,532 +-0.99% (59 cycles)
|
||||||
// > String#indexOf x 6,139,623 +-1.00% (131 cycles)
|
// > String#indexOf x 6,139,623 +-1.00% (131 cycles)
|
||||||
// > Fastest is String#indexOf
|
// > Fastest is String#indexOf
|
||||||
~~~
|
```
|
||||||
|
|
||||||
## Footnotes
|
## BestieJS
|
||||||
|
|
||||||
1. Benchmark.js has been tested in at least Adobe AIR 2.6, Chrome 5-15, Firefox 1.5-8, IE 6-10, Opera 9.25-11.52, Safari 2-5.1.1, Node.js 0.4.8-0.6.1, Narwhal 0.3.2, RingoJS 0.7-0.8, and Rhino 1.7RC3.
|
Benchmark.js 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.
|
||||||
<a name="fn1" title="Jump back to footnote 1 in the text." href="#fnref1">↩</a>
|
|
||||||
|
|
||||||
## Authors
|
## Authors
|
||||||
|
|
||||||
|
|||||||
291
vendor/benchmark.js/benchmark.js
vendored
291
vendor/benchmark.js/benchmark.js
vendored
@@ -1,6 +1,6 @@
|
|||||||
/*!
|
/*!
|
||||||
* Benchmark.js v1.0.0-pre <http://benchmarkjs.com/>
|
* Benchmark.js v1.0.0 <http://benchmarkjs.com/>
|
||||||
* Copyright 2010-2012 Mathias Bynens <http://mths.be/>
|
* Copyright 2010-2013 Mathias Bynens <http://mths.be/>
|
||||||
* Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
|
* Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
|
||||||
* Modified by John-David Dalton <http://allyoucanleet.com/>
|
* Modified by John-David Dalton <http://allyoucanleet.com/>
|
||||||
* Available under MIT license <http://mths.be/mit>
|
* Available under MIT license <http://mths.be/mit>
|
||||||
@@ -25,6 +25,9 @@
|
|||||||
/** Detect free variable `require` */
|
/** Detect free variable `require` */
|
||||||
var freeRequire = typeof require == 'function' && require;
|
var freeRequire = typeof require == 'function' && require;
|
||||||
|
|
||||||
|
/** Used to store the `Object` built-in in case it's overwritten later */
|
||||||
|
var Object = window.Object;
|
||||||
|
|
||||||
/** Used to crawl all properties regardless of enumerability */
|
/** Used to crawl all properties regardless of enumerability */
|
||||||
var getAllKeys = Object.getOwnPropertyNames;
|
var getAllKeys = Object.getOwnPropertyNames;
|
||||||
|
|
||||||
@@ -244,6 +247,36 @@
|
|||||||
} catch(e) {
|
} catch(e) {
|
||||||
support.getAllKeys = false;
|
support.getAllKeys = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect if own properties are iterated before inherited properties (all but IE < 9).
|
||||||
|
*
|
||||||
|
* @name iteratesOwnLast
|
||||||
|
* @memberOf Benchmark.support
|
||||||
|
* @type Boolean
|
||||||
|
*/
|
||||||
|
support.iteratesOwnFirst = (function() {
|
||||||
|
var props = [];
|
||||||
|
function ctor() { this.x = 1; }
|
||||||
|
ctor.prototype = { 'y': 1 };
|
||||||
|
for (var prop in new ctor) { props.push(prop); }
|
||||||
|
return props[0] == 'x';
|
||||||
|
}());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect if a node's [[Class]] is resolvable (all but IE < 9)
|
||||||
|
* and that the JS engine errors when attempting to coerce an object to a
|
||||||
|
* string without a `toString` property value of `typeof` "function".
|
||||||
|
*
|
||||||
|
* @name nodeClass
|
||||||
|
* @memberOf Benchmark.support
|
||||||
|
* @type Boolean
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
support.nodeClass = ({ 'toString': 0 } + '', toString.call(doc || 0) != '[object Object]');
|
||||||
|
} catch(e) {
|
||||||
|
support.nodeClass = true;
|
||||||
|
}
|
||||||
}());
|
}());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -290,6 +323,7 @@
|
|||||||
/** Math shortcuts */
|
/** Math shortcuts */
|
||||||
var abs = Math.abs,
|
var abs = Math.abs,
|
||||||
floor = Math.floor,
|
floor = Math.floor,
|
||||||
|
log = Math.log,
|
||||||
max = Math.max,
|
max = Math.max,
|
||||||
min = Math.min,
|
min = Math.min,
|
||||||
pow = Math.pow,
|
pow = Math.pow,
|
||||||
@@ -583,14 +617,17 @@
|
|||||||
while (++index < length) {
|
while (++index < length) {
|
||||||
if ((index - start) in tail) {
|
if ((index - start) in tail) {
|
||||||
object[index] = tail[index - start];
|
object[index] = tail[index - start];
|
||||||
} else {
|
} else if (index in object) {
|
||||||
delete object[index];
|
delete object[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// delete excess elements
|
// delete excess elements
|
||||||
deleteCount = deleteCount > elementCount ? deleteCount - elementCount : 0;
|
deleteCount = deleteCount > elementCount ? deleteCount - elementCount : 0;
|
||||||
while (deleteCount--) {
|
while (deleteCount--) {
|
||||||
delete object[length + deleteCount];
|
index = length + deleteCount;
|
||||||
|
if (index in object) {
|
||||||
|
delete object[index];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
object.length = length;
|
object.length = length;
|
||||||
return result;
|
return result;
|
||||||
@@ -912,6 +949,20 @@
|
|||||||
(/^[\s(]*function[^(]*\(([^\s,)]+)/.exec(fn) || 0)[1]) || '';
|
(/^[\s(]*function[^(]*\(([^\s,)]+)/.exec(fn) || 0)[1]) || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the geometric mean (log-average) of a sample.
|
||||||
|
* See http://en.wikipedia.org/wiki/Geometric_mean#Relationship_with_arithmetic_mean_of_logarithms.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {Array} sample The sample.
|
||||||
|
* @returns {Number} The geometric mean.
|
||||||
|
*/
|
||||||
|
function getGeometricMean(sample) {
|
||||||
|
return pow(Math.E, reduce(sample, function(sum, x) {
|
||||||
|
return sum + log(x);
|
||||||
|
}) / sample.length) || 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the arithmetic mean of a sample.
|
* Computes the arithmetic mean of a sample.
|
||||||
*
|
*
|
||||||
@@ -920,9 +971,9 @@
|
|||||||
* @returns {Number} The mean.
|
* @returns {Number} The mean.
|
||||||
*/
|
*/
|
||||||
function getMean(sample) {
|
function getMean(sample) {
|
||||||
return reduce(sample, function(sum, x) {
|
return (reduce(sample, function(sum, x) {
|
||||||
return sum + x;
|
return sum + x;
|
||||||
}) / sample.length || 0;
|
}) / sample.length) || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -939,9 +990,15 @@
|
|||||||
result = String(fn);
|
result = String(fn);
|
||||||
} else if (support.decompilation) {
|
} else if (support.decompilation) {
|
||||||
// escape the `{` for Firefox 1
|
// escape the `{` for Firefox 1
|
||||||
result = (/^[^{]+\{([\s\S]*)}\s*$/.exec(fn) || 0)[1];
|
result = (/^[^{]+\{([\s\S]*)\}\s*$/.exec(fn) || 0)[1];
|
||||||
}
|
}
|
||||||
return (result || '').replace(/^\s+|\s+$/g, '');
|
// trim string
|
||||||
|
result = (result || '').replace(/^\s+|\s+$/g, '');
|
||||||
|
|
||||||
|
// detect strings containing only the "use strict" directive
|
||||||
|
return /^(?:\/\*+[\w|\W]*?\*\/|\/\/.*?[\n\r\u2028\u2029]|\s)*(["'])use strict\1;?$/.test(result)
|
||||||
|
? ''
|
||||||
|
: result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -994,36 +1051,43 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the specified `value` is an object created by the `Object`
|
* Checks if a given `value` is an object created by the `Object` constructor
|
||||||
* constructor assuming objects created by the `Object` constructor have no
|
* assuming objects created by the `Object` constructor have no inherited
|
||||||
* inherited enumerable properties and assuming there are no `Object.prototype`
|
* enumerable properties and that there are no `Object.prototype` extensions.
|
||||||
* extensions.
|
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {Mixed} value The value to check.
|
* @param {Mixed} value The value to check.
|
||||||
* @returns {Boolean} Returns `true` if `value` is an object, else `false`.
|
* @returns {Boolean} Returns `true` if the `value` is a plain `Object` object, else `false`.
|
||||||
*/
|
*/
|
||||||
function isObject(value) {
|
function isPlainObject(value) {
|
||||||
var ctor,
|
// avoid non-objects and false positives for `arguments` objects in IE < 9
|
||||||
result = !!value && toString.call(value) == '[object Object]';
|
var result = false;
|
||||||
|
if (!(value && typeof value == 'object') || isArguments(value)) {
|
||||||
if (result && noArgumentsClass) {
|
return result;
|
||||||
// avoid false positives for `arguments` objects in IE < 9
|
|
||||||
result = !isArguments(value);
|
|
||||||
}
|
}
|
||||||
if (result) {
|
// IE < 9 presents DOM nodes as `Object` objects except they have `toString`
|
||||||
// IE < 9 presents nodes like `Object` objects:
|
// methods that are `typeof` "string" and still can coerce nodes to strings.
|
||||||
// IE < 8 are missing the node's constructor property
|
// Also check that the constructor is `Object` (i.e. `Object instanceof Object`)
|
||||||
// IE 8 node constructors are typeof "object"
|
var ctor = value.constructor;
|
||||||
ctor = value.constructor;
|
if ((support.nodeClass || !(typeof value.toString != 'function' && typeof (value + '') == 'string')) &&
|
||||||
// check if the constructor is `Object` as `Object instanceof Object` is `true`
|
(!isClassOf(ctor, 'Function') || ctor instanceof ctor)) {
|
||||||
if ((result = isClassOf(ctor, 'Function') && ctor instanceof ctor)) {
|
// In most environments an object's own properties are iterated before
|
||||||
// An object's own properties are iterated before inherited properties.
|
// its inherited properties. If the last iterated property is an object's
|
||||||
// If the last iterated key belongs to an object's own property then
|
// own property then there are no inherited enumerable properties.
|
||||||
// there are no inherited enumerable properties.
|
if (support.iteratesOwnFirst) {
|
||||||
forProps(value, function(subValue, subKey) { result = subKey; });
|
forProps(value, function(subValue, subKey) {
|
||||||
result = result === true || hasKey(value, result);
|
result = subKey;
|
||||||
|
});
|
||||||
|
return result === false || hasKey(value, result);
|
||||||
}
|
}
|
||||||
|
// IE < 9 iterates inherited properties before own properties. If the first
|
||||||
|
// iterated property is an object's own property then there are no inherited
|
||||||
|
// enumerable properties.
|
||||||
|
forProps(value, function(subValue, subKey) {
|
||||||
|
result = !hasKey(value, subKey);
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
return result === false;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1265,7 +1329,7 @@
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '[object Object]':
|
case '[object Object]':
|
||||||
isObject(value) && (clone = new ctor);
|
isPlainObject(value) && (clone = {});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '[object Number]':
|
case '[object Number]':
|
||||||
@@ -1584,7 +1648,10 @@
|
|||||||
function interpolate(string, object) {
|
function interpolate(string, object) {
|
||||||
forOwn(object, function(value, key) {
|
forOwn(object, function(value, key) {
|
||||||
// escape regexp special characters in `key`
|
// escape regexp special characters in `key`
|
||||||
string = string.replace(RegExp('#\\{' + key.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1') + '\\}', 'g'), value);
|
string = string.replace(
|
||||||
|
RegExp('#\\{' + key.replace(/([.*+?^${}()|[\]\\])/g, '\\$1') + '\\}', 'g'),
|
||||||
|
value.replace(/\$/g, '$$$$')
|
||||||
|
);
|
||||||
});
|
});
|
||||||
return string;
|
return string;
|
||||||
}
|
}
|
||||||
@@ -2030,6 +2097,10 @@
|
|||||||
event.aborted = me.aborted;
|
event.aborted = me.aborted;
|
||||||
},
|
},
|
||||||
'onComplete': function(event) {
|
'onComplete': function(event) {
|
||||||
|
me.score = getGeometricMean(map(me, function(bench) {
|
||||||
|
return bench.reference / (bench.times.period * 1e6);
|
||||||
|
})) || 0;
|
||||||
|
|
||||||
me.running = false;
|
me.running = false;
|
||||||
me.emit(event);
|
me.emit(event);
|
||||||
}
|
}
|
||||||
@@ -2405,13 +2476,12 @@
|
|||||||
|
|
||||||
var source = {
|
var source = {
|
||||||
'setup': getSource(bench.setup, preprocess('m$.setup()')),
|
'setup': getSource(bench.setup, preprocess('m$.setup()')),
|
||||||
'fn': getSource(fn, preprocess('f$(' + fnArg + ')')),
|
'fn': getSource(fn, preprocess('m$.fn(' + fnArg + ')')),
|
||||||
'fnArg': fnArg,
|
'fnArg': fnArg,
|
||||||
'teardown': getSource(bench.teardown, preprocess('m$.teardown()'))
|
'teardown': getSource(bench.teardown, preprocess('m$.teardown()'))
|
||||||
};
|
};
|
||||||
|
|
||||||
var compiled = bench.compiled,
|
var count = bench.count = clone.count,
|
||||||
count = bench.count = clone.count,
|
|
||||||
decompilable = support.decompilation || stringable,
|
decompilable = support.decompilation || stringable,
|
||||||
id = bench.id,
|
id = bench.id,
|
||||||
isEmpty = !(source.fn || stringable),
|
isEmpty = !(source.fn || stringable),
|
||||||
@@ -2433,77 +2503,77 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!compiled) {
|
// Compile in setup/teardown functions and the test loop.
|
||||||
// compile in setup/teardown functions and the test loop
|
// Create a new compiled test, instead of using the cached `bench.compiled`,
|
||||||
compiled = bench.compiled = createFunction(preprocess('t$'), interpolate(
|
// to avoid potential engine optimizations enabled over the life of the test.
|
||||||
preprocess(deferred
|
var compiled = bench.compiled = createFunction(preprocess('t$'), interpolate(
|
||||||
? 'var d$=this,#{fnArg}=d$,m$=d$.benchmark._original,f$=m$.fn,su$=m$.setup,td$=m$.teardown;' +
|
preprocess(deferred
|
||||||
// when `deferred.cycles` is `0` then...
|
? 'var d$=this,#{fnArg}=d$,m$=d$.benchmark._original,f$=m$.fn,su$=m$.setup,td$=m$.teardown;' +
|
||||||
'if(!d$.cycles){' +
|
// when `deferred.cycles` is `0` then...
|
||||||
// set `deferred.fn`
|
'if(!d$.cycles){' +
|
||||||
'd$.fn=function(){var #{fnArg}=d$;if(typeof f$=="function"){try{#{fn}\n}catch(e$){f$(d$)}}else{#{fn}\n}};' +
|
// set `deferred.fn`
|
||||||
// set `deferred.teardown`
|
'd$.fn=function(){var #{fnArg}=d$;if(typeof f$=="function"){try{#{fn}\n}catch(e$){f$(d$)}}else{#{fn}\n}};' +
|
||||||
'd$.teardown=function(){d$.cycles=0;if(typeof td$=="function"){try{#{teardown}\n}catch(e$){td$()}}else{#{teardown}\n}};' +
|
// set `deferred.teardown`
|
||||||
// execute the benchmark's `setup`
|
'd$.teardown=function(){d$.cycles=0;if(typeof td$=="function"){try{#{teardown}\n}catch(e$){td$()}}else{#{teardown}\n}};' +
|
||||||
'if(typeof su$=="function"){try{#{setup}\n}catch(e$){su$()}}else{#{setup}\n};' +
|
// execute the benchmark's `setup`
|
||||||
// start timer
|
'if(typeof su$=="function"){try{#{setup}\n}catch(e$){su$()}}else{#{setup}\n};' +
|
||||||
't$.start(d$);' +
|
// start timer
|
||||||
// execute `deferred.fn` and return a dummy object
|
't$.start(d$);' +
|
||||||
'}d$.fn();return{}'
|
// execute `deferred.fn` and return a dummy object
|
||||||
|
'}d$.fn();return{}'
|
||||||
|
|
||||||
: 'var r$,s$,m$=this,f$=m$.fn,i$=m$.count,n$=t$.ns;#{setup}\n#{begin};' +
|
: 'var r$,s$,m$=this,f$=m$.fn,i$=m$.count,n$=t$.ns;#{setup}\n#{begin};' +
|
||||||
'while(i$--){#{fn}\n}#{end};#{teardown}\nreturn{elapsed:r$,uid:"#{uid}"}'),
|
'while(i$--){#{fn}\n}#{end};#{teardown}\nreturn{elapsed:r$,uid:"#{uid}"}'),
|
||||||
|
source
|
||||||
|
));
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (isEmpty) {
|
||||||
|
// Firefox may remove dead code from Function#toString results
|
||||||
|
// http://bugzil.la/536085
|
||||||
|
throw new Error('The test "' + name + '" is empty. This may be the result of dead code removal.');
|
||||||
|
}
|
||||||
|
else if (!deferred) {
|
||||||
|
// pretest to determine if compiled code is exits early, usually by a
|
||||||
|
// rogue `return` statement, by checking for a return object with the uid
|
||||||
|
bench.count = 1;
|
||||||
|
compiled = (compiled.call(bench, timer) || {}).uid == uid && compiled;
|
||||||
|
bench.count = count;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
compiled = null;
|
||||||
|
clone.error = e || new Error(String(e));
|
||||||
|
bench.count = count;
|
||||||
|
}
|
||||||
|
// fallback when a test exits early or errors during pretest
|
||||||
|
if (decompilable && !compiled && !deferred && !isEmpty) {
|
||||||
|
compiled = createFunction(preprocess('t$'), interpolate(
|
||||||
|
preprocess(
|
||||||
|
(clone.error && !stringable
|
||||||
|
? 'var r$,s$,m$=this,f$=m$.fn,i$=m$.count'
|
||||||
|
: 'function f$(){#{fn}\n}var r$,s$,m$=this,i$=m$.count'
|
||||||
|
) +
|
||||||
|
',n$=t$.ns;#{setup}\n#{begin};m$.f$=f$;while(i$--){m$.f$()}#{end};' +
|
||||||
|
'delete m$.f$;#{teardown}\nreturn{elapsed:r$}'
|
||||||
|
),
|
||||||
source
|
source
|
||||||
));
|
));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (isEmpty) {
|
// pretest one more time to check for errors
|
||||||
// Firefox may remove dead code from Function#toString results
|
bench.count = 1;
|
||||||
// http://bugzil.la/536085
|
compiled.call(bench, timer);
|
||||||
throw new Error('The test "' + name + '" is empty. This may be the result of dead code removal.');
|
bench.compiled = compiled;
|
||||||
}
|
|
||||||
else if (!deferred) {
|
|
||||||
// pretest to determine if compiled code is exits early, usually by a
|
|
||||||
// rogue `return` statement, by checking for a return object with the uid
|
|
||||||
bench.count = 1;
|
|
||||||
compiled = (compiled.call(bench, timer) || {}).uid == uid && compiled;
|
|
||||||
bench.count = count;
|
|
||||||
}
|
|
||||||
} catch(e) {
|
|
||||||
compiled = null;
|
|
||||||
clone.error = e || new Error(String(e));
|
|
||||||
bench.count = count;
|
bench.count = count;
|
||||||
|
delete clone.error;
|
||||||
}
|
}
|
||||||
// fallback when a test exits early or errors during pretest
|
catch(e) {
|
||||||
if (decompilable && !compiled && !deferred && !isEmpty) {
|
bench.count = count;
|
||||||
compiled = createFunction(preprocess('t$'), interpolate(
|
if (clone.error) {
|
||||||
preprocess(
|
compiled = null;
|
||||||
(clone.error && !stringable
|
} else {
|
||||||
? 'var r$,s$,m$=this,f$=m$.fn,i$=m$.count'
|
|
||||||
: 'function f$(){#{fn}\n}var r$,s$,m$=this,i$=m$.count'
|
|
||||||
) +
|
|
||||||
',n$=t$.ns;#{setup}\n#{begin};m$.f$=f$;while(i$--){m$.f$()}#{end};' +
|
|
||||||
'delete m$.f$;#{teardown}\nreturn{elapsed:r$}'
|
|
||||||
),
|
|
||||||
source
|
|
||||||
));
|
|
||||||
|
|
||||||
try {
|
|
||||||
// pretest one more time to check for errors
|
|
||||||
bench.count = 1;
|
|
||||||
compiled.call(bench, timer);
|
|
||||||
bench.compiled = compiled;
|
bench.compiled = compiled;
|
||||||
bench.count = count;
|
clone.error = e || new Error(String(e));
|
||||||
delete clone.error;
|
|
||||||
}
|
|
||||||
catch(e) {
|
|
||||||
bench.count = count;
|
|
||||||
if (clone.error) {
|
|
||||||
compiled = null;
|
|
||||||
} else {
|
|
||||||
bench.compiled = compiled;
|
|
||||||
clone.error = e || new Error(String(e));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3046,6 +3116,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The maximum time a benchmark is allowed to run before finishing (secs).
|
* The maximum time a benchmark is allowed to run before finishing (secs).
|
||||||
|
*
|
||||||
* Note: Cycle delays aren't counted toward the maximum time.
|
* Note: Cycle delays aren't counted toward the maximum time.
|
||||||
*
|
*
|
||||||
* @memberOf Benchmark.options
|
* @memberOf Benchmark.options
|
||||||
@@ -3123,7 +3194,15 @@
|
|||||||
* @memberOf Benchmark.options
|
* @memberOf Benchmark.options
|
||||||
* @type Function
|
* @type Function
|
||||||
*/
|
*/
|
||||||
'onStart': undefined
|
'onStart': undefined,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The reference time taken to execute the test once (usecs).
|
||||||
|
*
|
||||||
|
* @memberOf Benchmark.options
|
||||||
|
* @type Number
|
||||||
|
*/
|
||||||
|
'reference': 0
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -3219,7 +3298,7 @@
|
|||||||
* @memberOf Benchmark
|
* @memberOf Benchmark
|
||||||
* @type String
|
* @type String
|
||||||
*/
|
*/
|
||||||
'version': '1.0.0-pre',
|
'version': '1.0.0',
|
||||||
|
|
||||||
// an object of environment/feature detection flags
|
// an object of environment/feature detection flags
|
||||||
'support': support,
|
'support': support,
|
||||||
@@ -3680,6 +3759,14 @@
|
|||||||
*/
|
*/
|
||||||
'length': 0,
|
'length': 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A score computed using the normalized result of each benchmark in the suite.
|
||||||
|
*
|
||||||
|
* @memberOf Benchmark.Suite
|
||||||
|
* @type Number
|
||||||
|
*/
|
||||||
|
'score': 0,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A flag to indicate if the suite is aborted.
|
* A flag to indicate if the suite is aborted.
|
||||||
*
|
*
|
||||||
|
|||||||
2
vendor/docdown/LICENSE.txt
vendored
2
vendor/docdown/LICENSE.txt
vendored
@@ -1,4 +1,4 @@
|
|||||||
Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
|
Copyright 2011-2013 John-David Dalton <http://allyoucanleet.com/>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
|
|||||||
17
vendor/docdown/README.md
vendored
17
vendor/docdown/README.md
vendored
@@ -1,4 +1,4 @@
|
|||||||
# Docdown <sup>v1.0.0-pre</sup>
|
# Docdown <sup>v1.0.0</sup>
|
||||||
|
|
||||||
A simple JSDoc to Markdown documentation generator.
|
A simple JSDoc to Markdown documentation generator.
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ For a list of upcoming features, check out our [roadmap](https://github.com/jdal
|
|||||||
|
|
||||||
Usage example:
|
Usage example:
|
||||||
|
|
||||||
~~~ php
|
```php
|
||||||
require("docdown.php");
|
require("docdown.php");
|
||||||
|
|
||||||
// generate Markdown
|
// generate Markdown
|
||||||
@@ -20,18 +20,7 @@ $markdown = docdown(array(
|
|||||||
"path" => $filepath,
|
"path" => $filepath,
|
||||||
"url" => "https://github.com/username/project/blob/master/my.js"
|
"url" => "https://github.com/username/project/blob/master/my.js"
|
||||||
));
|
));
|
||||||
~~~
|
```
|
||||||
|
|
||||||
## Cloning this repo
|
|
||||||
|
|
||||||
To clone this repository just use:
|
|
||||||
|
|
||||||
~~~ bash
|
|
||||||
git clone https://github.com/docdown/docdown.git
|
|
||||||
cd docdown
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Feel free to fork and send pull requests if you see improvements!
|
|
||||||
|
|
||||||
## Author
|
## Author
|
||||||
|
|
||||||
|
|||||||
4
vendor/docdown/docdown.php
vendored
4
vendor/docdown/docdown.php
vendored
@@ -1,14 +1,14 @@
|
|||||||
<?php
|
<?php
|
||||||
/*!
|
/*!
|
||||||
* Docdown v1.0.0-pre
|
* Docdown v1.0.0-pre
|
||||||
* Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
|
* Copyright 2011-2013 John-David Dalton <http://allyoucanleet.com/>
|
||||||
* Available under MIT license <http://mths.be/mit>
|
* Available under MIT license <http://mths.be/mit>
|
||||||
*/
|
*/
|
||||||
require(dirname(__FILE__) . '/src/DocDown/Generator.php');
|
require(dirname(__FILE__) . '/src/DocDown/Generator.php');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates Markdown from JSDoc entries in a given file.
|
* Generates Markdown from JSDoc entries in a given file.
|
||||||
*
|
*
|
||||||
* @param {Array} [$options=array()] The options array.
|
* @param {Array} [$options=array()] The options array.
|
||||||
* @returns {String} The generated Markdown.
|
* @returns {String} The generated Markdown.
|
||||||
* @example
|
* @example
|
||||||
|
|||||||
226
vendor/docdown/src/DocDown/Alias.php
vendored
Normal file
226
vendor/docdown/src/DocDown/Alias.php
vendored
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class to represent a JSDoc entry alias.
|
||||||
|
*/
|
||||||
|
class Alias {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The alias owner.
|
||||||
|
*
|
||||||
|
* @memberOf Alias
|
||||||
|
* @type Object
|
||||||
|
*/
|
||||||
|
public $owner;
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Alias constructor.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
* @param {String} $name The alias name.
|
||||||
|
* @param {Object} $owner The alias owner.
|
||||||
|
*/
|
||||||
|
public function __construct( $name, $owner ) {
|
||||||
|
$this->owner = $owner;
|
||||||
|
$this->_name = $name;
|
||||||
|
$this->_call = $owner->getCall();
|
||||||
|
$this->_category = $owner->getCategory();
|
||||||
|
$this->_desc = $owner->getDesc();
|
||||||
|
$this->_example = $owner->getExample();
|
||||||
|
$this->_isCtor = $owner->isCtor();
|
||||||
|
$this->_isLicense = $owner->isLicense();
|
||||||
|
$this->_isPlugin = $owner->isPlugin();
|
||||||
|
$this->_isPrivate = $owner->isPrivate();
|
||||||
|
$this->_isStatic = $owner->isStatic();
|
||||||
|
$this->_lineNumber = $owner->getLineNumber();
|
||||||
|
$this->_members = $owner->getMembers();
|
||||||
|
$this->_params = $owner->getParams();
|
||||||
|
$this->_returns = $owner->getReturns();
|
||||||
|
$this->_type = $owner->getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the entry's `alias` objects.
|
||||||
|
*
|
||||||
|
* @memberOf Alias
|
||||||
|
* @param {Number} $index The index of the array value to return.
|
||||||
|
* @returns {Array|String} The entry's `alias` objects.
|
||||||
|
*/
|
||||||
|
public function getAliases( $index = null ) {
|
||||||
|
$result = array();
|
||||||
|
return $index !== null
|
||||||
|
? @$result[$index]
|
||||||
|
: $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the function call from the owner entry.
|
||||||
|
*
|
||||||
|
* @memberOf Alias
|
||||||
|
* @returns {String} The function call.
|
||||||
|
*/
|
||||||
|
public function getCall() {
|
||||||
|
return $this->_call;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the owner entry's `category` data.
|
||||||
|
*
|
||||||
|
* @memberOf Alias
|
||||||
|
* @returns {String} The owner entry's `category` data.
|
||||||
|
*/
|
||||||
|
public function getCategory() {
|
||||||
|
return $this->_category;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the owner entry's description.
|
||||||
|
*
|
||||||
|
* @memberOf Alias
|
||||||
|
* @returns {String} The owner entry's description.
|
||||||
|
*/
|
||||||
|
public function getDesc() {
|
||||||
|
return $this->_desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the owner entry's `example` data.
|
||||||
|
*
|
||||||
|
* @memberOf Alias
|
||||||
|
* @returns {String} The owner entry's `example` data.
|
||||||
|
*/
|
||||||
|
public function getExample() {
|
||||||
|
return $this->_example;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the entry is an alias.
|
||||||
|
*
|
||||||
|
* @memberOf Alias
|
||||||
|
* @returns {Boolean} Returns `true`.
|
||||||
|
*/
|
||||||
|
public function isAlias() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the owner entry is a constructor.
|
||||||
|
*
|
||||||
|
* @memberOf Alias
|
||||||
|
* @returns {Boolean} Returns `true` if a constructor, else `false`.
|
||||||
|
*/
|
||||||
|
public function isCtor() {
|
||||||
|
return $this->_isCtor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the owner entry is a license.
|
||||||
|
*
|
||||||
|
* @memberOf Alias
|
||||||
|
* @returns {Boolean} Returns `true` if a license, else `false`.
|
||||||
|
*/
|
||||||
|
public function isLicense() {
|
||||||
|
return $this->_isLicense;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the owner entry *is* assigned to a prototype.
|
||||||
|
*
|
||||||
|
* @memberOf Alias
|
||||||
|
* @returns {Boolean} Returns `true` if assigned to a prototype, else `false`.
|
||||||
|
*/
|
||||||
|
public function isPlugin() {
|
||||||
|
return $this->_isPlugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the owner entry is private.
|
||||||
|
*
|
||||||
|
* @memberOf Alias
|
||||||
|
* @returns {Boolean} Returns `true` if private, else `false`.
|
||||||
|
*/
|
||||||
|
public function isPrivate() {
|
||||||
|
return $this->_isPrivate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the owner entry is *not* assigned to a prototype.
|
||||||
|
*
|
||||||
|
* @memberOf Alias
|
||||||
|
* @returns {Boolean} Returns `true` if not assigned to a prototype, else `false`.
|
||||||
|
*/
|
||||||
|
public function isStatic() {
|
||||||
|
return $this->_isStatic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the owner entry's line number.
|
||||||
|
*
|
||||||
|
* @memberOf Alias
|
||||||
|
* @returns {Number} The owner entry's line number.
|
||||||
|
*/
|
||||||
|
public function getLineNumber() {
|
||||||
|
return $this->_lineNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the owner entry's `member` data.
|
||||||
|
*
|
||||||
|
* @memberOf Alias
|
||||||
|
* @param {Number} $index The index of the array value to return.
|
||||||
|
* @returns {Array|String} The owner entry's `member` data.
|
||||||
|
*/
|
||||||
|
public function getMembers( $index = null ) {
|
||||||
|
return $index !== null
|
||||||
|
? @$this->_members[$index]
|
||||||
|
: $this->_members;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the owner entry's `name` data.
|
||||||
|
*
|
||||||
|
* @memberOf Alias
|
||||||
|
* @returns {String} The owner entry's `name` data.
|
||||||
|
*/
|
||||||
|
public function getName() {
|
||||||
|
return $this->_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the owner entry's `param` data.
|
||||||
|
*
|
||||||
|
* @memberOf Alias
|
||||||
|
* @param {Number} $index The index of the array value to return.
|
||||||
|
* @returns {Array} The owner entry's `param` data.
|
||||||
|
*/
|
||||||
|
public function getParams( $index = null ) {
|
||||||
|
return $index !== null
|
||||||
|
? @$this->_params[$index]
|
||||||
|
: $this->_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the owner entry's `returns` data.
|
||||||
|
*
|
||||||
|
* @memberOf Alias
|
||||||
|
* @returns {String} The owner entry's `returns` data.
|
||||||
|
*/
|
||||||
|
public function getReturns() {
|
||||||
|
return $this->_returns;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the owner entry's `type` data.
|
||||||
|
*
|
||||||
|
* @memberOf Alias
|
||||||
|
* @returns {String} The owner entry's `type` data.
|
||||||
|
*/
|
||||||
|
public function getType() {
|
||||||
|
return $this->_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
380
vendor/docdown/src/DocDown/Entry.php
vendored
380
vendor/docdown/src/DocDown/Entry.php
vendored
@@ -1,5 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
require(dirname(__FILE__) . "/Alias.php");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to simplify parsing a single JSDoc entry.
|
* A class to simplify parsing a single JSDoc entry.
|
||||||
*/
|
*/
|
||||||
@@ -37,7 +39,7 @@ class Entry {
|
|||||||
* @constructor
|
* @constructor
|
||||||
* @param {String} $entry The documentation entry to analyse.
|
* @param {String} $entry The documentation entry to analyse.
|
||||||
* @param {String} $source The source code.
|
* @param {String} $source The source code.
|
||||||
* @param {String} $lang The language highlighter used for code examples.
|
* @param {String} [$lang ='js'] The language highlighter used for code examples.
|
||||||
*/
|
*/
|
||||||
public function __construct( $entry, $source, $lang = 'js' ) {
|
public function __construct( $entry, $source, $lang = 'js' ) {
|
||||||
$this->entry = $entry;
|
$this->entry = $entry;
|
||||||
@@ -70,16 +72,46 @@ class Entry {
|
|||||||
* @returns {Boolean} Returns `true` if the entry is a function reference, else `false`.
|
* @returns {Boolean} Returns `true` if the entry is a function reference, else `false`.
|
||||||
*/
|
*/
|
||||||
private function isFunction() {
|
private function isFunction() {
|
||||||
return !!(
|
if (!isset($this->_isFunction)) {
|
||||||
$this->isCtor() ||
|
$this->_isFunction = !!(
|
||||||
count($this->getParams()) ||
|
$this->isCtor() ||
|
||||||
count($this->getReturns()) ||
|
count($this->getParams()) ||
|
||||||
preg_match('/\*\s*@function\b/', $this->entry)
|
count($this->getReturns()) ||
|
||||||
);
|
preg_match('/\* *@function\b/', $this->entry)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $this->_isFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the entry's `alias` objects.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @param {Number} $index The index of the array value to return.
|
||||||
|
* @returns {Array|String} The entry's `alias` objects.
|
||||||
|
*/
|
||||||
|
public function getAliases( $index = null ) {
|
||||||
|
if (!isset($this->_aliases)) {
|
||||||
|
preg_match('#\* *@alias\s+([^\n]+)#', $this->entry, $result);
|
||||||
|
|
||||||
|
if (count($result)) {
|
||||||
|
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
|
||||||
|
$result = preg_split('/,\s*/', $result);
|
||||||
|
natsort($result);
|
||||||
|
|
||||||
|
foreach ($result as $resultIndex => $value) {
|
||||||
|
$result[$resultIndex] = new Alias($value, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->_aliases = $result;
|
||||||
|
}
|
||||||
|
return $index !== null
|
||||||
|
? @$this->_aliases[$index]
|
||||||
|
: $this->_aliases;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the function call from the entry.
|
* Extracts the function call from the entry.
|
||||||
*
|
*
|
||||||
@@ -87,13 +119,17 @@ class Entry {
|
|||||||
* @returns {String} The function call.
|
* @returns {String} The function call.
|
||||||
*/
|
*/
|
||||||
public function getCall() {
|
public function getCall() {
|
||||||
|
if (isset($this->_call)) {
|
||||||
|
return $this->_call;
|
||||||
|
}
|
||||||
|
|
||||||
preg_match('#\*/\s*(?:function ([^(]*)|(.*?)(?=[:=,]|return\b))#', $this->entry, $result);
|
preg_match('#\*/\s*(?:function ([^(]*)|(.*?)(?=[:=,]|return\b))#', $this->entry, $result);
|
||||||
if ($result = array_pop($result)) {
|
if ($result = array_pop($result)) {
|
||||||
$result = array_pop(explode('var ', trim(trim(array_pop(explode('.', $result))), "'")));
|
$result = array_pop(explode('var ', trim(trim(array_pop(explode('.', $result))), "'")));
|
||||||
}
|
}
|
||||||
// resolve name
|
// resolve name
|
||||||
// avoid $this->getName() because it calls $this->getCall()
|
// avoid $this->getName() because it calls $this->getCall()
|
||||||
preg_match('#\*\s*@name\s+([^\n]+)#', $this->entry, $name);
|
preg_match('#\* *@name\s+([^\n]+)#', $this->entry, $name);
|
||||||
if (count($name)) {
|
if (count($name)) {
|
||||||
$name = trim($name[1]);
|
$name = trim($name[1]);
|
||||||
} else {
|
} else {
|
||||||
@@ -111,178 +147,151 @@ class Entry {
|
|||||||
$result = $name .'('. implode(array_slice($result, 1), ', ') .')';
|
$result = $name .'('. implode(array_slice($result, 1), ', ') .')';
|
||||||
$result = str_replace(', [', ' [, ', str_replace('], [', ', ', $result));
|
$result = str_replace(', [', ' [, ', str_replace('], [', ', ', $result));
|
||||||
}
|
}
|
||||||
return $result ? $result : $name;
|
|
||||||
|
$this->_call = $result ? $result : $name;
|
||||||
|
return $this->_call;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the entry description.
|
* Extracts the entry's `category` data.
|
||||||
*
|
*
|
||||||
* @memberOf Entry
|
* @memberOf Entry
|
||||||
* @returns {String} The entry description.
|
* @returns {String} The entry's `category` data.
|
||||||
|
*/
|
||||||
|
public function getCategory() {
|
||||||
|
if (isset($this->_category)) {
|
||||||
|
return $this->_category;
|
||||||
|
}
|
||||||
|
|
||||||
|
preg_match('#\* *@category\s+([^\n]+)#', $this->entry, $result);
|
||||||
|
if (count($result)) {
|
||||||
|
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
|
||||||
|
} else {
|
||||||
|
$result = $this->getType() == 'Function' ? 'Methods' : 'Properties';
|
||||||
|
}
|
||||||
|
$this->_category = $result;
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the entry's description.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @returns {String} The entry's description.
|
||||||
*/
|
*/
|
||||||
public function getDesc() {
|
public function getDesc() {
|
||||||
|
if (isset($this->_desc)) {
|
||||||
|
return $this->_desc;
|
||||||
|
}
|
||||||
|
|
||||||
preg_match('#/\*\*(?:\s*\*)?([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result);
|
preg_match('#/\*\*(?:\s*\*)?([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result);
|
||||||
if (count($result)) {
|
if (count($result)) {
|
||||||
$type = $this->getType();
|
$type = $this->getType();
|
||||||
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
|
$result = preg_replace('/:\n *\* */', ":<br>\n", $result[1]);
|
||||||
|
$result = preg_replace('/(?:^|\n) *\*\n *\* */', "\n\n", $result);
|
||||||
|
$result = preg_replace('/(?:^|\n) *\* ?/', ' ', $result);
|
||||||
|
$result = trim($result);
|
||||||
$result = ($type == 'Function' ? '' : '(' . str_replace('|', ', ', trim($type, '{}')) . '): ') . $result;
|
$result = ($type == 'Function' ? '' : '(' . str_replace('|', ', ', trim($type, '{}')) . '): ') . $result;
|
||||||
}
|
}
|
||||||
|
$this->_desc = $result;
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the entry `example` data.
|
* Extracts the entry's `example` data.
|
||||||
*
|
*
|
||||||
* @memberOf Entry
|
* @memberOf Entry
|
||||||
* @returns {String} The entry `example` data.
|
* @returns {String} The entry's `example` data.
|
||||||
*/
|
*/
|
||||||
public function getExample() {
|
public function getExample() {
|
||||||
preg_match('#\*\s*@example\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result);
|
if (isset($this->_example)) {
|
||||||
|
return $this->_example;
|
||||||
|
}
|
||||||
|
|
||||||
|
preg_match('#\* *@example\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result);
|
||||||
if (count($result)) {
|
if (count($result)) {
|
||||||
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', "\n", $result[1]));
|
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', "\n", $result[1]));
|
||||||
$result = '~~~ ' . $this->lang . "\n" . $result . "\n~~~";
|
$result = '```' . $this->lang . "\n" . $result . "\n```";
|
||||||
}
|
}
|
||||||
|
$this->_example = $result;
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves the line number of the entry.
|
* Checks if the entry is an alias.
|
||||||
*
|
*
|
||||||
* @memberOf Entry
|
* @memberOf Entry
|
||||||
* @returns {Number} The line number.
|
* @returns {Boolean} Returns `false`.
|
||||||
*/
|
*/
|
||||||
public function getLineNumber() {
|
public function isAlias() {
|
||||||
preg_match_all('/\n/', substr($this->source, 0, strrpos($this->source, $this->entry) + strlen($this->entry)), $lines);
|
return false;
|
||||||
return count(array_pop($lines)) + 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the entry `member` data.
|
* Checks if the entry is a constructor.
|
||||||
*
|
*
|
||||||
* @memberOf Entry
|
* @memberOf Entry
|
||||||
* @param {Number} $index The index of the array value to return.
|
* @returns {Boolean} Returns `true` if a constructor, else `false`.
|
||||||
* @returns {Array|String} The entry `member` data.
|
|
||||||
*/
|
|
||||||
public function getMembers( $index = null ) {
|
|
||||||
preg_match('#\*\s*@member(?:Of)?\s+([^\n]+)#', $this->entry, $result);
|
|
||||||
if (count($result)) {
|
|
||||||
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
|
|
||||||
$result = preg_split('/,\s*/', $result);
|
|
||||||
}
|
|
||||||
return $index !== null ? @$result[$index] : $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts the entry `name` data.
|
|
||||||
*
|
|
||||||
* @memberOf Entry
|
|
||||||
* @returns {String} The entry `name` data.
|
|
||||||
*/
|
|
||||||
public function getName() {
|
|
||||||
preg_match('#\*\s*@name\s+([^\n]+)#', $this->entry, $result);
|
|
||||||
if (count($result)) {
|
|
||||||
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
|
|
||||||
} else {
|
|
||||||
$result = array_shift(explode('(', $this->getCall()));
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts the entry `param` data.
|
|
||||||
*
|
|
||||||
* @memberOf Entry
|
|
||||||
* @param {Number} $index The index of the array value to return.
|
|
||||||
* @returns {Array} The entry `param` data.
|
|
||||||
*/
|
|
||||||
public function getParams( $index = null ) {
|
|
||||||
preg_match_all('#\*\s*@param\s+\{([^}]+)\}\s+(\[[^]]+\]|[$\w]+)\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#i', $this->entry, $result);
|
|
||||||
if (count($result = array_filter(array_slice($result, 1)))) {
|
|
||||||
// repurpose array
|
|
||||||
foreach ($result as $param) {
|
|
||||||
foreach ($param as $key => $value) {
|
|
||||||
if (!is_array($result[0][$key])) {
|
|
||||||
$result[0][$key] = array();
|
|
||||||
}
|
|
||||||
$result[0][$key][] = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$result = $result[0];
|
|
||||||
}
|
|
||||||
return $index !== null ? @$result[$index] : $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts the entry `returns` data.
|
|
||||||
*
|
|
||||||
* @memberOf Entry
|
|
||||||
* @returns {String} The entry `returns` data.
|
|
||||||
*/
|
|
||||||
public function getReturns() {
|
|
||||||
preg_match('#\*\s*@returns\s+\{([^}]+)\}\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result);
|
|
||||||
if (count($result)) {
|
|
||||||
$result = array_map('trim', array_slice($result, 1));
|
|
||||||
$result[0] = str_replace('|', ', ', $result[0]);
|
|
||||||
$result[1] = preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]);
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts the entry `type` data.
|
|
||||||
*
|
|
||||||
* @memberOf Entry
|
|
||||||
* @returns {String} The entry `type` data.
|
|
||||||
*/
|
|
||||||
public function getType() {
|
|
||||||
preg_match('#\*\s*@type\s+([^\n]+)#', $this->entry, $result);
|
|
||||||
if (count($result)) {
|
|
||||||
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
|
|
||||||
} else {
|
|
||||||
$result = $this->isFunction() ? 'Function' : 'Unknown';
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if an entry is a constructor.
|
|
||||||
*
|
|
||||||
* @memberOf Entry
|
|
||||||
* @returns {Boolean} Returns true if a constructor, else false.
|
|
||||||
*/
|
*/
|
||||||
public function isCtor() {
|
public function isCtor() {
|
||||||
return !!preg_match('/\*\s*@constructor\b/', $this->entry);
|
if (!isset($this->_isCtor)) {
|
||||||
|
$this->_isCtor = !!preg_match('/\* *@constructor\b/', $this->entry);
|
||||||
|
}
|
||||||
|
return $this->_isCtor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if an entry *is* assigned to a prototype.
|
* Checks if the entry is a license.
|
||||||
*
|
*
|
||||||
* @memberOf Entry
|
* @memberOf Entry
|
||||||
* @returns {Boolean} Returns true if assigned to a prototype, else false.
|
* @returns {Boolean} Returns `true` if a license, else `false`.
|
||||||
|
*/
|
||||||
|
public function isLicense() {
|
||||||
|
if (!isset($this->_isLicense)) {
|
||||||
|
$this->_isLicense = !!preg_match('/\* *@license\b/', $this->entry);
|
||||||
|
}
|
||||||
|
return $this->_isLicense;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the entry *is* assigned to a prototype.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @returns {Boolean} Returns `true` if assigned to a prototype, else `false`.
|
||||||
*/
|
*/
|
||||||
public function isPlugin() {
|
public function isPlugin() {
|
||||||
return !$this->isCtor() && !$this->isPrivate() && !$this->isStatic();
|
if (!isset($this->_isPlugin)) {
|
||||||
|
$this->_isPlugin = !$this->isCtor() && !$this->isPrivate() && !$this->isStatic();
|
||||||
|
}
|
||||||
|
return $this->_isPlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if an entry is private.
|
* Checks if the entry is private.
|
||||||
*
|
*
|
||||||
* @memberOf Entry
|
* @memberOf Entry
|
||||||
* @returns {Boolean} Returns true if private, else false.
|
* @returns {Boolean} Returns `true` if private, else `false`.
|
||||||
*/
|
*/
|
||||||
public function isPrivate() {
|
public function isPrivate() {
|
||||||
return !!preg_match('/\*\s*@private\b/', $this->entry) || strrpos($this->entry, '@') === false;
|
if (!isset($this->_isPrivate)) {
|
||||||
|
$this->_isPrivate = $this->isLicense() || !!preg_match('/\* *@private\b/', $this->entry) || !preg_match('/\* *@[a-z]+\b/', $this->entry);
|
||||||
|
}
|
||||||
|
return $this->_isPrivate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if an entry is *not* assigned to a prototype.
|
* Checks if the entry is *not* assigned to a prototype.
|
||||||
*
|
*
|
||||||
* @memberOf Entry
|
* @memberOf Entry
|
||||||
* @returns {Boolean} Returns true if not assigned to a prototype, else false.
|
* @returns {Boolean} Returns `true` if not assigned to a prototype, else `false`.
|
||||||
*/
|
*/
|
||||||
public function isStatic() {
|
public function isStatic() {
|
||||||
|
if (isset($this->_isStatic)) {
|
||||||
|
return $this->_isStatic;
|
||||||
|
}
|
||||||
|
|
||||||
$public = !$this->isPrivate();
|
$public = !$this->isPrivate();
|
||||||
$result = $public && !!preg_match('/\*\s*@static\b/', $this->entry);
|
$result = $public && !!preg_match('/\* *@static\b/', $this->entry);
|
||||||
|
|
||||||
// set in cases where it isn't explicitly stated
|
// set in cases where it isn't explicitly stated
|
||||||
if ($public && !$result) {
|
if ($public && !$result) {
|
||||||
@@ -298,6 +307,135 @@ class Entry {
|
|||||||
$result = true;
|
$result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
$this->_isStatic = $result;
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the entry's line number.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @returns {Number} The entry's line number.
|
||||||
|
*/
|
||||||
|
public function getLineNumber() {
|
||||||
|
if (!isset($this->_lineNumber)) {
|
||||||
|
preg_match_all('/\n/', substr($this->source, 0, strrpos($this->source, $this->entry) + strlen($this->entry)), $lines);
|
||||||
|
$this->_lineNumber = count(array_pop($lines)) + 1;
|
||||||
|
}
|
||||||
|
return $this->_lineNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the entry's `member` data.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @param {Number} $index The index of the array value to return.
|
||||||
|
* @returns {Array|String} The entry's `member` data.
|
||||||
|
*/
|
||||||
|
public function getMembers( $index = null ) {
|
||||||
|
if (!isset($this->_members)) {
|
||||||
|
preg_match('#\* *@member(?:Of)?\s+([^\n]+)#', $this->entry, $result);
|
||||||
|
if (count($result)) {
|
||||||
|
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
|
||||||
|
$result = preg_split('/,\s*/', $result);
|
||||||
|
natsort($result);
|
||||||
|
}
|
||||||
|
$this->_members = $result;
|
||||||
|
}
|
||||||
|
return $index !== null
|
||||||
|
? @$this->_members[$index]
|
||||||
|
: $this->_members;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the entry's `name` data.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @returns {String} The entry's `name` data.
|
||||||
|
*/
|
||||||
|
public function getName() {
|
||||||
|
if (isset($this->_name)) {
|
||||||
|
return $this->_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
preg_match('#\* *@name\s+([^\n]+)#', $this->entry, $result);
|
||||||
|
if (count($result)) {
|
||||||
|
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
|
||||||
|
} else {
|
||||||
|
$result = array_shift(explode('(', $this->getCall()));
|
||||||
|
}
|
||||||
|
$this->_name = $result;
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the entry's `param` data.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @param {Number} $index The index of the array value to return.
|
||||||
|
* @returns {Array} The entry's `param` data.
|
||||||
|
*/
|
||||||
|
public function getParams( $index = null ) {
|
||||||
|
if (!isset($this->_params)) {
|
||||||
|
preg_match_all('#\* *@param\s+\{([^}]+)\}\s+(\[.+\]|[$\w|]+(?:\[.+\])?)\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#i', $this->entry, $result);
|
||||||
|
if (count($result = array_filter(array_slice($result, 1)))) {
|
||||||
|
// repurpose array
|
||||||
|
foreach ($result as $param) {
|
||||||
|
foreach ($param as $key => $value) {
|
||||||
|
if (!is_array($result[0][$key])) {
|
||||||
|
$result[0][$key] = array();
|
||||||
|
}
|
||||||
|
$result[0][$key][] = trim(preg_replace('/(?:^|\n)\s*\* */', ' ', $value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$result = $result[0];
|
||||||
|
}
|
||||||
|
$this->_params = $result;
|
||||||
|
}
|
||||||
|
return $index !== null
|
||||||
|
? @$this->_params[$index]
|
||||||
|
: $this->_params;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the entry's `returns` data.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @returns {String} The entry's `returns` data.
|
||||||
|
*/
|
||||||
|
public function getReturns() {
|
||||||
|
if (isset($this->_returns)) {
|
||||||
|
return $this->_returns;
|
||||||
|
}
|
||||||
|
|
||||||
|
preg_match('#\* *@returns\s+\{([^}]+)\}\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result);
|
||||||
|
if (count($result)) {
|
||||||
|
$result = array_map('trim', array_slice($result, 1));
|
||||||
|
$result[0] = str_replace('|', ', ', $result[0]);
|
||||||
|
$result[1] = preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]);
|
||||||
|
}
|
||||||
|
$this->_returns = $result;
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the entry's `type` data.
|
||||||
|
*
|
||||||
|
* @memberOf Entry
|
||||||
|
* @returns {String} The entry's `type` data.
|
||||||
|
*/
|
||||||
|
public function getType() {
|
||||||
|
if (isset($this->_type)) {
|
||||||
|
return $this->_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
preg_match('#\* *@type\s+([^\n]+)#', $this->entry, $result);
|
||||||
|
if (count($result)) {
|
||||||
|
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
|
||||||
|
} else {
|
||||||
|
$result = $this->isFunction() ? 'Function' : 'Unknown';
|
||||||
|
}
|
||||||
|
$this->_type = $result;
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
385
vendor/docdown/src/DocDown/Generator.php
vendored
385
vendor/docdown/src/DocDown/Generator.php
vendored
@@ -7,6 +7,15 @@ require(dirname(__FILE__) . "/Entry.php");
|
|||||||
*/
|
*/
|
||||||
class Generator {
|
class Generator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The HTML for the close tag.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @memberOf Generator
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
public $closeTag = "\n<!-- /div -->\n";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An array of JSDoc entries.
|
* An array of JSDoc entries.
|
||||||
*
|
*
|
||||||
@@ -15,6 +24,15 @@ class Generator {
|
|||||||
*/
|
*/
|
||||||
public $entries = array();
|
public $entries = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The HTML for the open tag.
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @memberOf Generator
|
||||||
|
* @type String
|
||||||
|
*/
|
||||||
|
public $openTag = "\n<!-- div -->\n";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An options array used to configure the generator.
|
* An options array used to configure the generator.
|
||||||
*
|
*
|
||||||
@@ -24,7 +42,7 @@ class Generator {
|
|||||||
public $options = array();
|
public $options = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The entire file's source code.
|
* The file's source code.
|
||||||
*
|
*
|
||||||
* @memberOf Generator
|
* @memberOf Generator
|
||||||
* @type String
|
* @type String
|
||||||
@@ -65,6 +83,9 @@ class Generator {
|
|||||||
if (!isset($options['lang'])) {
|
if (!isset($options['lang'])) {
|
||||||
$options['lang'] = 'js';
|
$options['lang'] = 'js';
|
||||||
}
|
}
|
||||||
|
if (!isset($options['toc'])) {
|
||||||
|
$options['toc'] = 'properties';
|
||||||
|
}
|
||||||
|
|
||||||
$this->options = $options;
|
$this->options = $options;
|
||||||
$this->source = str_replace(PHP_EOL, "\n", $options['source']);
|
$this->source = str_replace(PHP_EOL, "\n", $options['source']);
|
||||||
@@ -86,7 +107,7 @@ class Generator {
|
|||||||
* @param {String} $string The string to format.
|
* @param {String} $string The string to format.
|
||||||
* @returns {String} The formatted string.
|
* @returns {String} The formatted string.
|
||||||
*/
|
*/
|
||||||
private static function format($string) {
|
private static function format( $string ) {
|
||||||
$counter = 0;
|
$counter = 0;
|
||||||
|
|
||||||
// tokenize inline code snippets
|
// tokenize inline code snippets
|
||||||
@@ -121,7 +142,7 @@ class Generator {
|
|||||||
* @param {Array|Object} $object The template object.
|
* @param {Array|Object} $object The template object.
|
||||||
* @returns {String} The modified string.
|
* @returns {String} The modified string.
|
||||||
*/
|
*/
|
||||||
private static function interpolate($string, $object) {
|
private static function interpolate( $string, $object ) {
|
||||||
preg_match_all('/#\{([^}]+)\}/', $string, $tokens);
|
preg_match_all('/#\{([^}]+)\}/', $string, $tokens);
|
||||||
$tokens = array_unique(array_pop($tokens));
|
$tokens = array_unique(array_pop($tokens));
|
||||||
|
|
||||||
@@ -149,6 +170,63 @@ class Generator {
|
|||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the given `$entries` to the `$result` array.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @memberOf Generator
|
||||||
|
* @param {Array} $result The result array to modify.
|
||||||
|
* @param {Array} $entries The entries to add to the `$result`.
|
||||||
|
*/
|
||||||
|
private function addEntries( &$result, $entries ) {
|
||||||
|
foreach ($entries as $entry) {
|
||||||
|
// skip aliases
|
||||||
|
if ($entry->isAlias()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// name and description
|
||||||
|
array_push(
|
||||||
|
$result,
|
||||||
|
$this->openTag,
|
||||||
|
Generator::interpolate("### <a id=\"#{hash}\"></a>`#{member}#{separator}#{call}`\n<a href=\"##{hash}\">#</a> [Ⓢ](#{href} \"View in source\") [Ⓣ][1]\n\n#{desc}", $entry)
|
||||||
|
);
|
||||||
|
|
||||||
|
// @alias
|
||||||
|
if (count($aliases = $entry->getAliases())) {
|
||||||
|
array_push($result, '', '#### Aliases');
|
||||||
|
foreach ($aliases as $index => $alias) {
|
||||||
|
$aliases[$index] = $alias->getName();
|
||||||
|
}
|
||||||
|
$result[] = '*' . implode(', ', $aliases) . '*';
|
||||||
|
}
|
||||||
|
// @param
|
||||||
|
if (count($params = $entry->getParams())) {
|
||||||
|
array_push($result, '', '#### Arguments');
|
||||||
|
foreach ($params as $index => $param) {
|
||||||
|
$result[] = Generator::interpolate('#{num}. `#{name}` (#{type}): #{desc}', array(
|
||||||
|
'desc' => $param[2],
|
||||||
|
'name' => $param[1],
|
||||||
|
'num' => $index + 1,
|
||||||
|
'type' => $param[0]
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// @returns
|
||||||
|
if (count($returns = $entry->getReturns())) {
|
||||||
|
array_push(
|
||||||
|
$result, '',
|
||||||
|
'#### Returns',
|
||||||
|
Generator::interpolate('(#{type}): #{desc}', array('desc' => $returns[1], 'type' => $returns[0]))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// @example
|
||||||
|
if ($example = $entry->getExample()) {
|
||||||
|
array_push($result, '', '#### Example', $example);
|
||||||
|
}
|
||||||
|
array_push($result, "\n* * *", $this->closeTag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves the entry's hash used to navigate the documentation.
|
* Resolves the entry's hash used to navigate the documentation.
|
||||||
*
|
*
|
||||||
@@ -163,7 +241,7 @@ class Generator {
|
|||||||
$member = !$member ? $entry->getMembers(0) : $member;
|
$member = !$member ? $entry->getMembers(0) : $member;
|
||||||
$result = ($member ? $member . ($entry->isPlugin() ? 'prototype' : '') : '') . $entry->getCall();
|
$result = ($member ? $member . ($entry->isPlugin() ? 'prototype' : '') : '') . $entry->getCall();
|
||||||
$result = preg_replace('/\(\[|\[\]/', '', $result);
|
$result = preg_replace('/\(\[|\[\]/', '', $result);
|
||||||
$result = preg_replace('/[ =\'"{}.()\]]/', '', $result);
|
$result = preg_replace('/[ =|\'"{}.()\]]/', '', $result);
|
||||||
$result = preg_replace('/[[#,]/', '-', $result);
|
$result = preg_replace('/[[#,]/', '-', $result);
|
||||||
return strtolower($result);
|
return strtolower($result);
|
||||||
}
|
}
|
||||||
@@ -204,43 +282,85 @@ class Generator {
|
|||||||
*/
|
*/
|
||||||
public function generate() {
|
public function generate() {
|
||||||
$api = array();
|
$api = array();
|
||||||
|
$byCategory = $this->options['toc'] == 'categories';
|
||||||
|
$categories = array();
|
||||||
|
$closeTag = $this->closeTag;
|
||||||
$compiling = false;
|
$compiling = false;
|
||||||
$openTag = "\n<!-- div -->\n";
|
$openTag = $this->openTag;
|
||||||
$closeTag = "\n<!-- /div -->\n";
|
|
||||||
$result = array('# ' . $this->options['title']);
|
$result = array('# ' . $this->options['title']);
|
||||||
|
$toc = 'toc';
|
||||||
|
|
||||||
// initialize $api array
|
// initialize $api array
|
||||||
foreach ($this->entries as $entry) {
|
foreach ($this->entries as $entry) {
|
||||||
|
// skip invalid or private entries
|
||||||
|
$name = $entry->getName();
|
||||||
|
if (!$name || $entry->isPrivate()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!$entry->isPrivate()) {
|
$members = $entry->getMembers();
|
||||||
$name = $entry->getName();
|
$members = count($members) ? $members : array('');
|
||||||
$members = $entry->getMembers();
|
|
||||||
$members = count($members) ? $members : array('');
|
|
||||||
|
|
||||||
foreach ($members as $member) {
|
foreach ($members as $member) {
|
||||||
// create api category arrays
|
// create api category arrays
|
||||||
if (!isset($api[$member]) && $member) {
|
if ($member && !isset($api[$member])) {
|
||||||
$api[$member] = new Entry('', '', $entry->lang);
|
// create temporary entry to be replaced later
|
||||||
$api[$member]->static = array();
|
$api[$member] = new stdClass;
|
||||||
$api[$member]->plugin = array();
|
$api[$member]->static = array();
|
||||||
|
$api[$member]->plugin = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
// append entry to api member
|
||||||
|
if (!$member || $entry->isCtor() || ($entry->getType() == 'Object' &&
|
||||||
|
!preg_match('/[=:]\s*(?:null|undefined)\s*[,;]?$/', $entry->entry))) {
|
||||||
|
|
||||||
|
// assign the real entry, replacing the temporary entry if it exist
|
||||||
|
$member = ($member ? $member . ($entry->isPlugin() ? '#' : '.') : '') . $name;
|
||||||
|
$entry->static = @$api[$member] ? $api[$member]->static : array();
|
||||||
|
$entry->plugin = @$api[$member] ? $api[$member]->plugin : array();
|
||||||
|
|
||||||
|
$api[$member] = $entry;
|
||||||
|
foreach ($entry->getAliases() as $alias) {
|
||||||
|
$api[$member] = $alias;
|
||||||
|
$alias->static = array();
|
||||||
|
$alias->plugin = array();
|
||||||
}
|
}
|
||||||
// append entry to api category
|
}
|
||||||
if (!$member || $entry->isCtor() || ($entry->getType() == 'Object' &&
|
else if ($entry->isStatic()) {
|
||||||
!preg_match('/[=:]\s*null\s*[,;]?$/', $entry->entry))) {
|
$api[$member]->static[] = $entry;
|
||||||
$member = ($member ? $member . ($entry->isPlugin() ? '#' : '.') : '') . $name;
|
foreach ($entry->getAliases() as $alias) {
|
||||||
$entry->static = @$api[$member] ? $api[$member]->static : array();
|
$api[$member]->static[] = $alias;
|
||||||
$entry->plugin = @$api[$member] ? $api[$member]->plugin : array();
|
|
||||||
$api[$member] = $entry;
|
|
||||||
}
|
}
|
||||||
else if ($entry->isStatic()) {
|
}
|
||||||
$api[$member]->static[] = $entry;
|
else if (!$entry->isCtor()) {
|
||||||
} else if (!$entry->isCtor()) {
|
$api[$member]->plugin[] = $entry;
|
||||||
$api[$member]->plugin[] = $entry;
|
foreach ($entry->getAliases() as $alias) {
|
||||||
|
$api[$member]->plugin[] = $alias;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add properties to each entry
|
||||||
|
foreach ($api as $entry) {
|
||||||
|
$entry->hash = $this->getHash($entry);
|
||||||
|
$entry->href = $this->getLineUrl($entry);
|
||||||
|
|
||||||
|
$member = $entry->getMembers(0);
|
||||||
|
$member = ($member ? $member . ($entry->isPlugin() ? '.prototype.' : '.') : '') . $entry->getName();
|
||||||
|
$entry->member = preg_replace('/' . $entry->getName() . '$/', '', $member);
|
||||||
|
|
||||||
|
// add properties to static and plugin sub-entries
|
||||||
|
foreach (array('static', 'plugin') as $kind) {
|
||||||
|
foreach ($entry->{$kind} as $subentry) {
|
||||||
|
$subentry->hash = $this->getHash($subentry);
|
||||||
|
$subentry->href = $this->getLineUrl($subentry);
|
||||||
|
$subentry->member = $member;
|
||||||
|
$subentry->separator = $this->getSeparator($subentry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
// custom sort for root level entries
|
// custom sort for root level entries
|
||||||
@@ -248,19 +368,19 @@ class Generator {
|
|||||||
function sortCompare($a, $b) {
|
function sortCompare($a, $b) {
|
||||||
$score = array( 'a' => 0, 'b' => 0);
|
$score = array( 'a' => 0, 'b' => 0);
|
||||||
foreach (array( 'a' => $a, 'b' => $b) as $key => $value) {
|
foreach (array( 'a' => $a, 'b' => $b) as $key => $value) {
|
||||||
// capitalized keys that represent constructor properties are last
|
// capitalized properties are last
|
||||||
if (preg_match('/[#.][A-Z]/', $value)) {
|
if (preg_match('/[#.][A-Z]/', $value)) {
|
||||||
$score[$key] = 0;
|
$score[$key] = 0;
|
||||||
}
|
}
|
||||||
// lowercase keys with prototype properties are next to last
|
// lowercase prototype properties are next to last
|
||||||
else if (preg_match('/#[a-z]/', $value)) {
|
else if (preg_match('/#[a-z]/', $value)) {
|
||||||
$score[$key] = 1;
|
$score[$key] = 1;
|
||||||
}
|
}
|
||||||
// lowercase keys with static properties next to first
|
// lowercase static properties next to first
|
||||||
else if (preg_match('/\.[a-z]/', $value)) {
|
else if (preg_match('/\.[a-z]/', $value)) {
|
||||||
$score[$key] = 2;
|
$score[$key] = 2;
|
||||||
}
|
}
|
||||||
// lowercase keys with no properties are first
|
// root properties are first
|
||||||
else if (preg_match('/^[^#.]+$/', $value)) {
|
else if (preg_match('/^[^#.]+$/', $value)) {
|
||||||
$score[$key] = 3;
|
$score[$key] = 3;
|
||||||
}
|
}
|
||||||
@@ -290,43 +410,90 @@ class Generator {
|
|||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// add categories
|
||||||
|
foreach ($api as $entry) {
|
||||||
|
$categories[$entry->getCategory()][] = $entry;
|
||||||
|
foreach (array('static', 'plugin') as $kind) {
|
||||||
|
foreach ($entry->{$kind} as $subentry) {
|
||||||
|
$categories[$subentry->getCategory()][] = $subentry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort categories
|
||||||
|
ksort($categories);
|
||||||
|
|
||||||
|
foreach(array('Methods', 'Properties') as $category) {
|
||||||
|
if (isset($categories[$category])) {
|
||||||
|
$entries = $categories[$category];
|
||||||
|
unset($categories[$category]);
|
||||||
|
$categories[$category] = $entries;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
// compile TOC
|
// compile TOC
|
||||||
$result[] = $openTag;
|
$result[] = $openTag;
|
||||||
|
|
||||||
foreach ($api as $key => $entry) {
|
// compile TOC by categories
|
||||||
$entry->hash = $this->getHash($entry);
|
if ($byCategory) {
|
||||||
$entry->href = $this->getLineUrl($entry);
|
foreach ($categories as $category => $entries) {
|
||||||
|
if ($compiling) {
|
||||||
$member = $entry->getMembers(0);
|
$result[] = $closeTag;
|
||||||
$member = ($member ? $member . ($entry->isPlugin() ? '.prototype.' : '.') : '') . $entry->getName();
|
} else {
|
||||||
|
$compiling = true;
|
||||||
$entry->member = preg_replace('/' . $entry->getName() . '$/', '', $member);
|
|
||||||
|
|
||||||
$compiling = $compiling ? ($result[] = $closeTag) : true;
|
|
||||||
|
|
||||||
// add root entry
|
|
||||||
array_push(
|
|
||||||
$result,
|
|
||||||
$openTag, '## ' . (count($result) == 2 ? '<a id="toc"></a>' : '') . '`' . $member . '`',
|
|
||||||
Generator::interpolate('* [`' . $member . '`](##{hash})', $entry)
|
|
||||||
);
|
|
||||||
|
|
||||||
// add static and plugin sub-entries
|
|
||||||
foreach (array('static', 'plugin') as $kind) {
|
|
||||||
if ($kind == 'plugin' && count($entry->plugin)) {
|
|
||||||
array_push(
|
|
||||||
$result,
|
|
||||||
$closeTag,
|
|
||||||
$openTag,
|
|
||||||
'## `' . $member . ($entry->isCtor() ? '.prototype`' : '`')
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
foreach ($entry->{$kind} as $subentry) {
|
// assign TOC hash
|
||||||
$subentry->hash = $this->getHash($subentry);
|
if (count($result) == 2) {
|
||||||
$subentry->href = $this->getLineUrl($subentry);
|
$toc = $category;
|
||||||
$subentry->member = $member;
|
}
|
||||||
$subentry->separator = $this->getSeparator($subentry);
|
// add category
|
||||||
$result[] = Generator::interpolate('* [`#{member}#{separator}#{name}`](##{hash})', $subentry);
|
array_push(
|
||||||
|
$result,
|
||||||
|
$openTag, '## ' . (count($result) == 2 ? '<a id="' . $toc . '"></a>' : '') . '`' . $category . '`'
|
||||||
|
);
|
||||||
|
// add entries
|
||||||
|
foreach ($entries as $entry) {
|
||||||
|
$result[] = Generator::interpolate('* [`#{member}#{separator}#{name}`](##{hash})', $entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// compile TOC by namespace
|
||||||
|
else {
|
||||||
|
foreach ($api as $entry) {
|
||||||
|
if ($compiling) {
|
||||||
|
$result[] = $closeTag;
|
||||||
|
} else {
|
||||||
|
$compiling = true;
|
||||||
|
}
|
||||||
|
$member = $entry->member . $entry->getName();
|
||||||
|
|
||||||
|
// assign TOC hash
|
||||||
|
if (count($result) == 2) {
|
||||||
|
$toc = $member;
|
||||||
|
}
|
||||||
|
// add root entry
|
||||||
|
array_push(
|
||||||
|
$result,
|
||||||
|
$openTag, '## ' . (count($result) == 2 ? '<a id="' . $toc . '"></a>' : '') . '`' . $member . '`',
|
||||||
|
Generator::interpolate('* [`' . $member . '`](##{hash})', $entry)
|
||||||
|
);
|
||||||
|
|
||||||
|
// add static and plugin sub-entries
|
||||||
|
foreach (array('static', 'plugin') as $kind) {
|
||||||
|
if ($kind == 'plugin' && count($entry->plugin)) {
|
||||||
|
array_push(
|
||||||
|
$result,
|
||||||
|
$closeTag,
|
||||||
|
$openTag,
|
||||||
|
'## `' . $member . ($entry->isCtor() ? '.prototype`' : '`')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
foreach ($entry->{$kind} as $subentry) {
|
||||||
|
$subentry->member = $member;
|
||||||
|
$result[] = Generator::interpolate('* [`#{member}#{separator}#{name}`](##{hash})', $subentry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -339,69 +506,57 @@ class Generator {
|
|||||||
$compiling = false;
|
$compiling = false;
|
||||||
$result[] = $openTag;
|
$result[] = $openTag;
|
||||||
|
|
||||||
foreach ($api as $entry) {
|
if ($byCategory) {
|
||||||
// add root entry
|
foreach ($categories as $category => $entries) {
|
||||||
$member = $entry->member . $entry->getName();
|
if ($compiling) {
|
||||||
$compiling = $compiling ? ($result[] = $closeTag) : true;
|
$result[] = $closeTag;
|
||||||
|
} else {
|
||||||
array_push($result, $openTag, '## `' . $member . '`');
|
$compiling = true;
|
||||||
|
|
||||||
foreach (array($entry, 'static', 'plugin') as $kind) {
|
|
||||||
$subentries = is_string($kind) ? $entry->{$kind} : array($kind);
|
|
||||||
|
|
||||||
// title
|
|
||||||
if ($kind != 'static' && $entry->getType() != 'Object' &&
|
|
||||||
count($subentries) && $subentries[0] != $kind) {
|
|
||||||
if ($kind == 'plugin') {
|
|
||||||
$result[] = $closeTag;
|
|
||||||
}
|
|
||||||
array_push(
|
|
||||||
$result,
|
|
||||||
$openTag,
|
|
||||||
'## `' . $member . ($kind == 'plugin' ? '.prototype`' : '`')
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
if ($category != 'Methods' && $category != 'Properties') {
|
||||||
|
$category = '“' . $category . '” Methods';
|
||||||
|
}
|
||||||
|
array_push($result, $openTag, '## `' . $category . '`');
|
||||||
|
$this->addEntries($result, $entries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
foreach ($api as $entry) {
|
||||||
|
// skip aliases
|
||||||
|
if ($entry->isAlias()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($compiling) {
|
||||||
|
$result[] = $closeTag;
|
||||||
|
} else {
|
||||||
|
$compiling = true;
|
||||||
|
}
|
||||||
|
// add root entry name
|
||||||
|
$member = $entry->member . $entry->getName();
|
||||||
|
array_push($result, $openTag, '## `' . $member . '`');
|
||||||
|
|
||||||
// body
|
foreach (array($entry, 'static', 'plugin') as $kind) {
|
||||||
foreach ($subentries as $subentry) {
|
$subentries = is_string($kind) ? $entry->{$kind} : array($kind);
|
||||||
// description
|
|
||||||
array_push(
|
|
||||||
$result,
|
|
||||||
$openTag,
|
|
||||||
Generator::interpolate("### <a id=\"#{hash}\"></a>`#{member}#{separator}#{call}`\n<a href=\"##{hash}\">#</a> [Ⓢ](#{href} \"View in source\") [Ⓣ][1]\n\n#{desc}", $subentry)
|
|
||||||
);
|
|
||||||
|
|
||||||
// @param
|
// add sub-entry name
|
||||||
if (count($params = $subentry->getParams())) {
|
if ($kind != 'static' && $entry->getType() != 'Object' &&
|
||||||
array_push($result, '', '#### Arguments');
|
count($subentries) && $subentries[0] != $kind) {
|
||||||
foreach ($params as $index => $param) {
|
if ($kind == 'plugin') {
|
||||||
$result[] = Generator::interpolate('#{num}. `#{name}` (#{type}): #{desc}', array(
|
$result[] = $closeTag;
|
||||||
'desc' => $param[2],
|
|
||||||
'name' => $param[1],
|
|
||||||
'num' => $index + 1,
|
|
||||||
'type' => $param[0]
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// @returns
|
|
||||||
if (count($returns = $subentry->getReturns())) {
|
|
||||||
array_push(
|
array_push(
|
||||||
$result, '',
|
$result,
|
||||||
'#### Returns',
|
$openTag,
|
||||||
Generator::interpolate('(#{type}): #{desc}', array('desc' => $returns[1], 'type' => $returns[0]))
|
'## `' . $member . ($kind == 'plugin' ? '.prototype`' : '`')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// @example
|
$this->addEntries($result, $subentries);
|
||||||
if ($example = $subentry->getExample()) {
|
|
||||||
array_push($result, '', '#### Example', $example);
|
|
||||||
}
|
|
||||||
array_push($result, "\n* * *", $closeTag);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// close tags add TOC link reference
|
// close tags add TOC link reference
|
||||||
array_push($result, $closeTag, $closeTag, '', ' [1]: #toc "Jump back to the TOC."');
|
array_push($result, $closeTag, $closeTag, '', ' [1]: #' . $toc . ' "Jump back to the TOC."');
|
||||||
|
|
||||||
// cleanup whitespace
|
// cleanup whitespace
|
||||||
return trim(preg_replace('/ +\n/', "\n", join($result, "\n")));
|
return trim(preg_replace('/ +\n/', "\n", join($result, "\n")));
|
||||||
|
|||||||
1049
vendor/firebug-lite/changelog.txt
vendored
1049
vendor/firebug-lite/changelog.txt
vendored
File diff suppressed because it is too large
Load Diff
662
vendor/firebug-lite/skin/xp/debugger.css
vendored
662
vendor/firebug-lite/skin/xp/debugger.css
vendored
@@ -1,331 +1,331 @@
|
|||||||
/* See license.txt for terms of usage */
|
/* See license.txt for terms of usage */
|
||||||
|
|
||||||
.panelNode-script {
|
.panelNode-script {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
|
|
||||||
.scriptTooltip {
|
.scriptTooltip {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 2147483647;
|
z-index: 2147483647;
|
||||||
padding: 2px 3px;
|
padding: 2px 3px;
|
||||||
border: 1px solid #CBE087;
|
border: 1px solid #CBE087;
|
||||||
background: LightYellow;
|
background: LightYellow;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
color: #000000;
|
color: #000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
|
|
||||||
.sourceBox {
|
.sourceBox {
|
||||||
/* TODO: xxxpedro problem with sourceBox and scrolling elements */
|
/* TODO: xxxpedro problem with sourceBox and scrolling elements */
|
||||||
/*overflow: scroll; /* see issue 1479 */
|
/*overflow: scroll; /* see issue 1479 */
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sourceRow {
|
.sourceRow {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
-moz-user-select: text;
|
-moz-user-select: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sourceRow.hovered {
|
.sourceRow.hovered {
|
||||||
background-color: #EEEEEE;
|
background-color: #EEEEEE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
|
|
||||||
.sourceLine {
|
.sourceLine {
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
border-right: 1px solid #CCCCCC;
|
border-right: 1px solid #CCCCCC;
|
||||||
padding: 0px 4px 0 20px;
|
padding: 0px 4px 0 20px;
|
||||||
background: #EEEEEE no-repeat 2px 0px;
|
background: #EEEEEE no-repeat 2px 0px;
|
||||||
color: #888888;
|
color: #888888;
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
font-family: monospace; /* see issue 2953 */
|
font-family: monospace; /* see issue 2953 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.noteInToolTip { /* below sourceLine, so it overrides it */
|
.noteInToolTip { /* below sourceLine, so it overrides it */
|
||||||
background-color: #FFD472;
|
background-color: #FFD472;
|
||||||
}
|
}
|
||||||
|
|
||||||
.useA11y .sourceBox .sourceViewport:focus .sourceLine {
|
.useA11y .sourceBox .sourceViewport:focus .sourceLine {
|
||||||
background-color: #FFFFC0;
|
background-color: #FFFFC0;
|
||||||
color: navy;
|
color: navy;
|
||||||
border-right: 1px solid black;
|
border-right: 1px solid black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.useA11y .sourceBox .sourceViewport:focus {
|
.useA11y .sourceBox .sourceViewport:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.a11y1emSize {
|
.a11y1emSize {
|
||||||
width: 1em;
|
width: 1em;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
.useA11y .panelStatusLabel:focus {
|
.useA11y .panelStatusLabel:focus {
|
||||||
outline-offset: -2px !important;
|
outline-offset: -2px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sourceBox > .sourceRow > .sourceLine {
|
.sourceBox > .sourceRow > .sourceLine {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sourceLine:hover {
|
.sourceLine:hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sourceRowText {
|
.sourceRowText {
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sourceRow[exe_line="true"] {
|
.sourceRow[exe_line="true"] {
|
||||||
outline: 1px solid #D9D9B6;
|
outline: 1px solid #D9D9B6;
|
||||||
margin-right: 1px;
|
margin-right: 1px;
|
||||||
background-color: lightgoldenrodyellow;
|
background-color: lightgoldenrodyellow;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sourceRow[executable="true"] > .sourceLine {
|
.sourceRow[executable="true"] > .sourceLine {
|
||||||
content: "-";
|
content: "-";
|
||||||
color: #4AA02C; /* Spring Green */
|
color: #4AA02C; /* Spring Green */
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sourceRow[exe_line="true"] > .sourceLine {
|
.sourceRow[exe_line="true"] > .sourceLine {
|
||||||
background-image: url(chrome://firebug/skin/exe.png);
|
background-image: url(chrome://firebug/skin/exe.png);
|
||||||
color: #000000;
|
color: #000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sourceRow[breakpoint="true"] > .sourceLine {
|
.sourceRow[breakpoint="true"] > .sourceLine {
|
||||||
background-image: url(chrome://firebug/skin/breakpoint.png);
|
background-image: url(chrome://firebug/skin/breakpoint.png);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sourceRow[breakpoint="true"][condition="true"] > .sourceLine {
|
.sourceRow[breakpoint="true"][condition="true"] > .sourceLine {
|
||||||
background-image: url(chrome://firebug/skin/breakpointCondition.png);
|
background-image: url(chrome://firebug/skin/breakpointCondition.png);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sourceRow[breakpoint="true"][disabledBreakpoint="true"] > .sourceLine {
|
.sourceRow[breakpoint="true"][disabledBreakpoint="true"] > .sourceLine {
|
||||||
background-image: url(chrome://firebug/skin/breakpointDisabled.png);
|
background-image: url(chrome://firebug/skin/breakpointDisabled.png);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sourceRow[breakpoint="true"][exe_line="true"] > .sourceLine {
|
.sourceRow[breakpoint="true"][exe_line="true"] > .sourceLine {
|
||||||
background-image: url(chrome://firebug/skin/breakpointExe.png);
|
background-image: url(chrome://firebug/skin/breakpointExe.png);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sourceRow[breakpoint="true"][exe_line="true"][disabledBreakpoint="true"] > .sourceLine {
|
.sourceRow[breakpoint="true"][exe_line="true"][disabledBreakpoint="true"] > .sourceLine {
|
||||||
background-image: url(chrome://firebug/skin/breakpointDisabledExe.png);
|
background-image: url(chrome://firebug/skin/breakpointDisabledExe.png);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sourceLine.editing {
|
.sourceLine.editing {
|
||||||
background-image: url(chrome://firebug/skin/breakpoint.png);
|
background-image: url(chrome://firebug/skin/breakpoint.png);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
|
|
||||||
.conditionEditor {
|
.conditionEditor {
|
||||||
z-index: 2147483647;
|
z-index: 2147483647;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
left: 2px;
|
left: 2px;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.conditionEditorInner {
|
.conditionEditorInner {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -26px;
|
top: -26px;
|
||||||
height: 0;
|
height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.conditionCaption {
|
.conditionCaption {
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
font-family: Lucida Grande, sans-serif;
|
font-family: Lucida Grande, sans-serif;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
color: #226679;
|
color: #226679;
|
||||||
}
|
}
|
||||||
|
|
||||||
.conditionInput {
|
.conditionInput {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 1px solid #0096C0;
|
border: 1px solid #0096C0;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.conditionEditorInner1 {
|
.conditionEditorInner1 {
|
||||||
padding-left: 37px;
|
padding-left: 37px;
|
||||||
background: url(condBorders.png) repeat-y;
|
background: url(condBorders.png) repeat-y;
|
||||||
}
|
}
|
||||||
|
|
||||||
.conditionEditorInner2 {
|
.conditionEditorInner2 {
|
||||||
padding-right: 25px;
|
padding-right: 25px;
|
||||||
background: url(condBorders.png) repeat-y 100% 0;
|
background: url(condBorders.png) repeat-y 100% 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.conditionEditorTop1 {
|
.conditionEditorTop1 {
|
||||||
background: url(condCorners.png) no-repeat 100% 0;
|
background: url(condCorners.png) no-repeat 100% 0;
|
||||||
margin-left: 37px;
|
margin-left: 37px;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.conditionEditorTop2 {
|
.conditionEditorTop2 {
|
||||||
position: relative;
|
position: relative;
|
||||||
left: -37px;
|
left: -37px;
|
||||||
width: 37px;
|
width: 37px;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
background: url(condCorners.png) no-repeat;
|
background: url(condCorners.png) no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
.conditionEditorBottom1 {
|
.conditionEditorBottom1 {
|
||||||
background: url(condCorners.png) no-repeat 100% 100%;
|
background: url(condCorners.png) no-repeat 100% 100%;
|
||||||
margin-left: 37px;
|
margin-left: 37px;
|
||||||
height: 33px;
|
height: 33px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.conditionEditorBottom2 {
|
.conditionEditorBottom2 {
|
||||||
position: relative; left: -37px;
|
position: relative; left: -37px;
|
||||||
width: 37px;
|
width: 37px;
|
||||||
height: 33px;
|
height: 33px;
|
||||||
background: url(condCorners.png) no-repeat 0 100%;
|
background: url(condCorners.png) no-repeat 0 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
.upsideDown {
|
.upsideDown {
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upsideDown .conditionEditorInner {
|
.upsideDown .conditionEditorInner {
|
||||||
top: -8px;
|
top: -8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upsideDown .conditionEditorInner1 {
|
.upsideDown .conditionEditorInner1 {
|
||||||
padding-left: 33px;
|
padding-left: 33px;
|
||||||
background: url(condBordersUps.png) repeat-y;
|
background: url(condBordersUps.png) repeat-y;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upsideDown .conditionEditorInner2 {
|
.upsideDown .conditionEditorInner2 {
|
||||||
padding-right: 25px;
|
padding-right: 25px;
|
||||||
background: url(condBordersUps.png) repeat-y 100% 0;
|
background: url(condBordersUps.png) repeat-y 100% 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upsideDown .conditionEditorTop1 {
|
.upsideDown .conditionEditorTop1 {
|
||||||
background: url(condCornersUps.png) no-repeat 100% 0;
|
background: url(condCornersUps.png) no-repeat 100% 0;
|
||||||
margin-left: 33px;
|
margin-left: 33px;
|
||||||
height: 25px;
|
height: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upsideDown .conditionEditorTop2 {
|
.upsideDown .conditionEditorTop2 {
|
||||||
position: relative;
|
position: relative;
|
||||||
left: -33px;
|
left: -33px;
|
||||||
width: 33px;
|
width: 33px;
|
||||||
height: 25px;
|
height: 25px;
|
||||||
background: url(condCornersUps.png) no-repeat;
|
background: url(condCornersUps.png) no-repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upsideDown .conditionEditorBottom1 {
|
.upsideDown .conditionEditorBottom1 {
|
||||||
background: url(condCornersUps.png) no-repeat 100% 100%;
|
background: url(condCornersUps.png) no-repeat 100% 100%;
|
||||||
margin-left: 33px;
|
margin-left: 33px;
|
||||||
height: 43px;
|
height: 43px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upsideDown .conditionEditorBottom2 {
|
.upsideDown .conditionEditorBottom2 {
|
||||||
position: relative;
|
position: relative;
|
||||||
left: -33px;
|
left: -33px;
|
||||||
width: 33px;
|
width: 33px;
|
||||||
height: 43px;
|
height: 43px;
|
||||||
background: url(condCornersUps.png) no-repeat 0 100%;
|
background: url(condCornersUps.png) no-repeat 0 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
|
|
||||||
.breakpointsGroupListBox {
|
.breakpointsGroupListBox {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpointBlockHead {
|
.breakpointBlockHead {
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-top: 4px;
|
padding-top: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpointBlockHead > .checkbox {
|
.breakpointBlockHead > .checkbox {
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpointBlockHead > .objectLink-sourceLink {
|
.breakpointBlockHead > .objectLink-sourceLink {
|
||||||
top: 4px;
|
top: 4px;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
background-color: #FFFFFF; /* issue 3308 */
|
background-color: #FFFFFF; /* issue 3308 */
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpointBlockHead > .closeButton {
|
.breakpointBlockHead > .closeButton {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 2px;
|
top: 2px;
|
||||||
right: 2px;
|
right: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpointCheckbox {
|
.breakpointCheckbox {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpointName {
|
.breakpointName {
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpointRow[aria-checked="false"] > .breakpointBlockHead > *,
|
.breakpointRow[aria-checked="false"] > .breakpointBlockHead > *,
|
||||||
.breakpointRow[aria-checked="false"] > .breakpointCode {
|
.breakpointRow[aria-checked="false"] > .breakpointCode {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpointRow[aria-checked="false"] .breakpointCheckbox,
|
.breakpointRow[aria-checked="false"] .breakpointCheckbox,
|
||||||
.breakpointRow[aria-checked="false"] .objectLink-sourceLink,
|
.breakpointRow[aria-checked="false"] .objectLink-sourceLink,
|
||||||
.breakpointRow[aria-checked="false"] .closeButton,
|
.breakpointRow[aria-checked="false"] .closeButton,
|
||||||
.breakpointRow[aria-checked="false"] .breakpointMutationType {
|
.breakpointRow[aria-checked="false"] .breakpointMutationType {
|
||||||
opacity: 1.0 !important;
|
opacity: 1.0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpointCode {
|
.breakpointCode {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
padding-left: 24px;
|
padding-left: 24px;
|
||||||
padding-bottom: 2px;
|
padding-bottom: 2px;
|
||||||
border-bottom: 1px solid #D7D7D7;
|
border-bottom: 1px solid #D7D7D7;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
color: DarkGreen;
|
color: DarkGreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpointCondition {
|
.breakpointCondition {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
padding-left: 24px;
|
padding-left: 24px;
|
||||||
padding-bottom: 2px;
|
padding-bottom: 2px;
|
||||||
border-bottom: 1px solid #D7D7D7;
|
border-bottom: 1px solid #D7D7D7;
|
||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
color: Gray;
|
color: Gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpointBlock-breakpoints > .groupHeader {
|
.breakpointBlock-breakpoints > .groupHeader {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpointBlock-monitors > .breakpointCode {
|
.breakpointBlock-monitors > .breakpointCode {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpointBlock-errorBreakpoints .breakpointCheckbox,
|
.breakpointBlock-errorBreakpoints .breakpointCheckbox,
|
||||||
.breakpointBlock-monitors .breakpointCheckbox {
|
.breakpointBlock-monitors .breakpointCheckbox {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpointHeader {
|
.breakpointHeader {
|
||||||
margin: 0 !important;
|
margin: 0 !important;
|
||||||
border-top: none !important;
|
border-top: none !important;
|
||||||
}
|
}
|
||||||
|
|||||||
1634
vendor/firebug-lite/skin/xp/firebug-1.3a2.css
vendored
1634
vendor/firebug-lite/skin/xp/firebug-1.3a2.css
vendored
File diff suppressed because it is too large
Load Diff
40
vendor/firebug-lite/skin/xp/firebug.IE6.css
vendored
40
vendor/firebug-lite/skin/xp/firebug.IE6.css
vendored
@@ -1,20 +1,20 @@
|
|||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
#fbToolbarSearch {
|
#fbToolbarSearch {
|
||||||
background-image: url(search.gif) !important;
|
background-image: url(search.gif) !important;
|
||||||
}
|
}
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
.fbErrors {
|
.fbErrors {
|
||||||
background-image: url(errorIcon.gif) !important;
|
background-image: url(errorIcon.gif) !important;
|
||||||
}
|
}
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
.logRow-info {
|
.logRow-info {
|
||||||
background-image: url(infoIcon.gif) !important;
|
background-image: url(infoIcon.gif) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logRow-warning {
|
.logRow-warning {
|
||||||
background-image: url(warningIcon.gif) !important;
|
background-image: url(warningIcon.gif) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logRow-error {
|
.logRow-error {
|
||||||
background-image: url(errorIcon.gif) !important;
|
background-image: url(errorIcon.gif) !important;
|
||||||
}
|
}
|
||||||
|
|||||||
6294
vendor/firebug-lite/skin/xp/firebug.css
vendored
6294
vendor/firebug-lite/skin/xp/firebug.css
vendored
File diff suppressed because it is too large
Load Diff
428
vendor/firebug-lite/skin/xp/firebug.html
vendored
428
vendor/firebug-lite/skin/xp/firebug.html
vendored
@@ -1,215 +1,215 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/DTD/strict.dtd">
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/DTD/strict.dtd">
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||||
<title>Firebug Lite</title>
|
<title>Firebug Lite</title>
|
||||||
<!-- An empty script to avoid FOUC when loading the stylesheet -->
|
<!-- An empty script to avoid FOUC when loading the stylesheet -->
|
||||||
<script type="text/javascript"></script>
|
<script type="text/javascript"></script>
|
||||||
<style type="text/css" media="screen">@import "firebug.css";</style>
|
<style type="text/css" media="screen">@import "firebug.css";</style>
|
||||||
<style>html,body{margin:0;padding:0;overflow:hidden;}</style>
|
<style>html,body{margin:0;padding:0;overflow:hidden;}</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="fbBody">
|
<body class="fbBody">
|
||||||
<table id="fbChrome" cellpadding="0" cellspacing="0" border="0">
|
<table id="fbChrome" cellpadding="0" cellspacing="0" border="0">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<!-- Interface - Top Area -->
|
<!-- Interface - Top Area -->
|
||||||
<td id="fbTop" colspan="2">
|
<td id="fbTop" colspan="2">
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
<div>
|
<div>
|
||||||
--><!-- <span id="fbToolbarErrors" class="fbErrors">2 errors</span> --><!--
|
--><!-- <span id="fbToolbarErrors" class="fbErrors">2 errors</span> --><!--
|
||||||
<input type="text" id="fbToolbarSearch" />
|
<input type="text" id="fbToolbarSearch" />
|
||||||
</div>
|
</div>
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<!-- Window Buttons -->
|
<!-- Window Buttons -->
|
||||||
<div id="fbWindowButtons">
|
<div id="fbWindowButtons">
|
||||||
<a id="fbWindow_btDeactivate" class="fbSmallButton fbHover" title="Deactivate Firebug for this web page"> </a>
|
<a id="fbWindow_btDeactivate" class="fbSmallButton fbHover" title="Deactivate Firebug for this web page"> </a>
|
||||||
<a id="fbWindow_btDetach" class="fbSmallButton fbHover" title="Open Firebug in popup window"> </a>
|
<a id="fbWindow_btDetach" class="fbSmallButton fbHover" title="Open Firebug in popup window"> </a>
|
||||||
<a id="fbWindow_btClose" class="fbSmallButton fbHover" title="Minimize Firebug"> </a>
|
<a id="fbWindow_btClose" class="fbSmallButton fbHover" title="Minimize Firebug"> </a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Toolbar buttons and Status Bar -->
|
<!-- Toolbar buttons and Status Bar -->
|
||||||
<div id="fbToolbar">
|
<div id="fbToolbar">
|
||||||
<div id="fbToolbarContent">
|
<div id="fbToolbarContent">
|
||||||
|
|
||||||
<!-- Firebug Button -->
|
<!-- Firebug Button -->
|
||||||
<span id="fbToolbarIcon">
|
<span id="fbToolbarIcon">
|
||||||
<a id="fbFirebugButton" class="fbIconButton" class="fbHover" target="_blank"> </a>
|
<a id="fbFirebugButton" class="fbIconButton" class="fbHover" target="_blank"> </a>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
<span id="fbLeftToolbarErrors" class="fbErrors">2 errors</span>
|
<span id="fbLeftToolbarErrors" class="fbErrors">2 errors</span>
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<!-- Toolbar Buttons -->
|
<!-- Toolbar Buttons -->
|
||||||
<span id="fbToolbarButtons">
|
<span id="fbToolbarButtons">
|
||||||
<!-- Fixed Toolbar Buttons -->
|
<!-- Fixed Toolbar Buttons -->
|
||||||
<span id="fbFixedButtons">
|
<span id="fbFixedButtons">
|
||||||
<a id="fbChrome_btInspect" class="fbButton fbHover" title="Click an element in the page to inspect">Inspect</a>
|
<a id="fbChrome_btInspect" class="fbButton fbHover" title="Click an element in the page to inspect">Inspect</a>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<!-- Console Panel Toolbar Buttons -->
|
<!-- Console Panel Toolbar Buttons -->
|
||||||
<span id="fbConsoleButtons" class="fbToolbarButtons">
|
<span id="fbConsoleButtons" class="fbToolbarButtons">
|
||||||
<a id="fbConsole_btClear" class="fbButton fbHover" title="Clear the console">Clear</a>
|
<a id="fbConsole_btClear" class="fbButton fbHover" title="Clear the console">Clear</a>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<!-- HTML Panel Toolbar Buttons -->
|
<!-- HTML Panel Toolbar Buttons -->
|
||||||
<!--
|
<!--
|
||||||
<span id="fbHTMLButtons" class="fbToolbarButtons">
|
<span id="fbHTMLButtons" class="fbToolbarButtons">
|
||||||
<a id="fbHTML_btEdit" class="fbHover" title="Edit this HTML">Edit</a>
|
<a id="fbHTML_btEdit" class="fbHover" title="Edit this HTML">Edit</a>
|
||||||
</span>
|
</span>
|
||||||
-->
|
-->
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<!-- Status Bar -->
|
<!-- Status Bar -->
|
||||||
<span id="fbStatusBarBox">
|
<span id="fbStatusBarBox">
|
||||||
<span class="fbToolbarSeparator"></span>
|
<span class="fbToolbarSeparator"></span>
|
||||||
<!-- HTML Panel Status Bar -->
|
<!-- HTML Panel Status Bar -->
|
||||||
<!--
|
<!--
|
||||||
<span id="fbHTMLStatusBar" class="fbStatusBar fbToolbarButtons">
|
<span id="fbHTMLStatusBar" class="fbStatusBar fbToolbarButtons">
|
||||||
</span>
|
</span>
|
||||||
-->
|
-->
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- PanelBars -->
|
<!-- PanelBars -->
|
||||||
<div id="fbPanelBarBox">
|
<div id="fbPanelBarBox">
|
||||||
|
|
||||||
<!-- Main PanelBar -->
|
<!-- Main PanelBar -->
|
||||||
<div id="fbPanelBar1" class="fbPanelBar">
|
<div id="fbPanelBar1" class="fbPanelBar">
|
||||||
<a id="fbConsoleTab" class="fbTab fbHover">
|
<a id="fbConsoleTab" class="fbTab fbHover">
|
||||||
<span class="fbTabL"></span>
|
<span class="fbTabL"></span>
|
||||||
<span class="fbTabText">Console</span>
|
<span class="fbTabText">Console</span>
|
||||||
<span class="fbTabMenuTarget"></span>
|
<span class="fbTabMenuTarget"></span>
|
||||||
<span class="fbTabR"></span>
|
<span class="fbTabR"></span>
|
||||||
</a>
|
</a>
|
||||||
<a id="fbHTMLTab" class="fbTab fbHover">
|
<a id="fbHTMLTab" class="fbTab fbHover">
|
||||||
<span class="fbTabL"></span>
|
<span class="fbTabL"></span>
|
||||||
<span class="fbTabText">HTML</span>
|
<span class="fbTabText">HTML</span>
|
||||||
<span class="fbTabR"></span>
|
<span class="fbTabR"></span>
|
||||||
</a>
|
</a>
|
||||||
<a class="fbTab fbHover">
|
<a class="fbTab fbHover">
|
||||||
<span class="fbTabL"></span>
|
<span class="fbTabL"></span>
|
||||||
<span class="fbTabText">CSS</span>
|
<span class="fbTabText">CSS</span>
|
||||||
<span class="fbTabR"></span>
|
<span class="fbTabR"></span>
|
||||||
</a>
|
</a>
|
||||||
<a class="fbTab fbHover">
|
<a class="fbTab fbHover">
|
||||||
<span class="fbTabL"></span>
|
<span class="fbTabL"></span>
|
||||||
<span class="fbTabText">Script</span>
|
<span class="fbTabText">Script</span>
|
||||||
<span class="fbTabR"></span>
|
<span class="fbTabR"></span>
|
||||||
</a>
|
</a>
|
||||||
<a class="fbTab fbHover">
|
<a class="fbTab fbHover">
|
||||||
<span class="fbTabL"></span>
|
<span class="fbTabL"></span>
|
||||||
<span class="fbTabText">DOM</span>
|
<span class="fbTabText">DOM</span>
|
||||||
<span class="fbTabR"></span>
|
<span class="fbTabR"></span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Side PanelBars -->
|
<!-- Side PanelBars -->
|
||||||
<div id="fbPanelBar2Box" class="hide">
|
<div id="fbPanelBar2Box" class="hide">
|
||||||
<div id="fbPanelBar2" class="fbPanelBar">
|
<div id="fbPanelBar2" class="fbPanelBar">
|
||||||
<!--
|
<!--
|
||||||
<a class="fbTab fbHover">
|
<a class="fbTab fbHover">
|
||||||
<span class="fbTabL"></span>
|
<span class="fbTabL"></span>
|
||||||
<span class="fbTabText">Style</span>
|
<span class="fbTabText">Style</span>
|
||||||
<span class="fbTabR"></span>
|
<span class="fbTabR"></span>
|
||||||
</a>
|
</a>
|
||||||
<a class="fbTab fbHover">
|
<a class="fbTab fbHover">
|
||||||
<span class="fbTabL"></span>
|
<span class="fbTabL"></span>
|
||||||
<span class="fbTabText">Layout</span>
|
<span class="fbTabText">Layout</span>
|
||||||
<span class="fbTabR"></span>
|
<span class="fbTabR"></span>
|
||||||
</a>
|
</a>
|
||||||
<a class="fbTab fbHover">
|
<a class="fbTab fbHover">
|
||||||
<span class="fbTabL"></span>
|
<span class="fbTabL"></span>
|
||||||
<span class="fbTabText">DOM</span>
|
<span class="fbTabText">DOM</span>
|
||||||
<span class="fbTabR"></span>
|
<span class="fbTabR"></span>
|
||||||
</a>
|
</a>
|
||||||
-->
|
-->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Horizontal Splitter -->
|
<!-- Horizontal Splitter -->
|
||||||
<div id="fbHSplitter"> </div>
|
<div id="fbHSplitter"> </div>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<!-- Interface - Main Area -->
|
<!-- Interface - Main Area -->
|
||||||
<tr id="fbContent">
|
<tr id="fbContent">
|
||||||
|
|
||||||
<!-- Panels -->
|
<!-- Panels -->
|
||||||
<td id="fbPanelBox1">
|
<td id="fbPanelBox1">
|
||||||
<div id="fbPanel1" class="fbFitHeight">
|
<div id="fbPanel1" class="fbFitHeight">
|
||||||
<div id="fbConsole" class="fbPanel"></div>
|
<div id="fbConsole" class="fbPanel"></div>
|
||||||
<div id="fbHTML" class="fbPanel"></div>
|
<div id="fbHTML" class="fbPanel"></div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<!-- Side Panel Box -->
|
<!-- Side Panel Box -->
|
||||||
<td id="fbPanelBox2" class="hide">
|
<td id="fbPanelBox2" class="hide">
|
||||||
|
|
||||||
<!-- VerticalSplitter -->
|
<!-- VerticalSplitter -->
|
||||||
<div id="fbVSplitter" class="fbVSplitter"> </div>
|
<div id="fbVSplitter" class="fbVSplitter"> </div>
|
||||||
|
|
||||||
<!-- Side Panels -->
|
<!-- Side Panels -->
|
||||||
<div id="fbPanel2" class="fbFitHeight">
|
<div id="fbPanel2" class="fbFitHeight">
|
||||||
|
|
||||||
<!-- HTML Side Panels -->
|
<!-- HTML Side Panels -->
|
||||||
<div id="fbHTML_Style" class="fbPanel"></div>
|
<div id="fbHTML_Style" class="fbPanel"></div>
|
||||||
<div id="fbHTML_Layout" class="fbPanel"></div>
|
<div id="fbHTML_Layout" class="fbPanel"></div>
|
||||||
<div id="fbHTML_DOM" class="fbPanel"></div>
|
<div id="fbHTML_DOM" class="fbPanel"></div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Large Command Line -->
|
<!-- Large Command Line -->
|
||||||
<textarea id="fbLargeCommandLine" class="fbFitHeight"></textarea>
|
<textarea id="fbLargeCommandLine" class="fbFitHeight"></textarea>
|
||||||
|
|
||||||
<!-- Large Command Line Buttons -->
|
<!-- Large Command Line Buttons -->
|
||||||
<div id="fbLargeCommandButtons">
|
<div id="fbLargeCommandButtons">
|
||||||
<a id="fbCommand_btRun" class="fbButton fbHover">Run</a>
|
<a id="fbCommand_btRun" class="fbButton fbHover">Run</a>
|
||||||
<a id="fbCommand_btClear" class="fbButton fbHover">Clear</a>
|
<a id="fbCommand_btClear" class="fbButton fbHover">Clear</a>
|
||||||
|
|
||||||
<a id="fbSmallCommandLineIcon" class="fbSmallButton fbHover"></a>
|
<a id="fbSmallCommandLineIcon" class="fbSmallButton fbHover"></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<!-- Interface - Bottom Area -->
|
<!-- Interface - Bottom Area -->
|
||||||
<tr id="fbBottom" class="hide">
|
<tr id="fbBottom" class="hide">
|
||||||
|
|
||||||
<!-- Command Line -->
|
<!-- Command Line -->
|
||||||
<td id="fbCommand" colspan="2">
|
<td id="fbCommand" colspan="2">
|
||||||
<div id="fbCommandBox">
|
<div id="fbCommandBox">
|
||||||
<div id="fbCommandIcon">>>></div>
|
<div id="fbCommandIcon">>>></div>
|
||||||
<input id="fbCommandLine" name="fbCommandLine" type="text" />
|
<input id="fbCommandLine" name="fbCommandLine" type="text" />
|
||||||
<a id="fbLargeCommandLineIcon" class="fbSmallButton fbHover"></a>
|
<a id="fbLargeCommandLineIcon" class="fbSmallButton fbHover"></a>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<span id="fbMiniChrome">
|
<span id="fbMiniChrome">
|
||||||
<span id="fbMiniContent">
|
<span id="fbMiniContent">
|
||||||
<span id="fbMiniIcon" title="Open Firebug Lite"></span>
|
<span id="fbMiniIcon" title="Open Firebug Lite"></span>
|
||||||
<span id="fbMiniErrors" class="fbErrors"><!-- 2 errors --></span>
|
<span id="fbMiniErrors" class="fbErrors"><!-- 2 errors --></span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<!--
|
<!--
|
||||||
<div id="fbErrorPopup">
|
<div id="fbErrorPopup">
|
||||||
<div id="fbErrorPopupContent">
|
<div id="fbErrorPopupContent">
|
||||||
<div id="fbErrorIndicator" class="fbErrors">2 errors</div>
|
<div id="fbErrorIndicator" class="fbErrors">2 errors</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
-->
|
-->
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
542
vendor/firebug-lite/skin/xp/html.css
vendored
542
vendor/firebug-lite/skin/xp/html.css
vendored
@@ -1,272 +1,272 @@
|
|||||||
/* See license.txt for terms of usage */
|
/* See license.txt for terms of usage */
|
||||||
|
|
||||||
.panelNode-html {
|
.panelNode-html {
|
||||||
-moz-box-sizing: padding-box;
|
-moz-box-sizing: padding-box;
|
||||||
padding: 4px 0 0 2px;
|
padding: 4px 0 0 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeBox {
|
.nodeBox {
|
||||||
position: relative;
|
position: relative;
|
||||||
font-family: Monaco, monospace;
|
font-family: Monaco, monospace;
|
||||||
padding-left: 13px;
|
padding-left: 13px;
|
||||||
-moz-user-select: -moz-none;
|
-moz-user-select: -moz-none;
|
||||||
}
|
}
|
||||||
.nodeBox.search-selection {
|
.nodeBox.search-selection {
|
||||||
-moz-user-select: text;
|
-moz-user-select: text;
|
||||||
}
|
}
|
||||||
.twisty {
|
.twisty {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeChildBox {
|
.nodeChildBox {
|
||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeLabel,
|
.nodeLabel,
|
||||||
.nodeCloseLabel {
|
.nodeCloseLabel {
|
||||||
margin: -2px 2px 0 2px;
|
margin: -2px 2px 0 2px;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
-moz-border-radius: 3px;
|
-moz-border-radius: 3px;
|
||||||
padding: 0 2px;
|
padding: 0 2px;
|
||||||
color: #000088;
|
color: #000088;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeCloseLabel {
|
.nodeCloseLabel {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeTag {
|
.nodeTag {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: blue;
|
color: blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeValue {
|
.nodeValue {
|
||||||
color: #FF0000;
|
color: #FF0000;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeText,
|
.nodeText,
|
||||||
.nodeComment {
|
.nodeComment {
|
||||||
margin: 0 2px;
|
margin: 0 2px;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeText {
|
.nodeText {
|
||||||
color: #333333;
|
color: #333333;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeWhiteSpace {
|
.nodeWhiteSpace {
|
||||||
border: 1px solid LightGray;
|
border: 1px solid LightGray;
|
||||||
white-space: pre; /* otherwise the border will be collapsed around zero pixels */
|
white-space: pre; /* otherwise the border will be collapsed around zero pixels */
|
||||||
margin-left: 1px;
|
margin-left: 1px;
|
||||||
color: gray;
|
color: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.nodeWhiteSpace_Space {
|
.nodeWhiteSpace_Space {
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeTextEntity {
|
.nodeTextEntity {
|
||||||
border: 1px solid gray;
|
border: 1px solid gray;
|
||||||
white-space: pre; /* otherwise the border will be collapsed around zero pixels */
|
white-space: pre; /* otherwise the border will be collapsed around zero pixels */
|
||||||
margin-left: 1px;
|
margin-left: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeComment {
|
.nodeComment {
|
||||||
color: DarkGreen;
|
color: DarkGreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
.nodeBox.highlightOpen > .nodeLabel {
|
.nodeBox.highlightOpen > .nodeLabel {
|
||||||
background-color: #EEEEEE;
|
background-color: #EEEEEE;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeBox.highlightOpen > .nodeCloseLabel,
|
.nodeBox.highlightOpen > .nodeCloseLabel,
|
||||||
.nodeBox.highlightOpen > .nodeChildBox,
|
.nodeBox.highlightOpen > .nodeChildBox,
|
||||||
.nodeBox.open > .nodeCloseLabel,
|
.nodeBox.open > .nodeCloseLabel,
|
||||||
.nodeBox.open > .nodeChildBox {
|
.nodeBox.open > .nodeChildBox {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
||||||
.nodeBox.selected > .nodeLabel {
|
.nodeBox.selected > .nodeLabel {
|
||||||
border-color: Highlight;
|
border-color: Highlight;
|
||||||
background-color: Highlight;
|
background-color: Highlight;
|
||||||
color: HighlightText !important;
|
color: HighlightText !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
||||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeTag,
|
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
||||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText {
|
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText {
|
||||||
color: inherit !important;
|
color: inherit !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
.nodeBox.highlighted > .nodeLabel {
|
.nodeBox.highlighted > .nodeLabel {
|
||||||
border-color: Highlight !important;
|
border-color: Highlight !important;
|
||||||
background-color: cyan !important;
|
background-color: cyan !important;
|
||||||
color: #000000 !important;
|
color: #000000 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox,
|
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox,
|
||||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeTag,
|
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
||||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeText {
|
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeText {
|
||||||
color: #000000 !important;
|
color: #000000 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox,
|
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox,
|
||||||
.nodeBox.nodeHidden .nodeCloseLabel,
|
.nodeBox.nodeHidden .nodeCloseLabel,
|
||||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeText,
|
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeText,
|
||||||
.nodeBox.nodeHidden .nodeText {
|
.nodeBox.nodeHidden .nodeText {
|
||||||
color: #888888;
|
color: #888888;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeTag,
|
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||||
.nodeBox.nodeHidden .nodeCloseLabel > .nodeCloseLabelBox > .nodeTag {
|
.nodeBox.nodeHidden .nodeCloseLabel > .nodeCloseLabelBox > .nodeTag {
|
||||||
color: #5F82D9;
|
color: #5F82D9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue {
|
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue {
|
||||||
color: #D86060;
|
color: #D86060;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox,
|
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox,
|
||||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeTag,
|
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
||||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeText {
|
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeText {
|
||||||
color: SkyBlue !important;
|
color: SkyBlue !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||||
|
|
||||||
.nodeBox.mutated > .nodeLabel,
|
.nodeBox.mutated > .nodeLabel,
|
||||||
.nodeAttr.mutated,
|
.nodeAttr.mutated,
|
||||||
.nodeValue.mutated,
|
.nodeValue.mutated,
|
||||||
.nodeText.mutated,
|
.nodeText.mutated,
|
||||||
.nodeBox.mutated > .nodeText {
|
.nodeBox.mutated > .nodeText {
|
||||||
background-color: #EFFF79;
|
background-color: #EFFF79;
|
||||||
color: #FF0000 !important;
|
color: #FF0000 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeBox.selected.mutated > .nodeLabel,
|
.nodeBox.selected.mutated > .nodeLabel,
|
||||||
.nodeBox.selected.mutated > .nodeLabel > .nodeLabelBox,
|
.nodeBox.selected.mutated > .nodeLabel > .nodeLabelBox,
|
||||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr.mutated > .nodeValue,
|
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr.mutated > .nodeValue,
|
||||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue.mutated,
|
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue.mutated,
|
||||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText.mutated {
|
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText.mutated {
|
||||||
background-color: #EFFF79;
|
background-color: #EFFF79;
|
||||||
border-color: #EFFF79;
|
border-color: #EFFF79;
|
||||||
color: #FF0000 !important;
|
color: #FF0000 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
|
|
||||||
.logRow-dirxml {
|
.logRow-dirxml {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.soloElement > .nodeBox {
|
.soloElement > .nodeBox {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.useA11y .nodeLabel.focused {
|
.useA11y .nodeLabel.focused {
|
||||||
outline: 2px solid #FF9933;
|
outline: 2px solid #FF9933;
|
||||||
-moz-outline-radius: 3px;
|
-moz-outline-radius: 3px;
|
||||||
outline-offset: -2px;
|
outline-offset: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.useA11y .nodeLabelBox:focus {
|
.useA11y .nodeLabelBox:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
|
|
||||||
.breakpointCode .twisty {
|
.breakpointCode .twisty {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpointCode .nodeBox.containerNodeBox,
|
.breakpointCode .nodeBox.containerNodeBox,
|
||||||
.breakpointCode .nodeLabel {
|
.breakpointCode .nodeLabel {
|
||||||
padding-left: 0px;
|
padding-left: 0px;
|
||||||
margin-left: 0px;
|
margin-left: 0px;
|
||||||
font-family: Monaco, monospace !important;
|
font-family: Monaco, monospace !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpointCode .nodeTag,
|
.breakpointCode .nodeTag,
|
||||||
.breakpointCode .nodeAttr,
|
.breakpointCode .nodeAttr,
|
||||||
.breakpointCode .nodeText,
|
.breakpointCode .nodeText,
|
||||||
.breakpointCode .nodeValue,
|
.breakpointCode .nodeValue,
|
||||||
.breakpointCode .nodeLabel {
|
.breakpointCode .nodeLabel {
|
||||||
color: DarkGreen !important;
|
color: DarkGreen !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.breakpointMutationType {
|
.breakpointMutationType {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 4px;
|
top: 4px;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
color: gray;
|
color: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************************************/
|
/************************************************************************************************/
|
||||||
/* Twisties */
|
/* Twisties */
|
||||||
|
|
||||||
.twisty,
|
.twisty,
|
||||||
.logRow-errorMessage > .hasTwisty > .errorTitle,
|
.logRow-errorMessage > .hasTwisty > .errorTitle,
|
||||||
.logRow-log > .objectBox-array.hasTwisty,
|
.logRow-log > .objectBox-array.hasTwisty,
|
||||||
.logRow-spy .spyHead .spyTitle,
|
.logRow-spy .spyHead .spyTitle,
|
||||||
.logGroup > .logRow,
|
.logGroup > .logRow,
|
||||||
.memberRow.hasChildren > .memberLabelCell > .memberLabel,
|
.memberRow.hasChildren > .memberLabelCell > .memberLabel,
|
||||||
.hasHeaders .netHrefLabel,
|
.hasHeaders .netHrefLabel,
|
||||||
.netPageRow > .netCol > .netPageTitle {
|
.netPageRow > .netCol > .netPageTitle {
|
||||||
background-image: url(twistyClosed.png);
|
background-image: url(twistyClosed.png);
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: 2px 2px;
|
background-position: 2px 2px;
|
||||||
min-height: 12px;
|
min-height: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logRow-errorMessage > .hasTwisty.opened > .errorTitle,
|
.logRow-errorMessage > .hasTwisty.opened > .errorTitle,
|
||||||
.logRow-log > .objectBox-array.hasTwisty.opened,
|
.logRow-log > .objectBox-array.hasTwisty.opened,
|
||||||
.logRow-spy.opened .spyHead .spyTitle,
|
.logRow-spy.opened .spyHead .spyTitle,
|
||||||
.logGroup.opened > .logRow,
|
.logGroup.opened > .logRow,
|
||||||
.memberRow.hasChildren.opened > .memberLabelCell > .memberLabel,
|
.memberRow.hasChildren.opened > .memberLabelCell > .memberLabel,
|
||||||
.nodeBox.highlightOpen > .nodeLabel > .twisty,
|
.nodeBox.highlightOpen > .nodeLabel > .twisty,
|
||||||
.nodeBox.open > .nodeLabel > .twisty,
|
.nodeBox.open > .nodeLabel > .twisty,
|
||||||
.netRow.opened > .netCol > .netHrefLabel,
|
.netRow.opened > .netCol > .netHrefLabel,
|
||||||
.netPageRow.opened > .netCol > .netPageTitle {
|
.netPageRow.opened > .netCol > .netPageTitle {
|
||||||
background-image: url(twistyOpen.png);
|
background-image: url(twistyOpen.png);
|
||||||
}
|
}
|
||||||
|
|
||||||
.twisty {
|
.twisty {
|
||||||
background-position: 4px 4px;
|
background-position: 4px 4px;
|
||||||
}
|
}
|
||||||
12
vendor/firebug-lite/skin/xp/roundCorner.svg
vendored
12
vendor/firebug-lite/skin/xp/roundCorner.svg
vendored
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg">
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
<rect fill="white" x="0" y="0" width="100%" height="100%" />
|
<rect fill="white" x="0" y="0" width="100%" height="100%" />
|
||||||
<rect fill="highlight" x="0" y="0" width="100%" height="100%" rx="2px"/>
|
<rect fill="highlight" x="0" y="0" width="100%" height="100%" rx="2px"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 234 B After Width: | Height: | Size: 228 B |
21
vendor/jquery/MIT-LICENSE.txt
vendored
Normal file
21
vendor/jquery/MIT-LICENSE.txt
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
Copyright 2012 jQuery Foundation and other contributors
|
||||||
|
http://jquery.com/
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
417
vendor/jquery/README.md
vendored
Normal file
417
vendor/jquery/README.md
vendored
Normal file
@@ -0,0 +1,417 @@
|
|||||||
|
[jQuery](http://jquery.com/) - New Wave JavaScript
|
||||||
|
==================================================
|
||||||
|
|
||||||
|
Contribution Guides
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
In the spirit of open source software development, jQuery always encourages community code contribution. To help you get started and before you jump into writing code, be sure to read these important contribution guidelines thoroughly:
|
||||||
|
|
||||||
|
1. [Getting Involved](http://docs.jquery.com/Getting_Involved)
|
||||||
|
2. [Core Style Guide](http://docs.jquery.com/JQuery_Core_Style_Guidelines)
|
||||||
|
3. [Tips For Bug Patching](http://docs.jquery.com/Tips_for_jQuery_Bug_Patching)
|
||||||
|
|
||||||
|
|
||||||
|
What you need to build your own jQuery
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
In order to build jQuery, you need to have GNU make 3.8 or later, Node.js/npm latest, and git 1.7 or later.
|
||||||
|
(Earlier versions might work OK, but are not tested.)
|
||||||
|
|
||||||
|
Windows users have two options:
|
||||||
|
|
||||||
|
1. Install [msysgit](https://code.google.com/p/msysgit/) (Full installer for official Git),
|
||||||
|
[GNU make for Windows](http://gnuwin32.sourceforge.net/packages/make.htm), and a
|
||||||
|
[binary version of Node.js](http://node-js.prcn.co.cc/). Make sure all three packages are installed to the same
|
||||||
|
location (by default, this is C:\Program Files\Git).
|
||||||
|
2. Install [Cygwin](http://cygwin.com/) (make sure you install the git, make, and which packages), then either follow
|
||||||
|
the [Node.js build instructions](https://github.com/ry/node/wiki/Building-node.js-on-Cygwin-%28Windows%29) or install
|
||||||
|
the [binary version of Node.js](http://node-js.prcn.co.cc/).
|
||||||
|
|
||||||
|
Mac OS users should install Xcode (comes on your Mac OS install DVD, or downloadable from
|
||||||
|
[Apple's Xcode site](http://developer.apple.com/technologies/xcode.html)) and
|
||||||
|
[Homebrew](http://mxcl.github.com/homebrew/). Once Homebrew is installed, run `brew install git` to install git,
|
||||||
|
and `brew install node` to install Node.js.
|
||||||
|
|
||||||
|
Linux/BSD users should use their appropriate package managers to install make, git, and node, or build from source
|
||||||
|
if you swing that way. Easy-peasy.
|
||||||
|
|
||||||
|
|
||||||
|
How to build your own jQuery
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
First, clone a copy of the main jQuery git repo by running:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone git://github.com/jquery/jquery.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Enter the directory and install the Node dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd jquery && npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Make sure you have `grunt` installed by testing:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
grunt -version
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Then, to get a complete, minified (w/ Uglify.js), linted (w/ JSHint) version of jQuery, type the following:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
grunt
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
The built version of jQuery will be put in the `dist/` subdirectory.
|
||||||
|
|
||||||
|
|
||||||
|
### Modules (new in 1.8)
|
||||||
|
|
||||||
|
Starting in jQuery 1.8, special builds can now be created that optionally exclude or include any of the following modules:
|
||||||
|
|
||||||
|
- ajax
|
||||||
|
- css
|
||||||
|
- dimensions
|
||||||
|
- effects
|
||||||
|
- offset
|
||||||
|
|
||||||
|
|
||||||
|
Before creating a custom build for use in production, be sure to check out the latest stable version:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git pull; git checkout $(git describe --abbrev=0 --tags)
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, make sure all Node dependencies are installed and all Git submodules are checked out:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install && grunt
|
||||||
|
```
|
||||||
|
|
||||||
|
To create a custom build, use the following special `grunt` commands:
|
||||||
|
|
||||||
|
Exclude **ajax**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
grunt custom:-ajax
|
||||||
|
```
|
||||||
|
|
||||||
|
Exclude **css**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
grunt custom:-css
|
||||||
|
```
|
||||||
|
|
||||||
|
Exclude **deprecated**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
grunt custom:-deprecated
|
||||||
|
```
|
||||||
|
|
||||||
|
Exclude **dimensions**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
grunt custom:-dimensions
|
||||||
|
```
|
||||||
|
|
||||||
|
Exclude **effects**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
grunt custom:-effects
|
||||||
|
```
|
||||||
|
|
||||||
|
Exclude **offset**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
grunt custom:-offset
|
||||||
|
```
|
||||||
|
|
||||||
|
Exclude **all** optional modules:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
grunt custom:-ajax,-css,-deprecated,-dimensions,-effects,-offset
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Note: dependencies will be handled internally, by the build process.
|
||||||
|
|
||||||
|
|
||||||
|
Running the Unit Tests
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
Start grunt to auto-build jQuery as you work:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd jquery && grunt watch
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Run the unit tests with a local server that supports PHP. No database is required. Pre-configured php local servers are available for Windows and Mac. Here are some options:
|
||||||
|
|
||||||
|
- Windows: [WAMP download](http://www.wampserver.com/en/)
|
||||||
|
- Mac: [MAMP download](http://www.mamp.info/en/index.html)
|
||||||
|
- Linux: [Setting up LAMP](https://www.linux.com/learn/tutorials/288158-easy-lamp-server-installation)
|
||||||
|
- [Mongoose (most platforms)](http://code.google.com/p/mongoose/)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Building to a different directory
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
If you want to build jQuery to a directory that is different from the default location:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
grunt && grunt dist:/path/to/special/location/
|
||||||
|
```
|
||||||
|
With this example, the output files would be:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
/path/to/special/location/jquery.js
|
||||||
|
/path/to/special/location/jquery.min.js
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to add a permanent copy destination, create a file in `dist/` called ".destination.json". Inside the file, paste and customize the following:
|
||||||
|
|
||||||
|
```json
|
||||||
|
|
||||||
|
{
|
||||||
|
"/Absolute/path/to/other/destination": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Additionally, both methods can be combined.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Updating Submodules
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Update the submodules to what is probably the latest upstream code.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
grunt update_submodules
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: This task will also be run any time the default `grunt` command is used.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Git for dummies
|
||||||
|
---------------
|
||||||
|
|
||||||
|
As the source code is handled by the version control system Git, it's useful to know some features used.
|
||||||
|
|
||||||
|
### Submodules ###
|
||||||
|
|
||||||
|
The repository uses submodules, which normally are handled directly by the Makefile, but sometimes you want to
|
||||||
|
be able to work with them manually.
|
||||||
|
|
||||||
|
Following are the steps to manually get the submodules:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/jquery/jquery.git
|
||||||
|
cd jquery
|
||||||
|
git submodule init
|
||||||
|
git submodule update
|
||||||
|
```
|
||||||
|
|
||||||
|
Or:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/jquery/jquery.git
|
||||||
|
cd jquery
|
||||||
|
git submodule update --init
|
||||||
|
```
|
||||||
|
|
||||||
|
Or:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone --recursive https://github.com/jquery/jquery.git
|
||||||
|
cd jquery
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to work inside a submodule, it is possible, but first you need to checkout a branch:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd src/sizzle
|
||||||
|
git checkout master
|
||||||
|
```
|
||||||
|
|
||||||
|
After you've committed your changes to the submodule, you'll update the jquery project to point to the new commit,
|
||||||
|
but remember to push the submodule changes before pushing the new jquery commit:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd src/sizzle
|
||||||
|
git push origin master
|
||||||
|
cd ..
|
||||||
|
git add src/sizzle
|
||||||
|
git commit
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### cleaning ###
|
||||||
|
|
||||||
|
If you want to purge your working directory back to the status of upstream, following commands can be used (remember everything you've worked on is gone after these):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git reset --hard upstream/master
|
||||||
|
git clean -fdx
|
||||||
|
```
|
||||||
|
|
||||||
|
### rebasing ###
|
||||||
|
|
||||||
|
For feature/topic branches, you should always used the `--rebase` flag to `git pull`, or if you are usually handling many temporary "to be in a github pull request" branches, run following to automate this:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git config branch.autosetuprebase local
|
||||||
|
```
|
||||||
|
(see `man git-config` for more information)
|
||||||
|
|
||||||
|
### handling merge conflicts ###
|
||||||
|
|
||||||
|
If you're getting merge conflicts when merging, instead of editing the conflicted files manually, you can use the feature
|
||||||
|
`git mergetool`. Even though the default tool `xxdiff` looks awful/old, it's rather useful.
|
||||||
|
|
||||||
|
Following are some commands that can be used there:
|
||||||
|
|
||||||
|
* `Ctrl + Alt + M` - automerge as much as possible
|
||||||
|
* `b` - jump to next merge conflict
|
||||||
|
* `s` - change the order of the conflicted lines
|
||||||
|
* `u` - undo an merge
|
||||||
|
* `left mouse button` - mark a block to be the winner
|
||||||
|
* `middle mouse button` - mark a line to be the winner
|
||||||
|
* `Ctrl + S` - save
|
||||||
|
* `Ctrl + Q` - quit
|
||||||
|
|
||||||
|
[QUnit](http://docs.jquery.com/QUnit) Reference
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
### Test methods ###
|
||||||
|
|
||||||
|
```js
|
||||||
|
expect( numAssertions );
|
||||||
|
stop();
|
||||||
|
start();
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
note: QUnit's eventual addition of an argument to stop/start is ignored in this test suite so that start and stop can be passed as callbacks without worrying about their parameters
|
||||||
|
|
||||||
|
### Test assertions ###
|
||||||
|
|
||||||
|
|
||||||
|
```js
|
||||||
|
ok( value, [message] );
|
||||||
|
equal( actual, expected, [message] );
|
||||||
|
notEqual( actual, expected, [message] );
|
||||||
|
deepEqual( actual, expected, [message] );
|
||||||
|
notDeepEqual( actual, expected, [message] );
|
||||||
|
strictEqual( actual, expected, [message] );
|
||||||
|
notStrictEqual( actual, expected, [message] );
|
||||||
|
raises( block, [expected], [message] );
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Test Suite Convenience Methods Reference (See [test/data/testinit.js](https://github.com/jquery/jquery/blob/master/test/data/testinit.js))
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
### Returns an array of elements with the given IDs ###
|
||||||
|
|
||||||
|
```js
|
||||||
|
q( ... );
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
q("main", "foo", "bar");
|
||||||
|
|
||||||
|
=> [ div#main, span#foo, input#bar ]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Asserts that a selection matches the given IDs ###
|
||||||
|
|
||||||
|
```js
|
||||||
|
t( testName, selector, [ "array", "of", "ids" ] );
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
t("Check for something", "//[a]", ["foo", "baar"]);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Fires a native DOM event without going through jQuery ###
|
||||||
|
|
||||||
|
```js
|
||||||
|
fireNative( node, eventType )
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
fireNative( jQuery("#elem")[0], "click" );
|
||||||
|
```
|
||||||
|
|
||||||
|
### Add random number to url to stop caching ###
|
||||||
|
|
||||||
|
```js
|
||||||
|
url( "some/url.php" );
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
url("data/test.html");
|
||||||
|
|
||||||
|
=> "data/test.html?10538358428943"
|
||||||
|
|
||||||
|
|
||||||
|
url("data/test.php?foo=bar");
|
||||||
|
|
||||||
|
=> "data/test.php?foo=bar&10538358345554"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Load tests in an iframe ###
|
||||||
|
|
||||||
|
Loads a given page constructing a url with fileName: `"./data/" + fileName + ".html"`
|
||||||
|
and fires the given callback on jQuery ready (using the jQuery loading from that page)
|
||||||
|
and passes the iFrame's jQuery to the callback.
|
||||||
|
|
||||||
|
```js
|
||||||
|
testIframe( fileName, testName, callback );
|
||||||
|
```
|
||||||
|
|
||||||
|
Callback arguments:
|
||||||
|
|
||||||
|
```js
|
||||||
|
callback( jQueryFromIFrame, iFrameWindow, iFrameDocument );
|
||||||
|
```
|
||||||
|
|
||||||
|
### Load tests in an iframe (window.iframeCallback) ###
|
||||||
|
|
||||||
|
Loads a given page constructing a url with fileName: `"./data/" + fileName + ".html"`
|
||||||
|
The given callback is fired when window.iframeCallback is called by the page
|
||||||
|
The arguments passed to the callback are the same as the
|
||||||
|
arguments passed to window.iframeCallback, whatever that may be
|
||||||
|
|
||||||
|
```js
|
||||||
|
testIframeWithCallback( testName, fileName, callback );
|
||||||
|
```
|
||||||
|
|
||||||
|
Questions?
|
||||||
|
----------
|
||||||
|
|
||||||
|
If you have any questions, please feel free to ask on the
|
||||||
|
[Developing jQuery Core forum](http://forum.jquery.com/developing-jquery-core) or in #jquery on irc.freenode.net.
|
||||||
File diff suppressed because it is too large
Load Diff
20
vendor/json3/LICENSE
vendored
Normal file
20
vendor/json3/LICENSE
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
Copyright (c) 2012 Kit Cambridge.
|
||||||
|
http://kitcambridge.github.com
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
124
vendor/json3/README.md
vendored
Normal file
124
vendor/json3/README.md
vendored
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
# JSON 3 #
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**JSON 3** is a modern JSON implementation compatible with a variety of JavaScript platforms, including Internet Explorer 6, Opera 7, Safari 2, and Netscape 6. The current version is **3.2.4**.
|
||||||
|
|
||||||
|
- [Development Version](http://cdnjs.cloudflare.com/ajax/libs/json3/3.2.4/json3.js) *(36.5 KB; uncompressed with comments)*
|
||||||
|
- [Production Version](http://cdnjs.cloudflare.com/ajax/libs/json3/3.2.4/json3.min.js) *(3.0 KB; compressed and `gzip`-ped)*
|
||||||
|
|
||||||
|
[JSON](http://json.org/) is a language-independent data interchange format based on a loose subset of the JavaScript grammar. Originally popularized by [Douglas Crockford](http://www.crockford.com/), the format was standardized in the [fifth edition](http://es5.github.com/) of the ECMAScript specification. The 5.1 edition, ratified in June 2011, incorporates several modifications to the grammar pertaining to the serialization of dates.
|
||||||
|
|
||||||
|
JSON 3 exposes two functions: `stringify()` for [serializing](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/stringify) a JavaScript value to JSON, and `parse()` for [producing](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/parse) a JavaScript value from a JSON source string. It is a **drop-in replacement** for [JSON 2](http://json.org/js). The functions behave exactly as described in the ECMAScript spec, **except** for the date serialization discrepancy noted below.
|
||||||
|
|
||||||
|
The JSON 3 parser does **not** use `eval` or regular expressions. This provides security and performance benefits in obsolete and mobile environments, where the margin is particularly significant. The complete [benchmark suite](http://jsperf.com/json3) is available on [jsPerf](http://jsperf.com/).
|
||||||
|
|
||||||
|
The project is [hosted on GitHub](http://git.io/json3), along with the [unit tests](http://bestiejs.github.com/json3/test/test_browser.html). It is part of the [BestieJS](https://github.com/bestiejs) family, a collection of best-in-class JavaScript libraries that promote cross-platform support, specification precedents, unit testing, and plenty of documentation.
|
||||||
|
|
||||||
|
# Changes from JSON 2 #
|
||||||
|
|
||||||
|
JSON 3...
|
||||||
|
|
||||||
|
* Correctly serializes primitive wrapper objects.
|
||||||
|
* Throws a `TypeError` when serializing cyclic structures (JSON 2 recurses until the call stack overflows).
|
||||||
|
* Utilizes **feature tests** to detect broken or incomplete *native* JSON implementations (JSON 2 only checks for the presence of the native functions). The tests are only executed once at runtime, so there is no additional performance cost when parsing or serializing values.
|
||||||
|
|
||||||
|
**As of v3.2.3**, JSON 3 is compatible with [Prototype](http://prototypejs.org) 1.6.1 and older.
|
||||||
|
|
||||||
|
In contrast to JSON 2, JSON 3 **does not**...
|
||||||
|
|
||||||
|
* Add `toJSON()` methods to the `Boolean`, `Number`, and `String` prototypes. These are not part of any standard, and are made redundant by the design of the `stringify()` implementation.
|
||||||
|
* Add `toJSON()` or `toISOString()` methods to `Date.prototype`. See the note about date serialization below.
|
||||||
|
|
||||||
|
## Date Serialization
|
||||||
|
|
||||||
|
**JSON 3 deviates from the specification in one important way**: it does not define `Date#toISOString()` or `Date#toJSON()`. This preserves CommonJS compatibility and avoids polluting native prototypes. Instead, date serialization is performed internally by the `stringify()` implementation: if a date object does not define a custom `toJSON()` method, it is serialized as a [simplified ISO 8601 date-time string](http://es5.github.com/#x15.9.1.15).
|
||||||
|
|
||||||
|
**Several native `Date#toJSON()` implementations produce date time strings that do *not* conform to the grammar outlined in the spec**. For instance, all versions of Safari 4, as well as JSON 2, fail to serialize extended years correctly. Furthermore, JSON 2 and older implementations omit the milliseconds from the date-time string (optional in ES 5, but required in 5.1). Finally, in all versions of Safari 4 and 5, serializing an invalid date will produce the string `"Invalid Date"`, rather than `null`. Because these environments exhibit other serialization bugs, however, JSON 3 will override the native `stringify()` implementation.
|
||||||
|
|
||||||
|
Portions of the date serialization code are adapted from the [`date-shim`](https://github.com/Yaffle/date-shim) project.
|
||||||
|
|
||||||
|
# Usage #
|
||||||
|
|
||||||
|
## Web Browsers
|
||||||
|
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/json3/3.2.4/json3.min.js"></script>
|
||||||
|
<script>
|
||||||
|
JSON.stringify({"Hello": 123});
|
||||||
|
// => '{"Hello":123}'
|
||||||
|
JSON.parse("[[1, 2, 3], 1, 2, 3, 4]", function (key, value) {
|
||||||
|
if (typeof value == "number") {
|
||||||
|
value = value % 2 ? "Odd" : "Even";
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
// => [["Odd", "Even", "Odd"], "Odd", "Even", "Odd", "Even"]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
## CommonJS Environments
|
||||||
|
|
||||||
|
var JSON3 = require("./path/to/json3");
|
||||||
|
JSON3.parse("[1, 2, 3]");
|
||||||
|
// => [1, 2, 3]
|
||||||
|
|
||||||
|
## JavaScript Engines
|
||||||
|
|
||||||
|
load("path/to/json3.js");
|
||||||
|
JSON.stringify({"Hello": 123, "Good-bye": 456}, ["Hello"], "\t");
|
||||||
|
// => '{\n\t"Hello": 123\n}'
|
||||||
|
|
||||||
|
# Compatibility #
|
||||||
|
|
||||||
|
JSON 3 has been **tested** with the following web browsers, CommonJS environments, and JavaScript engines.
|
||||||
|
|
||||||
|
## Web Browsers
|
||||||
|
|
||||||
|
- Windows [Internet Explorer](http://www.microsoft.com/windows/internet-explorer), version 6.0 and higher
|
||||||
|
- Mozilla [Firefox](http://www.mozilla.com/firefox), version 1.0 and higher
|
||||||
|
- Apple [Safari](http://www.apple.com/safari), version 2.0 and higher
|
||||||
|
- [Opera](http://www.opera.com) 7.02 and higher
|
||||||
|
- [Mozilla](http://sillydog.org/narchive/gecko.php) 1.0, [Netscape](http://sillydog.org/narchive/) 6.2.3, and [SeaMonkey](http://www.seamonkey-project.org/) 1.0 and higher
|
||||||
|
|
||||||
|
## CommonJS Environments
|
||||||
|
|
||||||
|
- [Node](http://nodejs.org/) 0.2.6 and higher
|
||||||
|
- [RingoJS](http://ringojs.org/) 0.4 and higher
|
||||||
|
- [Narwhal](http://narwhaljs.org/) 0.3.2 and higher
|
||||||
|
|
||||||
|
## JavaScript Engines
|
||||||
|
|
||||||
|
- Mozilla [Rhino](http://www.mozilla.org/rhino) 1.5R5 and higher
|
||||||
|
- WebKit [JSC](https://trac.webkit.org/wiki/JSC)
|
||||||
|
- Google [V8](http://code.google.com/p/v8)
|
||||||
|
|
||||||
|
## Known Incompatibilities
|
||||||
|
|
||||||
|
* Attempting to serialize the `arguments` object may produce inconsistent results across environments due to specification version differences. As a workaround, please convert the `arguments` object to an array first: `JSON.stringify([].slice.call(arguments, 0))`.
|
||||||
|
|
||||||
|
## Required Native Methods
|
||||||
|
|
||||||
|
JSON 3 assumes that the following methods exist and function as described in the ECMAScript specification:
|
||||||
|
|
||||||
|
- The `Number`, `String`, `Array`, `Object`, `Date`, `SyntaxError`, and `TypeError` constructors.
|
||||||
|
- `String.fromCharCode`
|
||||||
|
- `Object#toString`
|
||||||
|
- `Function#call`
|
||||||
|
- `Math.floor`
|
||||||
|
- `Number#toString`
|
||||||
|
- `Date#valueOf`
|
||||||
|
- `String.prototype`: `indexOf`, `charCodeAt`, `charAt`, `slice`.
|
||||||
|
- `Array.prototype`: `push`, `pop`, `join`.
|
||||||
|
|
||||||
|
# Contribute #
|
||||||
|
|
||||||
|
Check out a working copy of the JSON 3 source code with [Git](http://git-scm.com/):
|
||||||
|
|
||||||
|
$ git clone git://github.com/bestiejs/json3.git
|
||||||
|
$ cd json3
|
||||||
|
$ git submodule update --init
|
||||||
|
|
||||||
|
If you'd like to contribute a feature or bug fix, you can [fork](http://help.github.com/fork-a-repo/) JSON 3, commit your changes, and [send a pull request](http://help.github.com/send-pull-requests/). Please make sure to update the unit tests in the `test` directory as well.
|
||||||
|
|
||||||
|
Alternatively, you can use the [GitHub issue tracker](https://github.com/bestiejs/json3/issues) to submit bug reports, feature requests, and questions, or send tweets to [@kitcambridge](http://twitter.com/kitcambridge).
|
||||||
|
|
||||||
|
JSON 3 is released under the [MIT License](http://kit.mit-license.org/).
|
||||||
783
vendor/json3/lib/json3.js
vendored
Normal file
783
vendor/json3/lib/json3.js
vendored
Normal file
@@ -0,0 +1,783 @@
|
|||||||
|
/*! JSON v3.2.4 | http://bestiejs.github.com/json3 | Copyright 2012, Kit Cambridge | http://kit.mit-license.org */
|
||||||
|
;(function () {
|
||||||
|
// Convenience aliases.
|
||||||
|
var getClass = {}.toString, isProperty, forEach, undef;
|
||||||
|
|
||||||
|
// Detect the `define` function exposed by asynchronous module loaders. The
|
||||||
|
// strict `define` check is necessary for compatibility with `r.js`.
|
||||||
|
var isLoader = typeof define === "function" && define.amd, JSON3 = !isLoader && typeof exports == "object" && exports;
|
||||||
|
|
||||||
|
if (JSON3 || isLoader) {
|
||||||
|
if (typeof JSON == "object" && JSON) {
|
||||||
|
// Delegate to the native `stringify` and `parse` implementations in
|
||||||
|
// asynchronous module loaders and CommonJS environments.
|
||||||
|
if (isLoader) {
|
||||||
|
JSON3 = JSON;
|
||||||
|
} else {
|
||||||
|
JSON3.stringify = JSON.stringify;
|
||||||
|
JSON3.parse = JSON.parse;
|
||||||
|
}
|
||||||
|
} else if (isLoader) {
|
||||||
|
JSON3 = this.JSON = {};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Export for web browsers and JavaScript engines.
|
||||||
|
JSON3 = this.JSON || (this.JSON = {});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Local variables.
|
||||||
|
var Escapes, toPaddedString, quote, serialize;
|
||||||
|
var fromCharCode, Unescapes, abort, lex, get, walk, update, Index, Source;
|
||||||
|
|
||||||
|
// Test the `Date#getUTC*` methods. Based on work by @Yaffle.
|
||||||
|
var isExtended = new Date(-3509827334573292), floor, Months, getDay;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// The `getUTCFullYear`, `Month`, and `Date` methods return nonsensical
|
||||||
|
// results for certain dates in Opera >= 10.53.
|
||||||
|
isExtended = isExtended.getUTCFullYear() == -109252 && isExtended.getUTCMonth() === 0 && isExtended.getUTCDate() == 1 &&
|
||||||
|
// Safari < 2.0.2 stores the internal millisecond time value correctly,
|
||||||
|
// but clips the values returned by the date methods to the range of
|
||||||
|
// signed 32-bit integers ([-2 ** 31, 2 ** 31 - 1]).
|
||||||
|
isExtended.getUTCHours() == 10 && isExtended.getUTCMinutes() == 37 && isExtended.getUTCSeconds() == 6 && isExtended.getUTCMilliseconds() == 708;
|
||||||
|
} catch (exception) {}
|
||||||
|
|
||||||
|
// Internal: Determines whether the native `JSON.stringify` and `parse`
|
||||||
|
// implementations are spec-compliant. Based on work by Ken Snyder.
|
||||||
|
function has(name) {
|
||||||
|
var stringifySupported, parseSupported, value, serialized = '{"A":[1,true,false,null,"\\u0000\\b\\n\\f\\r\\t"]}', all = name == "json";
|
||||||
|
if (all || name == "json-stringify" || name == "json-parse") {
|
||||||
|
// Test `JSON.stringify`.
|
||||||
|
if (name == "json-stringify" || all) {
|
||||||
|
if ((stringifySupported = typeof JSON3.stringify == "function" && isExtended)) {
|
||||||
|
// A test function object with a custom `toJSON` method.
|
||||||
|
(value = function () {
|
||||||
|
return 1;
|
||||||
|
}).toJSON = value;
|
||||||
|
try {
|
||||||
|
stringifySupported =
|
||||||
|
// Firefox 3.1b1 and b2 serialize string, number, and boolean
|
||||||
|
// primitives as object literals.
|
||||||
|
JSON3.stringify(0) === "0" &&
|
||||||
|
// FF 3.1b1, b2, and JSON 2 serialize wrapped primitives as object
|
||||||
|
// literals.
|
||||||
|
JSON3.stringify(new Number()) === "0" &&
|
||||||
|
JSON3.stringify(new String()) == '""' &&
|
||||||
|
// FF 3.1b1, 2 throw an error if the value is `null`, `undefined`, or
|
||||||
|
// does not define a canonical JSON representation (this applies to
|
||||||
|
// objects with `toJSON` properties as well, *unless* they are nested
|
||||||
|
// within an object or array).
|
||||||
|
JSON3.stringify(getClass) === undef &&
|
||||||
|
// IE 8 serializes `undefined` as `"undefined"`. Safari <= 5.1.7 and
|
||||||
|
// FF 3.1b3 pass this test.
|
||||||
|
JSON3.stringify(undef) === undef &&
|
||||||
|
// Safari <= 5.1.7 and FF 3.1b3 throw `Error`s and `TypeError`s,
|
||||||
|
// respectively, if the value is omitted entirely.
|
||||||
|
JSON3.stringify() === undef &&
|
||||||
|
// FF 3.1b1, 2 throw an error if the given value is not a number,
|
||||||
|
// string, array, object, Boolean, or `null` literal. This applies to
|
||||||
|
// objects with custom `toJSON` methods as well, unless they are nested
|
||||||
|
// inside object or array literals. YUI 3.0.0b1 ignores custom `toJSON`
|
||||||
|
// methods entirely.
|
||||||
|
JSON3.stringify(value) === "1" &&
|
||||||
|
JSON3.stringify([value]) == "[1]" &&
|
||||||
|
// Prototype <= 1.6.1 serializes `[undefined]` as `"[]"` instead of
|
||||||
|
// `"[null]"`.
|
||||||
|
JSON3.stringify([undef]) == "[null]" &&
|
||||||
|
// YUI 3.0.0b1 fails to serialize `null` literals.
|
||||||
|
JSON3.stringify(null) == "null" &&
|
||||||
|
// FF 3.1b1, 2 halts serialization if an array contains a function:
|
||||||
|
// `[1, true, getClass, 1]` serializes as "[1,true,],". These versions
|
||||||
|
// of Firefox also allow trailing commas in JSON objects and arrays.
|
||||||
|
// FF 3.1b3 elides non-JSON values from objects and arrays, unless they
|
||||||
|
// define custom `toJSON` methods.
|
||||||
|
JSON3.stringify([undef, getClass, null]) == "[null,null,null]" &&
|
||||||
|
// Simple serialization test. FF 3.1b1 uses Unicode escape sequences
|
||||||
|
// where character escape codes are expected (e.g., `\b` => `\u0008`).
|
||||||
|
JSON3.stringify({ "A": [value, true, false, null, "\0\b\n\f\r\t"] }) == serialized &&
|
||||||
|
// FF 3.1b1 and b2 ignore the `filter` and `width` arguments.
|
||||||
|
JSON3.stringify(null, value) === "1" &&
|
||||||
|
JSON3.stringify([1, 2], null, 1) == "[\n 1,\n 2\n]" &&
|
||||||
|
// JSON 2, Prototype <= 1.7, and older WebKit builds incorrectly
|
||||||
|
// serialize extended years.
|
||||||
|
JSON3.stringify(new Date(-8.64e15)) == '"-271821-04-20T00:00:00.000Z"' &&
|
||||||
|
// The milliseconds are optional in ES 5, but required in 5.1.
|
||||||
|
JSON3.stringify(new Date(8.64e15)) == '"+275760-09-13T00:00:00.000Z"' &&
|
||||||
|
// Firefox <= 11.0 incorrectly serializes years prior to 0 as negative
|
||||||
|
// four-digit years instead of six-digit years. Credits: @Yaffle.
|
||||||
|
JSON3.stringify(new Date(-621987552e5)) == '"-000001-01-01T00:00:00.000Z"' &&
|
||||||
|
// Safari <= 5.1.5 and Opera >= 10.53 incorrectly serialize millisecond
|
||||||
|
// values less than 1000. Credits: @Yaffle.
|
||||||
|
JSON3.stringify(new Date(-1)) == '"1969-12-31T23:59:59.999Z"';
|
||||||
|
} catch (exception) {
|
||||||
|
stringifySupported = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!all) {
|
||||||
|
return stringifySupported;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Test `JSON.parse`.
|
||||||
|
if (name == "json-parse" || all) {
|
||||||
|
if (typeof JSON3.parse == "function") {
|
||||||
|
try {
|
||||||
|
// FF 3.1b1, b2 will throw an exception if a bare literal is provided.
|
||||||
|
// Conforming implementations should also coerce the initial argument to
|
||||||
|
// a string prior to parsing.
|
||||||
|
if (JSON3.parse("0") === 0 && !JSON3.parse(false)) {
|
||||||
|
// Simple parsing test.
|
||||||
|
value = JSON3.parse(serialized);
|
||||||
|
if ((parseSupported = value.A.length == 5 && value.A[0] == 1)) {
|
||||||
|
try {
|
||||||
|
// Safari <= 5.1.2 and FF 3.1b1 allow unescaped tabs in strings.
|
||||||
|
parseSupported = !JSON3.parse('"\t"');
|
||||||
|
} catch (exception) {}
|
||||||
|
if (parseSupported) {
|
||||||
|
try {
|
||||||
|
// FF 4.0 and 4.0.1 allow leading `+` signs, and leading and
|
||||||
|
// trailing decimal points. FF 4.0, 4.0.1, and IE 9-10 also
|
||||||
|
// allow certain octal literals.
|
||||||
|
parseSupported = JSON3.parse("01") != 1;
|
||||||
|
} catch (exception) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (exception) {
|
||||||
|
parseSupported = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!all) {
|
||||||
|
return parseSupported;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stringifySupported && parseSupported;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!has("json")) {
|
||||||
|
// Define additional utility methods if the `Date` methods are buggy.
|
||||||
|
if (!isExtended) {
|
||||||
|
floor = Math.floor;
|
||||||
|
// A mapping between the months of the year and the number of days between
|
||||||
|
// January 1st and the first of the respective month.
|
||||||
|
Months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
|
||||||
|
// Internal: Calculates the number of days between the Unix epoch and the
|
||||||
|
// first day of the given month.
|
||||||
|
getDay = function (year, month) {
|
||||||
|
return Months[month] + 365 * (year - 1970) + floor((year - 1969 + (month = +(month > 1))) / 4) - floor((year - 1901 + month) / 100) + floor((year - 1601 + month) / 400);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal: Determines if a property is a direct property of the given
|
||||||
|
// object. Delegates to the native `Object#hasOwnProperty` method.
|
||||||
|
if (!(isProperty = {}.hasOwnProperty)) {
|
||||||
|
isProperty = function (property) {
|
||||||
|
var members = {}, constructor;
|
||||||
|
if ((members.__proto__ = null, members.__proto__ = {
|
||||||
|
// The *proto* property cannot be set multiple times in recent
|
||||||
|
// versions of Firefox and SeaMonkey.
|
||||||
|
"toString": 1
|
||||||
|
}, members).toString != getClass) {
|
||||||
|
// Safari <= 2.0.3 doesn't implement `Object#hasOwnProperty`, but
|
||||||
|
// supports the mutable *proto* property.
|
||||||
|
isProperty = function (property) {
|
||||||
|
// Capture and break the object's prototype chain (see section 8.6.2
|
||||||
|
// of the ES 5.1 spec). The parenthesized expression prevents an
|
||||||
|
// unsafe transformation by the Closure Compiler.
|
||||||
|
var original = this.__proto__, result = property in (this.__proto__ = null, this);
|
||||||
|
// Restore the original prototype chain.
|
||||||
|
this.__proto__ = original;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// Capture a reference to the top-level `Object` constructor.
|
||||||
|
constructor = members.constructor;
|
||||||
|
// Use the `constructor` property to simulate `Object#hasOwnProperty` in
|
||||||
|
// other environments.
|
||||||
|
isProperty = function (property) {
|
||||||
|
var parent = (this.constructor || constructor).prototype;
|
||||||
|
return property in this && !(property in parent && this[property] === parent[property]);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
members = null;
|
||||||
|
return isProperty.call(this, property);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal: Normalizes the `for...in` iteration algorithm across
|
||||||
|
// environments. Each enumerated key is yielded to a `callback` function.
|
||||||
|
forEach = function (object, callback) {
|
||||||
|
var size = 0, Properties, members, property, forEach;
|
||||||
|
|
||||||
|
// Tests for bugs in the current environment's `for...in` algorithm. The
|
||||||
|
// `valueOf` property inherits the non-enumerable flag from
|
||||||
|
// `Object.prototype` in older versions of IE, Netscape, and Mozilla.
|
||||||
|
(Properties = function () {
|
||||||
|
this.valueOf = 0;
|
||||||
|
}).prototype.valueOf = 0;
|
||||||
|
|
||||||
|
// Iterate over a new instance of the `Properties` class.
|
||||||
|
members = new Properties();
|
||||||
|
for (property in members) {
|
||||||
|
// Ignore all properties inherited from `Object.prototype`.
|
||||||
|
if (isProperty.call(members, property)) {
|
||||||
|
size++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Properties = members = null;
|
||||||
|
|
||||||
|
// Normalize the iteration algorithm.
|
||||||
|
if (!size) {
|
||||||
|
// A list of non-enumerable properties inherited from `Object.prototype`.
|
||||||
|
members = ["valueOf", "toString", "toLocaleString", "propertyIsEnumerable", "isPrototypeOf", "hasOwnProperty", "constructor"];
|
||||||
|
// IE <= 8, Mozilla 1.0, and Netscape 6.2 ignore shadowed non-enumerable
|
||||||
|
// properties.
|
||||||
|
forEach = function (object, callback) {
|
||||||
|
var isFunction = getClass.call(object) == "[object Function]", property, length;
|
||||||
|
for (property in object) {
|
||||||
|
// Gecko <= 1.0 enumerates the `prototype` property of functions under
|
||||||
|
// certain conditions; IE does not.
|
||||||
|
if (!(isFunction && property == "prototype") && isProperty.call(object, property)) {
|
||||||
|
callback(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Manually invoke the callback for each non-enumerable property.
|
||||||
|
for (length = members.length; property = members[--length]; isProperty.call(object, property) && callback(property));
|
||||||
|
};
|
||||||
|
} else if (size == 2) {
|
||||||
|
// Safari <= 2.0.4 enumerates shadowed properties twice.
|
||||||
|
forEach = function (object, callback) {
|
||||||
|
// Create a set of iterated properties.
|
||||||
|
var members = {}, isFunction = getClass.call(object) == "[object Function]", property;
|
||||||
|
for (property in object) {
|
||||||
|
// Store each property name to prevent double enumeration. The
|
||||||
|
// `prototype` property of functions is not enumerated due to cross-
|
||||||
|
// environment inconsistencies.
|
||||||
|
if (!(isFunction && property == "prototype") && !isProperty.call(members, property) && (members[property] = 1) && isProperty.call(object, property)) {
|
||||||
|
callback(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// No bugs detected; use the standard `for...in` algorithm.
|
||||||
|
forEach = function (object, callback) {
|
||||||
|
var isFunction = getClass.call(object) == "[object Function]", property, isConstructor;
|
||||||
|
for (property in object) {
|
||||||
|
if (!(isFunction && property == "prototype") && isProperty.call(object, property) && !(isConstructor = property === "constructor")) {
|
||||||
|
callback(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Manually invoke the callback for the `constructor` property due to
|
||||||
|
// cross-environment inconsistencies.
|
||||||
|
if (isConstructor || isProperty.call(object, (property = "constructor"))) {
|
||||||
|
callback(property);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return forEach(object, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Public: Serializes a JavaScript `value` as a JSON string. The optional
|
||||||
|
// `filter` argument may specify either a function that alters how object and
|
||||||
|
// array members are serialized, or an array of strings and numbers that
|
||||||
|
// indicates which properties should be serialized. The optional `width`
|
||||||
|
// argument may be either a string or number that specifies the indentation
|
||||||
|
// level of the output.
|
||||||
|
if (!has("json-stringify")) {
|
||||||
|
// Internal: A map of control characters and their escaped equivalents.
|
||||||
|
Escapes = {
|
||||||
|
"\\": "\\\\",
|
||||||
|
'"': '\\"',
|
||||||
|
"\b": "\\b",
|
||||||
|
"\f": "\\f",
|
||||||
|
"\n": "\\n",
|
||||||
|
"\r": "\\r",
|
||||||
|
"\t": "\\t"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Internal: Converts `value` into a zero-padded string such that its
|
||||||
|
// length is at least equal to `width`. The `width` must be <= 6.
|
||||||
|
toPaddedString = function (width, value) {
|
||||||
|
// The `|| 0` expression is necessary to work around a bug in
|
||||||
|
// Opera <= 7.54u2 where `0 == -0`, but `String(-0) !== "0"`.
|
||||||
|
return ("000000" + (value || 0)).slice(-width);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Internal: Double-quotes a string `value`, replacing all ASCII control
|
||||||
|
// characters (characters with code unit values between 0 and 31) with
|
||||||
|
// their escaped equivalents. This is an implementation of the
|
||||||
|
// `Quote(value)` operation defined in ES 5.1 section 15.12.3.
|
||||||
|
quote = function (value) {
|
||||||
|
var result = '"', index = 0, symbol;
|
||||||
|
for (; symbol = value.charAt(index); index++) {
|
||||||
|
// Escape the reverse solidus, double quote, backspace, form feed, line
|
||||||
|
// feed, carriage return, and tab characters.
|
||||||
|
result += '\\"\b\f\n\r\t'.indexOf(symbol) > -1 ? Escapes[symbol] :
|
||||||
|
// If the character is a control character, append its Unicode escape
|
||||||
|
// sequence; otherwise, append the character as-is.
|
||||||
|
(Escapes[symbol] = symbol < " " ? "\\u00" + toPaddedString(2, symbol.charCodeAt(0).toString(16)) : symbol);
|
||||||
|
}
|
||||||
|
return result + '"';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Internal: Recursively serializes an object. Implements the
|
||||||
|
// `Str(key, holder)`, `JO(value)`, and `JA(value)` operations.
|
||||||
|
serialize = function (property, object, callback, properties, whitespace, indentation, stack) {
|
||||||
|
var value = object[property], className, year, month, date, time, hours, minutes, seconds, milliseconds, results, element, index, length, prefix, any, result;
|
||||||
|
if (typeof value == "object" && value) {
|
||||||
|
className = getClass.call(value);
|
||||||
|
if (className == "[object Date]" && !isProperty.call(value, "toJSON")) {
|
||||||
|
if (value > -1 / 0 && value < 1 / 0) {
|
||||||
|
// Dates are serialized according to the `Date#toJSON` method
|
||||||
|
// specified in ES 5.1 section 15.9.5.44. See section 15.9.1.15
|
||||||
|
// for the ISO 8601 date time string format.
|
||||||
|
if (getDay) {
|
||||||
|
// Manually compute the year, month, date, hours, minutes,
|
||||||
|
// seconds, and milliseconds if the `getUTC*` methods are
|
||||||
|
// buggy. Adapted from @Yaffle's `date-shim` project.
|
||||||
|
date = floor(value / 864e5);
|
||||||
|
for (year = floor(date / 365.2425) + 1970 - 1; getDay(year + 1, 0) <= date; year++);
|
||||||
|
for (month = floor((date - getDay(year, 0)) / 30.42); getDay(year, month + 1) <= date; month++);
|
||||||
|
date = 1 + date - getDay(year, month);
|
||||||
|
// The `time` value specifies the time within the day (see ES
|
||||||
|
// 5.1 section 15.9.1.2). The formula `(A % B + B) % B` is used
|
||||||
|
// to compute `A modulo B`, as the `%` operator does not
|
||||||
|
// correspond to the `modulo` operation for negative numbers.
|
||||||
|
time = (value % 864e5 + 864e5) % 864e5;
|
||||||
|
// The hours, minutes, seconds, and milliseconds are obtained by
|
||||||
|
// decomposing the time within the day. See section 15.9.1.10.
|
||||||
|
hours = floor(time / 36e5) % 24;
|
||||||
|
minutes = floor(time / 6e4) % 60;
|
||||||
|
seconds = floor(time / 1e3) % 60;
|
||||||
|
milliseconds = time % 1e3;
|
||||||
|
} else {
|
||||||
|
year = value.getUTCFullYear();
|
||||||
|
month = value.getUTCMonth();
|
||||||
|
date = value.getUTCDate();
|
||||||
|
hours = value.getUTCHours();
|
||||||
|
minutes = value.getUTCMinutes();
|
||||||
|
seconds = value.getUTCSeconds();
|
||||||
|
milliseconds = value.getUTCMilliseconds();
|
||||||
|
}
|
||||||
|
// Serialize extended years correctly.
|
||||||
|
value = (year <= 0 || year >= 1e4 ? (year < 0 ? "-" : "+") + toPaddedString(6, year < 0 ? -year : year) : toPaddedString(4, year)) +
|
||||||
|
"-" + toPaddedString(2, month + 1) + "-" + toPaddedString(2, date) +
|
||||||
|
// Months, dates, hours, minutes, and seconds should have two
|
||||||
|
// digits; milliseconds should have three.
|
||||||
|
"T" + toPaddedString(2, hours) + ":" + toPaddedString(2, minutes) + ":" + toPaddedString(2, seconds) +
|
||||||
|
// Milliseconds are optional in ES 5.0, but required in 5.1.
|
||||||
|
"." + toPaddedString(3, milliseconds) + "Z";
|
||||||
|
} else {
|
||||||
|
value = null;
|
||||||
|
}
|
||||||
|
} else if (typeof value.toJSON == "function" && ((className != "[object Number]" && className != "[object String]" && className != "[object Array]") || isProperty.call(value, "toJSON"))) {
|
||||||
|
// Prototype <= 1.6.1 adds non-standard `toJSON` methods to the
|
||||||
|
// `Number`, `String`, `Date`, and `Array` prototypes. JSON 3
|
||||||
|
// ignores all `toJSON` methods on these objects unless they are
|
||||||
|
// defined directly on an instance.
|
||||||
|
value = value.toJSON(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (callback) {
|
||||||
|
// If a replacement function was provided, call it to obtain the value
|
||||||
|
// for serialization.
|
||||||
|
value = callback.call(object, property, value);
|
||||||
|
}
|
||||||
|
if (value === null) {
|
||||||
|
return "null";
|
||||||
|
}
|
||||||
|
className = getClass.call(value);
|
||||||
|
if (className == "[object Boolean]") {
|
||||||
|
// Booleans are represented literally.
|
||||||
|
return "" + value;
|
||||||
|
} else if (className == "[object Number]") {
|
||||||
|
// JSON numbers must be finite. `Infinity` and `NaN` are serialized as
|
||||||
|
// `"null"`.
|
||||||
|
return value > -1 / 0 && value < 1 / 0 ? "" + value : "null";
|
||||||
|
} else if (className == "[object String]") {
|
||||||
|
// Strings are double-quoted and escaped.
|
||||||
|
return quote(value);
|
||||||
|
}
|
||||||
|
// Recursively serialize objects and arrays.
|
||||||
|
if (typeof value == "object") {
|
||||||
|
// Check for cyclic structures. This is a linear search; performance
|
||||||
|
// is inversely proportional to the number of unique nested objects.
|
||||||
|
for (length = stack.length; length--;) {
|
||||||
|
if (stack[length] === value) {
|
||||||
|
// Cyclic structures cannot be serialized by `JSON.stringify`.
|
||||||
|
throw TypeError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add the object to the stack of traversed objects.
|
||||||
|
stack.push(value);
|
||||||
|
results = [];
|
||||||
|
// Save the current indentation level and indent one additional level.
|
||||||
|
prefix = indentation;
|
||||||
|
indentation += whitespace;
|
||||||
|
if (className == "[object Array]") {
|
||||||
|
// Recursively serialize array elements.
|
||||||
|
for (index = 0, length = value.length; index < length; any || (any = true), index++) {
|
||||||
|
element = serialize(index, value, callback, properties, whitespace, indentation, stack);
|
||||||
|
results.push(element === undef ? "null" : element);
|
||||||
|
}
|
||||||
|
result = any ? (whitespace ? "[\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "]" : ("[" + results.join(",") + "]")) : "[]";
|
||||||
|
} else {
|
||||||
|
// Recursively serialize object members. Members are selected from
|
||||||
|
// either a user-specified list of property names, or the object
|
||||||
|
// itself.
|
||||||
|
forEach(properties || value, function (property) {
|
||||||
|
var element = serialize(property, value, callback, properties, whitespace, indentation, stack);
|
||||||
|
if (element !== undef) {
|
||||||
|
// According to ES 5.1 section 15.12.3: "If `gap` {whitespace}
|
||||||
|
// is not the empty string, let `member` {quote(property) + ":"}
|
||||||
|
// be the concatenation of `member` and the `space` character."
|
||||||
|
// The "`space` character" refers to the literal space
|
||||||
|
// character, not the `space` {width} argument provided to
|
||||||
|
// `JSON.stringify`.
|
||||||
|
results.push(quote(property) + ":" + (whitespace ? " " : "") + element);
|
||||||
|
}
|
||||||
|
any || (any = true);
|
||||||
|
});
|
||||||
|
result = any ? (whitespace ? "{\n" + indentation + results.join(",\n" + indentation) + "\n" + prefix + "}" : ("{" + results.join(",") + "}")) : "{}";
|
||||||
|
}
|
||||||
|
// Remove the object from the traversed object stack.
|
||||||
|
stack.pop();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Public: `JSON.stringify`. See ES 5.1 section 15.12.3.
|
||||||
|
JSON3.stringify = function (source, filter, width) {
|
||||||
|
var whitespace, callback, properties, index, length, value;
|
||||||
|
if (typeof filter == "function" || typeof filter == "object" && filter) {
|
||||||
|
if (getClass.call(filter) == "[object Function]") {
|
||||||
|
callback = filter;
|
||||||
|
} else if (getClass.call(filter) == "[object Array]") {
|
||||||
|
// Convert the property names array into a makeshift set.
|
||||||
|
properties = {};
|
||||||
|
for (index = 0, length = filter.length; index < length; value = filter[index++], ((getClass.call(value) == "[object String]" || getClass.call(value) == "[object Number]") && (properties[value] = 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (width) {
|
||||||
|
if (getClass.call(width) == "[object Number]") {
|
||||||
|
// Convert the `width` to an integer and create a string containing
|
||||||
|
// `width` number of space characters.
|
||||||
|
if ((width -= width % 1) > 0) {
|
||||||
|
for (whitespace = "", width > 10 && (width = 10); whitespace.length < width; whitespace += " ");
|
||||||
|
}
|
||||||
|
} else if (getClass.call(width) == "[object String]") {
|
||||||
|
whitespace = width.length <= 10 ? width : width.slice(0, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Opera <= 7.54u2 discards the values associated with empty string keys
|
||||||
|
// (`""`) only if they are used directly within an object member list
|
||||||
|
// (e.g., `!("" in { "": 1})`).
|
||||||
|
return serialize("", (value = {}, value[""] = source, value), callback, properties, whitespace, "", []);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public: Parses a JSON source string.
|
||||||
|
if (!has("json-parse")) {
|
||||||
|
fromCharCode = String.fromCharCode;
|
||||||
|
// Internal: A map of escaped control characters and their unescaped
|
||||||
|
// equivalents.
|
||||||
|
Unescapes = {
|
||||||
|
"\\": "\\",
|
||||||
|
'"': '"',
|
||||||
|
"/": "/",
|
||||||
|
"b": "\b",
|
||||||
|
"t": "\t",
|
||||||
|
"n": "\n",
|
||||||
|
"f": "\f",
|
||||||
|
"r": "\r"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Internal: Resets the parser state and throws a `SyntaxError`.
|
||||||
|
abort = function() {
|
||||||
|
Index = Source = null;
|
||||||
|
throw SyntaxError();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Internal: Returns the next token, or `"$"` if the parser has reached
|
||||||
|
// the end of the source string. A token may be a string, number, `null`
|
||||||
|
// literal, or Boolean literal.
|
||||||
|
lex = function () {
|
||||||
|
var source = Source, length = source.length, symbol, value, begin, position, sign;
|
||||||
|
while (Index < length) {
|
||||||
|
symbol = source.charAt(Index);
|
||||||
|
if ("\t\r\n ".indexOf(symbol) > -1) {
|
||||||
|
// Skip whitespace tokens, including tabs, carriage returns, line
|
||||||
|
// feeds, and space characters.
|
||||||
|
Index++;
|
||||||
|
} else if ("{}[]:,".indexOf(symbol) > -1) {
|
||||||
|
// Parse a punctuator token at the current position.
|
||||||
|
Index++;
|
||||||
|
return symbol;
|
||||||
|
} else if (symbol == '"') {
|
||||||
|
// Advance to the next character and parse a JSON string at the
|
||||||
|
// current position. String tokens are prefixed with the sentinel
|
||||||
|
// `@` character to distinguish them from punctuators.
|
||||||
|
for (value = "@", Index++; Index < length;) {
|
||||||
|
symbol = source.charAt(Index);
|
||||||
|
if (symbol < " ") {
|
||||||
|
// Unescaped ASCII control characters are not permitted.
|
||||||
|
abort();
|
||||||
|
} else if (symbol == "\\") {
|
||||||
|
// Parse escaped JSON control characters, `"`, `\`, `/`, and
|
||||||
|
// Unicode escape sequences.
|
||||||
|
symbol = source.charAt(++Index);
|
||||||
|
if ('\\"/btnfr'.indexOf(symbol) > -1) {
|
||||||
|
// Revive escaped control characters.
|
||||||
|
value += Unescapes[symbol];
|
||||||
|
Index++;
|
||||||
|
} else if (symbol == "u") {
|
||||||
|
// Advance to the first character of the escape sequence.
|
||||||
|
begin = ++Index;
|
||||||
|
// Validate the Unicode escape sequence.
|
||||||
|
for (position = Index + 4; Index < position; Index++) {
|
||||||
|
symbol = source.charAt(Index);
|
||||||
|
// A valid sequence comprises four hexdigits that form a
|
||||||
|
// single hexadecimal value.
|
||||||
|
if (!(symbol >= "0" && symbol <= "9" || symbol >= "a" && symbol <= "f" || symbol >= "A" && symbol <= "F")) {
|
||||||
|
// Invalid Unicode escape sequence.
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Revive the escaped character.
|
||||||
|
value += fromCharCode("0x" + source.slice(begin, Index));
|
||||||
|
} else {
|
||||||
|
// Invalid escape sequence.
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (symbol == '"') {
|
||||||
|
// An unescaped double-quote character marks the end of the
|
||||||
|
// string.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Append the original character as-is.
|
||||||
|
value += symbol;
|
||||||
|
Index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (source.charAt(Index) == '"') {
|
||||||
|
Index++;
|
||||||
|
// Return the revived string.
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
// Unterminated string.
|
||||||
|
abort();
|
||||||
|
} else {
|
||||||
|
// Parse numbers and literals.
|
||||||
|
begin = Index;
|
||||||
|
// Advance the scanner's position past the sign, if one is
|
||||||
|
// specified.
|
||||||
|
if (symbol == "-") {
|
||||||
|
sign = true;
|
||||||
|
symbol = source.charAt(++Index);
|
||||||
|
}
|
||||||
|
// Parse an integer or floating-point value.
|
||||||
|
if (symbol >= "0" && symbol <= "9") {
|
||||||
|
// Leading zeroes are interpreted as octal literals.
|
||||||
|
if (symbol == "0" && (symbol = source.charAt(Index + 1), symbol >= "0" && symbol <= "9")) {
|
||||||
|
// Illegal octal literal.
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
sign = false;
|
||||||
|
// Parse the integer component.
|
||||||
|
for (; Index < length && (symbol = source.charAt(Index), symbol >= "0" && symbol <= "9"); Index++);
|
||||||
|
// Floats cannot contain a leading decimal point; however, this
|
||||||
|
// case is already accounted for by the parser.
|
||||||
|
if (source.charAt(Index) == ".") {
|
||||||
|
position = ++Index;
|
||||||
|
// Parse the decimal component.
|
||||||
|
for (; position < length && (symbol = source.charAt(position), symbol >= "0" && symbol <= "9"); position++);
|
||||||
|
if (position == Index) {
|
||||||
|
// Illegal trailing decimal.
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
Index = position;
|
||||||
|
}
|
||||||
|
// Parse exponents.
|
||||||
|
symbol = source.charAt(Index);
|
||||||
|
if (symbol == "e" || symbol == "E") {
|
||||||
|
// Skip past the sign following the exponent, if one is
|
||||||
|
// specified.
|
||||||
|
symbol = source.charAt(++Index);
|
||||||
|
if (symbol == "+" || symbol == "-") {
|
||||||
|
Index++;
|
||||||
|
}
|
||||||
|
// Parse the exponential component.
|
||||||
|
for (position = Index; position < length && (symbol = source.charAt(position), symbol >= "0" && symbol <= "9"); position++);
|
||||||
|
if (position == Index) {
|
||||||
|
// Illegal empty exponent.
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
Index = position;
|
||||||
|
}
|
||||||
|
// Coerce the parsed value to a JavaScript number.
|
||||||
|
return +source.slice(begin, Index);
|
||||||
|
}
|
||||||
|
// A negative sign may only precede numbers.
|
||||||
|
if (sign) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
// `true`, `false`, and `null` literals.
|
||||||
|
if (source.slice(Index, Index + 4) == "true") {
|
||||||
|
Index += 4;
|
||||||
|
return true;
|
||||||
|
} else if (source.slice(Index, Index + 5) == "false") {
|
||||||
|
Index += 5;
|
||||||
|
return false;
|
||||||
|
} else if (source.slice(Index, Index + 4) == "null") {
|
||||||
|
Index += 4;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// Unrecognized token.
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Return the sentinel `$` character if the parser has reached the end
|
||||||
|
// of the source string.
|
||||||
|
return "$";
|
||||||
|
};
|
||||||
|
|
||||||
|
// Internal: Parses a JSON `value` token.
|
||||||
|
get = function (value) {
|
||||||
|
var results, any, key;
|
||||||
|
if (value == "$") {
|
||||||
|
// Unexpected end of input.
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
if (typeof value == "string") {
|
||||||
|
if (value.charAt(0) == "@") {
|
||||||
|
// Remove the sentinel `@` character.
|
||||||
|
return value.slice(1);
|
||||||
|
}
|
||||||
|
// Parse object and array literals.
|
||||||
|
if (value == "[") {
|
||||||
|
// Parses a JSON array, returning a new JavaScript array.
|
||||||
|
results = [];
|
||||||
|
for (;; any || (any = true)) {
|
||||||
|
value = lex();
|
||||||
|
// A closing square bracket marks the end of the array literal.
|
||||||
|
if (value == "]") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// If the array literal contains elements, the current token
|
||||||
|
// should be a comma separating the previous element from the
|
||||||
|
// next.
|
||||||
|
if (any) {
|
||||||
|
if (value == ",") {
|
||||||
|
value = lex();
|
||||||
|
if (value == "]") {
|
||||||
|
// Unexpected trailing `,` in array literal.
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// A `,` must separate each array element.
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Elisions and leading commas are not permitted.
|
||||||
|
if (value == ",") {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
results.push(get(value));
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
} else if (value == "{") {
|
||||||
|
// Parses a JSON object, returning a new JavaScript object.
|
||||||
|
results = {};
|
||||||
|
for (;; any || (any = true)) {
|
||||||
|
value = lex();
|
||||||
|
// A closing curly brace marks the end of the object literal.
|
||||||
|
if (value == "}") {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// If the object literal contains members, the current token
|
||||||
|
// should be a comma separator.
|
||||||
|
if (any) {
|
||||||
|
if (value == ",") {
|
||||||
|
value = lex();
|
||||||
|
if (value == "}") {
|
||||||
|
// Unexpected trailing `,` in object literal.
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// A `,` must separate each object member.
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Leading commas are not permitted, object property names must be
|
||||||
|
// double-quoted strings, and a `:` must separate each property
|
||||||
|
// name and value.
|
||||||
|
if (value == "," || typeof value != "string" || value.charAt(0) != "@" || lex() != ":") {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
results[value.slice(1)] = get(lex());
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
// Unexpected token encountered.
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Internal: Updates a traversed object member.
|
||||||
|
update = function(source, property, callback) {
|
||||||
|
var element = walk(source, property, callback);
|
||||||
|
if (element === undef) {
|
||||||
|
delete source[property];
|
||||||
|
} else {
|
||||||
|
source[property] = element;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Internal: Recursively traverses a parsed JSON object, invoking the
|
||||||
|
// `callback` function for each value. This is an implementation of the
|
||||||
|
// `Walk(holder, name)` operation defined in ES 5.1 section 15.12.2.
|
||||||
|
walk = function (source, property, callback) {
|
||||||
|
var value = source[property], length;
|
||||||
|
if (typeof value == "object" && value) {
|
||||||
|
if (getClass.call(value) == "[object Array]") {
|
||||||
|
for (length = value.length; length--;) {
|
||||||
|
update(value, length, callback);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// `forEach` can't be used to traverse an array in Opera <= 8.54,
|
||||||
|
// as `Object#hasOwnProperty` returns `false` for array indices
|
||||||
|
// (e.g., `![1, 2, 3].hasOwnProperty("0")`).
|
||||||
|
forEach(value, function (property) {
|
||||||
|
update(value, property, callback);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return callback.call(source, property, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Public: `JSON.parse`. See ES 5.1 section 15.12.2.
|
||||||
|
JSON3.parse = function (source, callback) {
|
||||||
|
var result, value;
|
||||||
|
Index = 0;
|
||||||
|
Source = source;
|
||||||
|
result = get(lex());
|
||||||
|
// If a JSON string contains multiple tokens, it is invalid.
|
||||||
|
if (lex() != "$") {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
// Reset the parser state.
|
||||||
|
Index = Source = null;
|
||||||
|
return callback && getClass.call(callback) == "[object Function]" ? walk((value = {}, value[""] = result, value), "", callback) : result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export for asynchronous module loaders.
|
||||||
|
if (isLoader) {
|
||||||
|
define(function () {
|
||||||
|
return JSON3;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).call(this);
|
||||||
2
vendor/platform.js/LICENSE.txt
vendored
2
vendor/platform.js/LICENSE.txt
vendored
@@ -1,4 +1,4 @@
|
|||||||
Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
|
Copyright 2011-2013 John-David Dalton <http://allyoucanleet.com/>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
|
|||||||
37
vendor/platform.js/README.md
vendored
37
vendor/platform.js/README.md
vendored
@@ -1,4 +1,4 @@
|
|||||||
# Platform.js <sup>v1.0.0-pre</sup>
|
# Platform.js <sup>v1.0.0</sup>
|
||||||
|
|
||||||
A platform detection library that works on nearly all JavaScript platforms<sup><a name="fnref1" href="#fn1">1</a></sup>.
|
A platform detection library that works on nearly all JavaScript platforms<sup><a name="fnref1" href="#fn1">1</a></sup>.
|
||||||
|
|
||||||
@@ -16,35 +16,39 @@ The documentation for Platform.js can be viewed here: [/doc/README.md](https://g
|
|||||||
|
|
||||||
For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/platform.js/wiki/Roadmap).
|
For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/platform.js/wiki/Roadmap).
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
Platform.js has been tested in at least Adobe AIR 3.1, Chrome 5-21, Firefox 1-14, IE 6-9, Opera 9.25-12, Safari 3-6, Node.js 0.8.6, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC5.
|
||||||
|
|
||||||
## Installation and usage
|
## Installation and usage
|
||||||
|
|
||||||
In a browser or Adobe AIR:
|
In a browser or Adobe AIR:
|
||||||
|
|
||||||
~~~ html
|
```html
|
||||||
<script src="platform.js"></script>
|
<script src="platform.js"></script>
|
||||||
~~~
|
```
|
||||||
|
|
||||||
Via [npm](http://npmjs.org/):
|
Via [npm](http://npmjs.org/):
|
||||||
|
|
||||||
~~~ bash
|
```bash
|
||||||
npm install platform
|
npm install platform
|
||||||
~~~
|
```
|
||||||
|
|
||||||
In [Narwhal](http://narwhaljs.org/), [Node.js](http://nodejs.org/), and [RingoJS](http://ringojs.org/):
|
In [Node.js](http://nodejs.org/) and [RingoJS](http://ringojs.org/):
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
var platform = require('platform');
|
var platform = require('platform');
|
||||||
~~~
|
```
|
||||||
|
|
||||||
In [Rhino](http://www.mozilla.org/rhino/):
|
In [Rhino](http://www.mozilla.org/rhino/):
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
load('platform.js');
|
load('platform.js');
|
||||||
~~~
|
```
|
||||||
|
|
||||||
In an AMD loader like [RequireJS](http://requirejs.org/):
|
In an AMD loader like [RequireJS](http://requirejs.org/):
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
require({
|
require({
|
||||||
'paths': {
|
'paths': {
|
||||||
'platform': 'path/to/platform'
|
'platform': 'path/to/platform'
|
||||||
@@ -53,11 +57,11 @@ require({
|
|||||||
['platform'], function(platform) {
|
['platform'], function(platform) {
|
||||||
console.log(platform.name);
|
console.log(platform.name);
|
||||||
});
|
});
|
||||||
~~~
|
```
|
||||||
|
|
||||||
Usage example:
|
Usage example:
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
// on IE10 x86 platform preview running in IE7 compatibility mode on Windows 7 64 bit edition
|
// on IE10 x86 platform preview running in IE7 compatibility mode on Windows 7 64 bit edition
|
||||||
platform.name; // 'IE'
|
platform.name; // 'IE'
|
||||||
platform.version; // '10.0'
|
platform.version; // '10.0'
|
||||||
@@ -81,12 +85,7 @@ info.version; // '11.52'
|
|||||||
info.layout; // 'Presto'
|
info.layout; // 'Presto'
|
||||||
info.os; // 'Mac OS X 10.7.2'
|
info.os; // 'Mac OS X 10.7.2'
|
||||||
info.description; // 'Opera 11.52 (identifying as Firefox 4.0) on Mac OS X 10.7.2'
|
info.description; // 'Opera 11.52 (identifying as Firefox 4.0) on Mac OS X 10.7.2'
|
||||||
~~~
|
```
|
||||||
|
|
||||||
## Footnotes
|
|
||||||
|
|
||||||
1. Platform.js has been tested in at least Adobe AIR 2.6, Chrome 5-15, Firefox 1.5-8, IE 6-10, Opera 9.25-11.52, Safari 2-5.1.1, Node.js 0.4.8-0.6.1, Narwhal 0.3.2, RingoJS 0.7-0.8, and Rhino 1.7RC3.
|
|
||||||
<a name="fn1" title="Jump back to footnote 1 in the text." href="#fnref1">↩</a>
|
|
||||||
|
|
||||||
## Author
|
## Author
|
||||||
|
|
||||||
|
|||||||
106
vendor/platform.js/platform.js
vendored
106
vendor/platform.js/platform.js
vendored
@@ -1,6 +1,6 @@
|
|||||||
/*!
|
/*!
|
||||||
* Platform.js v1.0.0-pre <http://mths.be/platform>
|
* Platform.js v1.0.0 <http://mths.be/platform>
|
||||||
* Copyright 2010-2012 John-David Dalton <http://allyoucanleet.com/>
|
* Copyright 2010-2013 John-David Dalton <http://allyoucanleet.com/>
|
||||||
* Available under MIT license <http://mths.be/mit>
|
* Available under MIT license <http://mths.be/mit>
|
||||||
*/
|
*/
|
||||||
;(function(window) {
|
;(function(window) {
|
||||||
@@ -297,7 +297,7 @@
|
|||||||
'Opera Mini',
|
'Opera Mini',
|
||||||
'Opera',
|
'Opera',
|
||||||
'Chrome',
|
'Chrome',
|
||||||
{ 'label': 'Chrome Mobile', 'pattern': 'CrMo' },
|
{ 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' },
|
||||||
{ 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },
|
{ 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },
|
||||||
{ 'label': 'IE', 'pattern': 'MSIE' },
|
{ 'label': 'IE', 'pattern': 'MSIE' },
|
||||||
'Safari'
|
'Safari'
|
||||||
@@ -512,12 +512,11 @@
|
|||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return platform description when the platform object is coerced to a string.
|
* Returns `platform.description` when the platform object is coerced to a string.
|
||||||
*
|
*
|
||||||
* @name toString
|
* @name toString
|
||||||
* @memberOf platform
|
* @memberOf platform
|
||||||
* @type Function
|
* @returns {String} Returns `platform.description` if available, else an empty string.
|
||||||
* @returns {String} The platform description.
|
|
||||||
*/
|
*/
|
||||||
function toStringPlatform() {
|
function toStringPlatform() {
|
||||||
return this.description || '';
|
return this.description || '';
|
||||||
@@ -573,7 +572,7 @@
|
|||||||
// detect non-Opera versions (order is important)
|
// detect non-Opera versions (order is important)
|
||||||
if (!version) {
|
if (!version) {
|
||||||
version = getVersion([
|
version = getVersion([
|
||||||
'(?:Cloud9|CrMo|Opera ?Mini|Raven|Silk(?!/[\\d.]+$))',
|
'(?:Cloud9|CriOS|CrMo|Opera ?Mini|Raven|Silk(?!/[\\d.]+$))',
|
||||||
'Version',
|
'Version',
|
||||||
qualify(name),
|
qualify(name),
|
||||||
'(?:Firefox|Minefield|NetFront)'
|
'(?:Firefox|Minefield|NetFront)'
|
||||||
@@ -708,7 +707,7 @@
|
|||||||
))
|
))
|
||||||
) && !reOpera.test(data = parse.call(forOwn, ua.replace(reOpera, '') + ';')) && data.name) {
|
) && !reOpera.test(data = parse.call(forOwn, ua.replace(reOpera, '') + ';')) && data.name) {
|
||||||
|
|
||||||
// when "indentifying" the UA contains both Opera and the other browser's name
|
// when "indentifying", the UA contains both Opera and the other browser's name
|
||||||
data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');
|
data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');
|
||||||
if (reOpera.test(name)) {
|
if (reOpera.test(name)) {
|
||||||
if (/IE/.test(data) && os == 'Mac OS') {
|
if (/IE/.test(data) && os == 'Mac OS') {
|
||||||
@@ -716,7 +715,7 @@
|
|||||||
}
|
}
|
||||||
data = 'identify' + data;
|
data = 'identify' + data;
|
||||||
}
|
}
|
||||||
// when "masking" the UA contains only the other browser's name
|
// when "masking", the UA contains only the other browser's name
|
||||||
else {
|
else {
|
||||||
data = 'mask' + data;
|
data = 'mask' + data;
|
||||||
if (operaClass) {
|
if (operaClass) {
|
||||||
@@ -760,7 +759,7 @@
|
|||||||
data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : '5');
|
data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : '5');
|
||||||
} else {
|
} else {
|
||||||
layout[1] = 'like Chrome';
|
layout[1] = 'like Chrome';
|
||||||
data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 535.21 ? 18 : '19');
|
data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : '21');
|
||||||
}
|
}
|
||||||
// add the postfix of ".x" or "+" for approximate versions
|
// add the postfix of ".x" or "+" for approximate versions
|
||||||
layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+');
|
layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+');
|
||||||
@@ -769,6 +768,30 @@
|
|||||||
version = data;
|
version = data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// detect Opera desktop modes
|
||||||
|
if (name == 'Opera' && (data = /(?:zbov|zvav)$/.exec(os))) {
|
||||||
|
name += ' ';
|
||||||
|
description.unshift('desktop mode');
|
||||||
|
if (data == 'zvav') {
|
||||||
|
name += 'Mini';
|
||||||
|
version = null;
|
||||||
|
} else {
|
||||||
|
name += 'Mobile';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// detect Chrome desktop mode
|
||||||
|
else if (name == 'Safari' && /Chrome/.exec(layout[1])) {
|
||||||
|
description.unshift('desktop mode');
|
||||||
|
name = 'Chrome Mobile';
|
||||||
|
version = null;
|
||||||
|
|
||||||
|
if (/Mac OS X/.test(os)) {
|
||||||
|
manufacturer = 'Apple';
|
||||||
|
os = 'iOS 4.3+';
|
||||||
|
} else {
|
||||||
|
os = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
// strip incorrect OS versions
|
// strip incorrect OS versions
|
||||||
if (version && version.indexOf(data = /[\d.]+$/.exec(os)) == 0 &&
|
if (version && version.indexOf(data = /[\d.]+$/.exec(os)) == 0 &&
|
||||||
ua.indexOf('/' + data + '-') > -1) {
|
ua.indexOf('/' + data + '-') > -1) {
|
||||||
@@ -793,9 +816,25 @@
|
|||||||
if (product) {
|
if (product) {
|
||||||
description.push((/^on /.test(description[description.length -1]) ? '' : 'on ') + product);
|
description.push((/^on /.test(description[description.length -1]) ? '' : 'on ') + product);
|
||||||
}
|
}
|
||||||
|
// parse OS into an object
|
||||||
|
if (os) {
|
||||||
|
data = / ([\d.+]+)$/.exec(os);
|
||||||
|
os = {
|
||||||
|
'architecture': 32,
|
||||||
|
'family': data ? os.replace(data[0], '') : os,
|
||||||
|
'version': data ? data[1] : null,
|
||||||
|
'toString': function() {
|
||||||
|
var version = this.version;
|
||||||
|
return this.family + (version ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : '');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
// add browser/OS architecture
|
// add browser/OS architecture
|
||||||
if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i).test(arch) && !/\bi686\b/i.test(arch)) {
|
if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) {
|
||||||
os = os && os + (data.test(os) ? '' : ' 64-bit');
|
if (os) {
|
||||||
|
os.architecture = 64;
|
||||||
|
os.family = os.family.replace(RegExp(' *' + data), '');
|
||||||
|
}
|
||||||
if (name && (/WOW64/i.test(ua) ||
|
if (name && (/WOW64/i.test(ua) ||
|
||||||
(useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform)))) {
|
(useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform)))) {
|
||||||
description.unshift('32-bit');
|
description.unshift('32-bit');
|
||||||
@@ -834,11 +873,46 @@
|
|||||||
* The name of the operating system.
|
* The name of the operating system.
|
||||||
*
|
*
|
||||||
* @memberOf platform
|
* @memberOf platform
|
||||||
* @type String|Null
|
* @type Object
|
||||||
*/
|
*/
|
||||||
'os': os && (name &&
|
'os': os
|
||||||
!(os == os.split(' ')[0] && (os == name.split(' ')[0] || product)) &&
|
? (name &&
|
||||||
description.push(product ? '(' + os + ')' : 'on ' + os), os),
|
!(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product)) &&
|
||||||
|
description.push(product ? '(' + os + ')' : 'on ' + os), os)
|
||||||
|
: {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The CPU architecture the OS is built for.
|
||||||
|
*
|
||||||
|
* @memberOf platform.os
|
||||||
|
* @type Number|Null
|
||||||
|
*/
|
||||||
|
'architecture': null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The family of the OS.
|
||||||
|
*
|
||||||
|
* @memberOf platform.os
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'family': null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The version of the OS.
|
||||||
|
*
|
||||||
|
* @memberOf platform.os
|
||||||
|
* @type String|Null
|
||||||
|
*/
|
||||||
|
'version': null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the OS string.
|
||||||
|
*
|
||||||
|
* @memberOf platform.os
|
||||||
|
* @returns {String} The OS string.
|
||||||
|
*/
|
||||||
|
'toString': function() { return 'null'; }
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The platform description.
|
* The platform description.
|
||||||
|
|||||||
2
vendor/qunit-clib/LICENSE.txt
vendored
2
vendor/qunit-clib/LICENSE.txt
vendored
@@ -1,4 +1,4 @@
|
|||||||
Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
|
Copyright 2011-2013 John-David Dalton <http://allyoucanleet.com/>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
|
|||||||
37
vendor/qunit-clib/README.md
vendored
37
vendor/qunit-clib/README.md
vendored
@@ -1,27 +1,32 @@
|
|||||||
# QUnit CLIB <sup>v1.0.0-pre</sup>
|
# QUnit CLIB <sup>v1.2.0</sup>
|
||||||
## command-line interface boilerplate
|
## command-line interface boilerplate
|
||||||
|
|
||||||
QUnit CLIB helps extend QUnit's CLI support to many common CLI environments<sup><a name="fnref1" href="#fn1">1</a></sup>.
|
QUnit CLIB helps extend QUnit's CLI support to many common CLI environments.
|
||||||
|
|
||||||
## Screenshot
|
## Screenshot
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
QUnit CLIB has been tested in at least Node.js 0.4.8-0.8.19, Narwhal v0.3.2, PhantomJS 1.8.1, RingoJS v0.9, and Rhino v1.7RC5.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
~~~ js
|
```js
|
||||||
(function(window) {
|
(function(window) {
|
||||||
|
|
||||||
// use a single load function
|
// use a single "load" function
|
||||||
var load = typeof require == 'function' ? require : window.load;
|
var load = typeof require == 'function' ? require : window.load;
|
||||||
|
|
||||||
// load QUnit and CLIB if needed
|
// load QUnit and CLIB if needed
|
||||||
var QUnit =
|
var QUnit =
|
||||||
window.QUnit || (
|
window.QUnit || (
|
||||||
window.setTimeout || (window.addEventListener = window.setTimeout = / /),
|
window.addEventListener || (window.addEventListener = Function.prototype),
|
||||||
|
window.setTimeout || (window.setTimeout = Function.prototype),
|
||||||
window.QUnit = load('path/to/qunit.js') || window.QUnit,
|
window.QUnit = load('path/to/qunit.js') || window.QUnit,
|
||||||
load('path/to/qunit-clib.js'),
|
load('path/to/qunit-clib.js'),
|
||||||
(window.addEventListener || 0).test && delete window.addEventListener,
|
window.addEventListener === Function.prototype && delete window.addEventListener,
|
||||||
window.QUnit
|
window.QUnit
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -34,30 +39,18 @@ QUnit CLIB helps extend QUnit's CLI support to many common CLI environments<sup>
|
|||||||
});
|
});
|
||||||
|
|
||||||
// must call `QUnit.start()` if using QUnit < 1.3.0 with Node.js or any
|
// must call `QUnit.start()` if using QUnit < 1.3.0 with Node.js or any
|
||||||
// version of QUnit with Narwhal, Rhino, or RingoJS
|
// version of QUnit with Narwhal, PhantomJS, Rhino, or RingoJS
|
||||||
if (!window.document) {
|
if (!window.document) {
|
||||||
QUnit.start();
|
QUnit.start();
|
||||||
}
|
}
|
||||||
}(typeof global == 'object' && global || this));
|
}(typeof global == 'object' && global || this));
|
||||||
~~~
|
```
|
||||||
|
|
||||||
## Cloning this repo
|
|
||||||
|
|
||||||
To clone this repository just use:
|
|
||||||
|
|
||||||
~~~ bash
|
|
||||||
git clone https://github.com/jdalton/qunit-clib.git
|
|
||||||
cd qunit-clib
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Feel free to fork and send pull requests if you see improvements!
|
|
||||||
|
|
||||||
## Footnotes
|
## Footnotes
|
||||||
|
|
||||||
1. QUnit CLIB has been tested in at least Node.js v0.4.8-0.6.1, Narwhal v0.3.2, RingoJS v0.7.0-0.8.0, and Rhino v1.7RC3.
|
1. QUnit v1.3.0 does not work with Narwhal or Ringo < v0.8.0
|
||||||
<a name="fn1" title="Jump back to footnote 1 in the text." href="#fnref1">↩</a>
|
|
||||||
|
|
||||||
2. QUnit v1.3.0 does not work with Narwhal or Ringo < v0.8.0
|
2. Rhino v1.7RC4 does not support timeout fallbacks `clearTimeout` and `setTimeout`
|
||||||
|
|
||||||
## Author
|
## Author
|
||||||
|
|
||||||
|
|||||||
506
vendor/qunit-clib/qunit-clib.js
vendored
506
vendor/qunit-clib/qunit-clib.js
vendored
@@ -1,317 +1,269 @@
|
|||||||
/*!
|
/*!
|
||||||
* QUnit CLI Boilerplate v1.0.0-pre
|
* QUnit CLI Boilerplate v1.2.0
|
||||||
* Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
|
* Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
|
||||||
* Based on a gist by Jörn Zaefferer <https://gist.github.com/722381>
|
* Based on a gist by Jörn Zaefferer <https://gist.github.com/722381>
|
||||||
* Available under MIT license <http://mths.be/mit>
|
* Available under MIT license <http://mths.be/mit>
|
||||||
*/
|
*/
|
||||||
;(function(global) {
|
;(function(window) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
/** Add `console.log()` support for Narwhal, Rhino, and RingoJS */
|
|
||||||
global.console || (global.console = { 'log': global.print });
|
|
||||||
|
|
||||||
/** Reduce global.QUnit.QUnit -> global.QUnit */
|
|
||||||
global.QUnit && (QUnit = QUnit.QUnit || QUnit);
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/** Used as a horizontal rule in console output */
|
|
||||||
var hr = '----------------------------------------';
|
|
||||||
|
|
||||||
/** Shortcut used to convert array-like objects to arrays */
|
|
||||||
var slice = [].slice;
|
|
||||||
|
|
||||||
/** Used to resolve a value's internal [[Class]] */
|
|
||||||
var toString = {}.toString;
|
|
||||||
|
|
||||||
/** Used by timer methods */
|
|
||||||
var doneCalled,
|
|
||||||
timer,
|
|
||||||
counter = 0,
|
|
||||||
ids = {};
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An iteration utility for arrays.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Array} array The array to iterate over.
|
|
||||||
* @param {Function} callback The function called per iteration.
|
|
||||||
*/
|
|
||||||
function each(array, callback) {
|
|
||||||
var index = -1,
|
|
||||||
length = array.length;
|
|
||||||
|
|
||||||
while (++index < length) {
|
|
||||||
callback(array[index], index, array);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the specified `value` is a function.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {Mixed} value The value to check.
|
|
||||||
* @returns {Boolean} Returns `true` if `value` is a function, else `false`.
|
|
||||||
*/
|
|
||||||
function isFunction(value) {
|
|
||||||
return toString.call(value) == '[object Function]';
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Timeout fallbacks based on the work of Andrea Giammarchi and Weston C.
|
* Timeout fallbacks based on the work of Andrea Giammarchi and Weston C.
|
||||||
* https://github.com/WebReflection/wru/blob/master/src/rhinoTimers.js
|
* https://github.com/WebReflection/wru/blob/master/src/rhinoTimers.js
|
||||||
* http://stackoverflow.com/questions/2261705/how-to-run-a-javascript-function-asynchronously-without-using-settimeout
|
* http://stackoverflow.com/questions/2261705/how-to-run-a-javascript-function-asynchronously-without-using-settimeout
|
||||||
*/
|
*/
|
||||||
|
(function() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the delay set by `setInterval` or `setTimeout`.
|
* Schedules timer-based callbacks.
|
||||||
*
|
*
|
||||||
* @memberOf global
|
* @private
|
||||||
* @param {Number} id The ID of the timeout to be cleared.
|
* @param {Function|String} fn The function to call.
|
||||||
*/
|
* @oaram {Number} delay The number of milliseconds to delay the `fn` call.
|
||||||
function clearTimer(id) {
|
* @param [arg1, arg2, ...] Arguments to invoke `fn` with.
|
||||||
if (ids[id]) {
|
* @param {Boolean} repeated A flag to specify whether `fn` is called repeatedly.
|
||||||
ids[id].cancel();
|
* @returns {Number} The the ID of the timeout.
|
||||||
timer.purge();
|
*/
|
||||||
delete ids[id];
|
function schedule(fn, delay, args, repeated) {
|
||||||
}
|
// Rhino 1.7RC4 will error assigning `task` below
|
||||||
}
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=775566
|
||||||
|
var task = ids[++counter] = new JavaAdapter(java.util.TimerTask, {
|
||||||
/**
|
'run': function() {
|
||||||
* Schedules timer-based callbacks.
|
fn.apply(window, args);
|
||||||
*
|
}
|
||||||
* @private
|
});
|
||||||
* @param {Function} fn The function to call.
|
// support non-functions
|
||||||
* @oaram {Number} delay The number of milliseconds to delay the `fn` call.
|
if (typeof fn != 'function') {
|
||||||
* @param [arg1, arg2, ...] Arguments to invoke `fn` with.
|
fn = (function(code) {
|
||||||
* @param {Boolean} repeated A flag to specify whether `fn` is called repeatedly.
|
code = String(code);
|
||||||
* @returns {Number} The the ID of the timeout.
|
return function() { eval(code); };
|
||||||
*/
|
}(fn));
|
||||||
function schedule(fn, delay, args, repeated) {
|
|
||||||
var task = ids[++counter] = new JavaAdapter(java.util.TimerTask, {
|
|
||||||
'run': function() {
|
|
||||||
fn.apply(global, args);
|
|
||||||
}
|
}
|
||||||
});
|
// used by setInterval
|
||||||
// support non-functions
|
if (repeated) {
|
||||||
if (!isFunction(fn)) {
|
timer.schedule(task, delay, delay);
|
||||||
fn = (function(code) {
|
}
|
||||||
code = String(code);
|
// used by setTimeout
|
||||||
return function() { eval(code); };
|
else {
|
||||||
}(fn));
|
timer.schedule(task, delay);
|
||||||
|
}
|
||||||
|
return counter;
|
||||||
}
|
}
|
||||||
// used by setInterval
|
|
||||||
if (repeated) {
|
|
||||||
timer.schedule(task, delay, delay);
|
|
||||||
}
|
|
||||||
// used by setTimeout
|
|
||||||
else {
|
|
||||||
timer.schedule(task, delay);
|
|
||||||
}
|
|
||||||
return counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes a code snippet or function repeatedly, with a delay between each call.
|
* Clears the delay set by `setInterval` or `setTimeout`.
|
||||||
*
|
*
|
||||||
* @memberOf global
|
* @memberOf window
|
||||||
* @param {Function|String} fn The function to call or string to evaluate.
|
* @param {Number} id The ID of the timeout to be cleared.
|
||||||
* @oaram {Number} delay The number of milliseconds to delay each `fn` call.
|
*/
|
||||||
* @param [arg1, arg2, ...] Arguments to invoke `fn` with.
|
function clearTimer(id) {
|
||||||
* @returns {Number} The the ID of the timeout.
|
if (ids[id]) {
|
||||||
*/
|
ids[id].cancel();
|
||||||
function setInterval(fn, delay) {
|
timer.purge();
|
||||||
return schedule(fn, delay, slice.call(arguments, 2), true);
|
delete ids[id];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes a code snippet or a function after specified delay.
|
* Executes a code snippet or function repeatedly, with a delay between each call.
|
||||||
*
|
*
|
||||||
* @memberOf global
|
* @memberOf window
|
||||||
* @param {Function|String} fn The function to call or string to evaluate.
|
* @param {Function|String} fn The function to call or string to evaluate.
|
||||||
* @oaram {Number} delay The number of milliseconds to delay the `fn` call.
|
* @oaram {Number} delay The number of milliseconds to delay each `fn` call.
|
||||||
* @param [arg1, arg2, ...] Arguments to invoke `fn` with.
|
* @param [arg1, arg2, ...] Arguments to invoke `fn` with.
|
||||||
* @returns {Number} The the ID of the timeout.
|
* @returns {Number} The the ID of the timeout.
|
||||||
*/
|
*/
|
||||||
function setTimeout(fn, delay) {
|
function setInterval(fn, delay) {
|
||||||
return schedule(fn, delay, slice.call(arguments, 2));
|
return schedule(fn, delay, slice.call(arguments, 2), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes a code snippet or a function after specified delay.
|
||||||
|
*
|
||||||
|
* @memberOf window
|
||||||
|
* @param {Function|String} fn The function to call or string to evaluate.
|
||||||
|
* @oaram {Number} delay The number of milliseconds to delay the `fn` call.
|
||||||
|
* @param [arg1, arg2, ...] Arguments to invoke `fn` with.
|
||||||
|
* @returns {Number} The the ID of the timeout.
|
||||||
|
*/
|
||||||
|
function setTimeout(fn, delay) {
|
||||||
|
return schedule(fn, delay, slice.call(arguments, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
var counter = 0,
|
||||||
|
ids = {},
|
||||||
|
slice = Array.prototype.slice,
|
||||||
|
timer = new java.util.Timer;
|
||||||
|
|
||||||
|
window.clearInterval =
|
||||||
|
window.clearTimeout = clearTimer;
|
||||||
|
window.setInterval = setInterval;
|
||||||
|
window.setTimeout = setTimeout;
|
||||||
|
} catch(e) { }
|
||||||
|
}());
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
(function() {
|
||||||
* A logging callback triggered when all testing is completed.
|
|
||||||
*
|
|
||||||
* @memberOf QUnit
|
|
||||||
* @param {Object} details An object with properties `failed`, `passed`,
|
|
||||||
* `runtime`, and `total`.
|
|
||||||
*/
|
|
||||||
function done(details) {
|
|
||||||
// stop `asyncTest()` from erroneously calling `done()` twice in
|
|
||||||
// environments w/o timeouts
|
|
||||||
if (doneCalled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
doneCalled = true;
|
|
||||||
console.log(hr);
|
|
||||||
console.log(' PASS: ' + details.passed + ' FAIL: ' + details.failed + ' TOTAL: ' + details.total);
|
|
||||||
console.log(' Finished in ' + details.runtime + ' milliseconds.');
|
|
||||||
console.log(hr);
|
|
||||||
|
|
||||||
// exit out of Rhino
|
/** Used as a horizontal rule in console output */
|
||||||
try {
|
var hr = '----------------------------------------';
|
||||||
quit();
|
|
||||||
} catch(e) { }
|
|
||||||
|
|
||||||
// exit out of Node.js
|
/** Shorten `window.QUnit.QUnit` to `window.QUnit` */
|
||||||
try {
|
window.QUnit && (QUnit = QUnit.QUnit || QUnit);
|
||||||
process.exit();
|
|
||||||
} catch(e) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A logging callback triggered after every assertion.
|
* A logging callback triggered when all testing is completed.
|
||||||
*
|
*
|
||||||
* @memberOf QUnit
|
* @memberOf QUnit
|
||||||
* @param {Object} details An object with properties `actual`, `expected`,
|
* @param {Object} details An object with properties `failed`, `passed`, `runtime`, and `total`.
|
||||||
* `message`, and `result`.
|
*/
|
||||||
*/
|
QUnit.done(function() {
|
||||||
function log(details) {
|
var ran;
|
||||||
var expected = details.expected,
|
return function(details) {
|
||||||
result = details.result,
|
// stop `asyncTest()` from erroneously calling `done()` twice in
|
||||||
type = typeof expected != 'undefined' ? 'EQ' : 'OK';
|
// environments w/o timeouts
|
||||||
|
if (ran) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ran = true;
|
||||||
|
|
||||||
var assertion = [
|
console.log(hr);
|
||||||
result ? 'PASS' : 'FAIL',
|
console.log(' PASS: ' + details.passed + ' FAIL: ' + details.failed + ' TOTAL: ' + details.total);
|
||||||
type,
|
console.log(' Finished in ' + details.runtime + ' milliseconds.');
|
||||||
details.message || 'ok'
|
console.log(hr);
|
||||||
];
|
|
||||||
|
|
||||||
if (!result && type == 'EQ') {
|
// exit out of Rhino
|
||||||
assertion.push('Expected: ' + expected + ', Actual: ' + details.actual);
|
try {
|
||||||
}
|
quit();
|
||||||
QUnit.config.testStats.assertions.push(assertion.join(' | '));
|
} catch(e) { }
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
// exit out of Node.js or PhantomJS
|
||||||
* A logging callback triggered at the start of every test module.
|
try {
|
||||||
*
|
var process = window.process || window.phantom;
|
||||||
* @memberOf QUnit
|
if (details.failed) {
|
||||||
* @param {Object} details An object with property `name`.
|
console.error('Error: ' + details.failed + ' of ' + details.total + ' tests failed.');
|
||||||
*/
|
process.exit(1);
|
||||||
function moduleStart(details) {
|
} else {
|
||||||
console.log(hr);
|
process.exit(0);
|
||||||
console.log(details.name);
|
}
|
||||||
console.log(hr);
|
} catch(e) { }
|
||||||
}
|
};
|
||||||
|
}());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an object into a string representation.
|
* A logging callback triggered after every assertion.
|
||||||
*
|
*
|
||||||
* @memberOf QUnit
|
* @memberOf QUnit
|
||||||
* @type Function
|
* @param {Object} details An object with properties `actual`, `expected`, `message`, and `result`.
|
||||||
* @param {Object} object The object to stringify.
|
*/
|
||||||
* @returns {String} The result string.
|
QUnit.log(function(details) {
|
||||||
*/
|
var expected = details.expected,
|
||||||
var parseObject = (function() {
|
result = details.result,
|
||||||
var func = QUnit.jsDump.parsers.object;
|
type = typeof expected != 'undefined' ? 'EQ' : 'OK';
|
||||||
return function(object) {
|
|
||||||
// fork to support Rhino's error objects
|
var assertion = [
|
||||||
if (typeof object.rhinoException == 'object') {
|
result ? 'PASS' : 'FAIL',
|
||||||
return object.name +
|
type,
|
||||||
' { message: "' + object.message +
|
details.message || 'ok'
|
||||||
'", fileName: "' + object.fileName +
|
];
|
||||||
'", lineNumber: ' + object.lineNumber + ' }';
|
|
||||||
|
if (!result && type == 'EQ') {
|
||||||
|
assertion.push('Expected: ' + expected + ', Actual: ' + details.actual);
|
||||||
}
|
}
|
||||||
return func(object);
|
QUnit.config.testStats.assertions.push(assertion.join(' | '));
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A logging callback triggered at the start of every test module.
|
||||||
|
*
|
||||||
|
* @memberOf QUnit
|
||||||
|
* @param {Object} details An object with property `name`.
|
||||||
|
*/
|
||||||
|
QUnit.moduleStart(function(details) {
|
||||||
|
console.log(hr);
|
||||||
|
console.log(details.name);
|
||||||
|
console.log(hr);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an object into a string representation.
|
||||||
|
*
|
||||||
|
* @memberOf QUnit
|
||||||
|
* @type Function
|
||||||
|
* @param {Object} object The object to stringify.
|
||||||
|
* @returns {String} The result string.
|
||||||
|
*/
|
||||||
|
QUnit.jsDump.parsers.object = (function() {
|
||||||
|
var func = QUnit.jsDump.parsers.object;
|
||||||
|
return function(object) {
|
||||||
|
// fork to support Rhino's error objects
|
||||||
|
if (typeof object.rhinoException == 'object') {
|
||||||
|
return object.name +
|
||||||
|
' { message: "' + object.message +
|
||||||
|
'", fileName: "' + object.fileName +
|
||||||
|
'", lineNumber: ' + object.lineNumber + ' }';
|
||||||
|
}
|
||||||
|
return func(object);
|
||||||
|
};
|
||||||
|
}());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A logging callback triggered after a test is completed.
|
||||||
|
*
|
||||||
|
* @memberOf QUnit
|
||||||
|
* @param {Object} details An object with properties `failed`, `name`, `passed`, and `total`.
|
||||||
|
*/
|
||||||
|
QUnit.testDone(function(details) {
|
||||||
|
var assertions = QUnit.config.testStats.assertions,
|
||||||
|
testName = details.name;
|
||||||
|
|
||||||
|
if (details.failed > 0) {
|
||||||
|
console.log(' FAIL - '+ testName);
|
||||||
|
assertions.forEach(function(value) {
|
||||||
|
console.log(' ' + value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(' PASS - ' + testName);
|
||||||
|
}
|
||||||
|
assertions.length = 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object used to hold information about the current running test.
|
||||||
|
*
|
||||||
|
* @memberOf QUnit.config
|
||||||
|
* @type Object
|
||||||
|
*/
|
||||||
|
QUnit.config.testStats = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of test summaries (pipe separated).
|
||||||
|
*
|
||||||
|
* @memberOf QUnit.config.testStats
|
||||||
|
* @type Array
|
||||||
|
*/
|
||||||
|
'assertions': []
|
||||||
};
|
};
|
||||||
}());
|
}());
|
||||||
|
|
||||||
/**
|
|
||||||
* A logging callback triggered after a test is completed.
|
|
||||||
*
|
|
||||||
* @memberOf QUnit
|
|
||||||
* @param {Object} details An object with properties `failed`, `name`,
|
|
||||||
* `passed`, and `total`.
|
|
||||||
*/
|
|
||||||
function testDone(details) {
|
|
||||||
var assertions = QUnit.config.testStats.assertions,
|
|
||||||
testName = details.name;
|
|
||||||
|
|
||||||
if (details.failed > 0) {
|
|
||||||
console.log(' FAIL - '+ testName);
|
|
||||||
each(assertions, function(value) {
|
|
||||||
console.log(' ' + value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(' PASS - ' + testName);
|
|
||||||
}
|
|
||||||
assertions.length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
// expose shortcuts
|
||||||
* An object used to hold information about the current running test.
|
|
||||||
*
|
|
||||||
* @memberOf QUnit.config
|
|
||||||
* @type Object
|
|
||||||
*/
|
|
||||||
QUnit.config.testStats = {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An array of test summaries (pipe separated).
|
|
||||||
*
|
|
||||||
* @memberOf QUnit.config.testStats
|
|
||||||
* @type Array
|
|
||||||
*/
|
|
||||||
'assertions': []
|
|
||||||
};
|
|
||||||
|
|
||||||
// add shortcuts to the global
|
|
||||||
// exclude `module` because some environments have it as a built-in object
|
// exclude `module` because some environments have it as a built-in object
|
||||||
each(['asyncTest', 'deepEqual', 'equal', 'equals', 'expect', 'notDeepEqual',
|
('asyncTest deepEqual equal equals expect notDeepEqual notEqual notStrictEqual ' +
|
||||||
'notEqual', 'notStrictEqual', 'ok', 'raises', 'same', 'start', 'stop',
|
'ok raises same start stop strictEqual test throws').replace(/\S+/g, function(methodName) {
|
||||||
'strictEqual', 'test', 'throws'], function(funcName) {
|
window[methodName] = QUnit[methodName];
|
||||||
var func = QUnit[funcName];
|
|
||||||
if (func) {
|
|
||||||
global[funcName] = func;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// expose timer methods to global
|
// add `console.log()` support for Narwhal, Rhino, and RingoJS
|
||||||
try {
|
if (!window.console && window.print) {
|
||||||
timer = new java.util.Timer;
|
window.console = { 'log': window.print };
|
||||||
if (!isFunction(global.clearInterval)) {
|
}
|
||||||
global.clearInterval = clearTimer;
|
|
||||||
}
|
|
||||||
if (!isFunction(global.clearTimeout)) {
|
|
||||||
global.clearTimeout = clearTimer;
|
|
||||||
}
|
|
||||||
if (!isFunction(global.setInterval)) {
|
|
||||||
global.setInterval = setInterval;
|
|
||||||
}
|
|
||||||
if (!isFunction(global.setTimeout)) {
|
|
||||||
global.setTimeout = setTimeout;
|
|
||||||
}
|
|
||||||
} catch(e) { }
|
|
||||||
|
|
||||||
// add callbacks
|
|
||||||
QUnit.done(done);
|
|
||||||
QUnit.log(log);
|
|
||||||
QUnit.moduleStart(moduleStart);
|
|
||||||
QUnit.testDone(testDone);
|
|
||||||
|
|
||||||
// add wrapped function
|
|
||||||
QUnit.jsDump.parsers.object = parseObject;
|
|
||||||
|
|
||||||
// must call `QUnit.start()` in the test file if using QUnit < 1.3.0 with
|
// must call `QUnit.start()` in the test file if using QUnit < 1.3.0 with
|
||||||
// Node.js or any version of QUnit with Narwhal, Rhino, or RingoJS
|
// Node.js or any version of QUnit with Narwhal, PhantomJS, Rhino, or RingoJS
|
||||||
QUnit.init();
|
QUnit.init();
|
||||||
|
|
||||||
}(typeof global == 'object' && global || this));
|
}(typeof global == 'object' && global || this));
|
||||||
|
|||||||
23
vendor/qunit/README.md
vendored
23
vendor/qunit/README.md
vendored
@@ -1,4 +1,4 @@
|
|||||||
[QUnit](http://docs.jquery.com/QUnit) - A JavaScript Unit Testing framework.
|
[QUnit](http://qunitjs.com) - A JavaScript Unit Testing framework.
|
||||||
================================
|
================================
|
||||||
|
|
||||||
QUnit is a powerful, easy-to-use, JavaScript test suite. It's used by the jQuery
|
QUnit is a powerful, easy-to-use, JavaScript test suite. It's used by the jQuery
|
||||||
@@ -23,9 +23,6 @@ If you are interested in helping developing QUnit, you are in the right place.
|
|||||||
For related discussions, visit the
|
For related discussions, visit the
|
||||||
[QUnit and Testing forum](http://forum.jquery.com/qunit-and-testing).
|
[QUnit and Testing forum](http://forum.jquery.com/qunit-and-testing).
|
||||||
|
|
||||||
Planning for a qunitjs.com site and other testing tools related work now happens
|
|
||||||
on the [jQuery Testing Team planning wiki](http://jquerytesting.pbworks.com/w/page/41556026/FrontPage).
|
|
||||||
|
|
||||||
Development
|
Development
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
@@ -35,7 +32,8 @@ the change, run `grunt` to lint and test it, then commit, push and create a pull
|
|||||||
Include some background for the change in the commit message and `Fixes #nnn`, referring
|
Include some background for the change in the commit message and `Fixes #nnn`, referring
|
||||||
to the issue number you're addressing.
|
to the issue number you're addressing.
|
||||||
|
|
||||||
To run `grunt`, you need `node` and `npm`, then `npm install grunt -g`.
|
To run `grunt`, you need `node` and `npm`, then `npm install grunt -g`. That gives you a global
|
||||||
|
grunt binary. For additional grunt tasks, also run `npm install`.
|
||||||
|
|
||||||
Releases
|
Releases
|
||||||
--------
|
--------
|
||||||
@@ -47,3 +45,18 @@ tag, update them again to the next version, commit and push commits and tags
|
|||||||
|
|
||||||
Put the 'v' in front of the tag, e.g. `v1.8.0`. Clean up the changelog, removing merge commits
|
Put the 'v' in front of the tag, e.g. `v1.8.0`. Clean up the changelog, removing merge commits
|
||||||
or whitespace cleanups.
|
or whitespace cleanups.
|
||||||
|
|
||||||
|
To upload to code.jquery.com (replace $version accordingly), ssh to code.origin.jquery.com:
|
||||||
|
|
||||||
|
cp qunit/qunit.js /var/www/html/code.jquery.com/qunit/qunit-$version.js
|
||||||
|
cp qunit/qunit.css /var/www/html/code.jquery.com/qunit/qunit-$version.css
|
||||||
|
|
||||||
|
Then update /var/www/html/code.jquery.com/index.html and purge it with:
|
||||||
|
|
||||||
|
curl -s http://code.origin.jquery.com/?reload
|
||||||
|
|
||||||
|
Update web-base-template to link to those files for qunitjs.com.
|
||||||
|
|
||||||
|
Publish to npm via
|
||||||
|
|
||||||
|
npm publish
|
||||||
|
|||||||
1863
vendor/qunit/qunit/qunit-1.8.0.js
vendored
1863
vendor/qunit/qunit/qunit-1.8.0.js
vendored
File diff suppressed because it is too large
Load Diff
27
vendor/qunit/qunit/qunit.css
vendored
27
vendor/qunit/qunit/qunit.css
vendored
@@ -1,11 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* QUnit v1.9.0 - A JavaScript Unit Testing Framework
|
* QUnit v1.11.0 - A JavaScript Unit Testing Framework
|
||||||
*
|
*
|
||||||
* http://docs.jquery.com/QUnit
|
* http://qunitjs.com
|
||||||
*
|
*
|
||||||
* Copyright (c) 2012 John Resig, Jörn Zaefferer
|
* Copyright 2012 jQuery Foundation and other contributors
|
||||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
* Released under the MIT license.
|
||||||
* or GPL (GPL-LICENSE.txt) licenses.
|
* http://jquery.org/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** Font Family and Sizes */
|
/** Font Family and Sizes */
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
/** Resets */
|
/** Resets */
|
||||||
|
|
||||||
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
|
#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
@@ -67,6 +67,7 @@
|
|||||||
padding: 0.5em 0 0.5em 2em;
|
padding: 0.5em 0 0.5em 2em;
|
||||||
color: #5E740B;
|
color: #5E740B;
|
||||||
background-color: #eee;
|
background-color: #eee;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-userAgent {
|
#qunit-userAgent {
|
||||||
@@ -76,6 +77,9 @@
|
|||||||
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
|
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#qunit-modulefilter-container {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
/** Tests: Pass/Fail */
|
/** Tests: Pass/Fail */
|
||||||
|
|
||||||
@@ -107,7 +111,12 @@
|
|||||||
color: #000;
|
color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
#qunit-tests ol {
|
#qunit-tests li .runtime {
|
||||||
|
float: right;
|
||||||
|
font-size: smaller;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qunit-assert-list {
|
||||||
margin-top: 0.5em;
|
margin-top: 0.5em;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
|
|
||||||
@@ -118,6 +127,10 @@
|
|||||||
-webkit-border-radius: 5px;
|
-webkit-border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.qunit-collapsed {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
#qunit-tests table {
|
#qunit-tests table {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
margin-top: .2em;
|
margin-top: .2em;
|
||||||
|
|||||||
564
vendor/qunit/qunit/qunit.js
vendored
564
vendor/qunit/qunit/qunit.js
vendored
File diff suppressed because it is too large
Load Diff
972
vendor/requirejs/require.js
vendored
972
vendor/requirejs/require.js
vendored
File diff suppressed because it is too large
Load Diff
4
vendor/underscore/LICENSE
vendored
4
vendor/underscore/LICENSE
vendored
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2009-2012 Jeremy Ashkenas, DocumentCloud
|
Copyright (c) 2009-2013 Jeremy Ashkenas, DocumentCloud
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
Permission is hereby granted, free of charge, to any person
|
||||||
obtaining a copy of this software and associated documentation
|
obtaining a copy of this software and associated documentation
|
||||||
@@ -19,4 +19,4 @@ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|||||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
OTHER DEALINGS IN THE SOFTWARE.
|
OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|||||||
78
vendor/underscore/test/arrays.js
vendored
78
vendor/underscore/test/arrays.js
vendored
@@ -2,7 +2,7 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
module("Arrays");
|
module("Arrays");
|
||||||
|
|
||||||
test("arrays: first", function() {
|
test("first", function() {
|
||||||
equal(_.first([1,2,3]), 1, 'can pull out the first element of an array');
|
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(_([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], 0).join(', '), "", 'can pass an index to first');
|
||||||
@@ -14,9 +14,11 @@ $(document).ready(function() {
|
|||||||
equal(result.join(','), '1,1', 'works well with _.map');
|
equal(result.join(','), '1,1', 'works well with _.map');
|
||||||
result = (function() { return _.take([1,2,3], 2); })();
|
result = (function() { return _.take([1,2,3], 2); })();
|
||||||
equal(result.join(','), '1,2', 'aliased as take');
|
equal(result.join(','), '1,2', 'aliased as take');
|
||||||
|
|
||||||
|
equal(_.first(null), undefined, 'handles nulls');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("arrays: rest", function() {
|
test("rest", function() {
|
||||||
var numbers = [1, 2, 3, 4];
|
var numbers = [1, 2, 3, 4];
|
||||||
equal(_.rest(numbers).join(", "), "2, 3, 4", 'working rest()');
|
equal(_.rest(numbers).join(", "), "2, 3, 4", 'working rest()');
|
||||||
equal(_.rest(numbers, 0).join(", "), "1, 2, 3, 4", 'working rest(0)');
|
equal(_.rest(numbers, 0).join(", "), "1, 2, 3, 4", 'working rest(0)');
|
||||||
@@ -25,9 +27,11 @@ $(document).ready(function() {
|
|||||||
equal(result.join(', '), '2, 3, 4', 'aliased as tail and works on arguments object');
|
equal(result.join(', '), '2, 3, 4', 'aliased as tail and works on arguments object');
|
||||||
result = _.map([[1,2,3],[1,2,3]], _.rest);
|
result = _.map([[1,2,3],[1,2,3]], _.rest);
|
||||||
equal(_.flatten(result).join(','), '2,3,2,3', 'works well with _.map');
|
equal(_.flatten(result).join(','), '2,3,2,3', 'works well with _.map');
|
||||||
|
result = (function(){ return _(arguments).drop(); })(1, 2, 3, 4);
|
||||||
|
equal(result.join(', '), '2, 3, 4', 'aliased as drop and works on arguments object');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("arrays: initial", function() {
|
test("initial", function() {
|
||||||
equal(_.initial([1,2,3,4,5]).join(", "), "1, 2, 3, 4", 'working initial()');
|
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');
|
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);
|
var result = (function(){ return _(arguments).initial(); })(1, 2, 3, 4);
|
||||||
@@ -36,7 +40,7 @@ $(document).ready(function() {
|
|||||||
equal(_.flatten(result).join(','), '1,2,1,2', 'initial works with _.map');
|
equal(_.flatten(result).join(','), '1,2,1,2', 'initial works with _.map');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("arrays: last", function() {
|
test("last", function() {
|
||||||
equal(_.last([1,2,3]), 3, 'can pull out the last element of an array');
|
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], 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], 2).join(', '), '2, 3', 'can pass an index to last');
|
||||||
@@ -45,25 +49,25 @@ $(document).ready(function() {
|
|||||||
equal(result, 4, 'works on an arguments object');
|
equal(result, 4, 'works on an arguments object');
|
||||||
result = _.map([[1,2,3],[1,2,3]], _.last);
|
result = _.map([[1,2,3],[1,2,3]], _.last);
|
||||||
equal(result.join(','), '3,3', 'works well with _.map');
|
equal(result.join(','), '3,3', 'works well with _.map');
|
||||||
|
|
||||||
|
equal(_.last(null), undefined, 'handles nulls');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("arrays: compact", function() {
|
test("compact", function() {
|
||||||
equal(_.compact([0, 1, false, 2, false, 3]).length, 3, 'can trim out all falsy values');
|
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);
|
var result = (function(){ return _.compact(arguments).length; })(0, 1, false, 2, false, 3);
|
||||||
equal(result, 3, 'works on an arguments object');
|
equal(result, 3, 'works on an arguments object');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("arrays: flatten", function() {
|
test("flatten", function() {
|
||||||
if (window.JSON) {
|
var list = [1, [2], [3, [[[4]]]]];
|
||||||
var list = [1, [2], [3, [[[4]]]]];
|
deepEqual(_.flatten(list), [1,2,3,4], 'can flatten nested arrays');
|
||||||
equal(JSON.stringify(_.flatten(list)), '[1,2,3,4]', 'can flatten nested arrays');
|
deepEqual(_.flatten(list, true), [1,2,3,[[[4]]]], 'can shallowly 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]]]]);
|
||||||
var result = (function(){ return _.flatten(arguments); })(1, [2], [3, [[[4]]]]);
|
deepEqual(result, [1,2,3,4], 'works on an arguments object');
|
||||||
equal(JSON.stringify(result), '[1,2,3,4]', 'works on an arguments object');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("arrays: without", function() {
|
test("without", function() {
|
||||||
var list = [1, 2, 1, 0, 3, 1, 4];
|
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');
|
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);
|
var result = (function(){ return _.without(arguments, 0, 1); })(1, 2, 1, 0, 3, 1, 4);
|
||||||
@@ -74,7 +78,7 @@ $(document).ready(function() {
|
|||||||
ok(_.without(list, list[0]).length == 1, 'ditto.');
|
ok(_.without(list, list[0]).length == 1, 'ditto.');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("arrays: uniq", function() {
|
test("uniq", function() {
|
||||||
var list = [1, 2, 1, 3, 1, 4];
|
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');
|
equal(_.uniq(list).join(', '), '1, 2, 3, 4', 'can find the unique values of an unsorted array');
|
||||||
|
|
||||||
@@ -85,6 +89,8 @@ $(document).ready(function() {
|
|||||||
var iterator = function(value) { return value.name; };
|
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');
|
equal(_.map(_.uniq(list, false, iterator), iterator).join(', '), 'moe, curly, larry', 'can find the unique values of an array using a custom iterator');
|
||||||
|
|
||||||
|
equal(_.map(_.uniq(list, iterator), iterator).join(', '), 'moe, curly, larry', 'can find the unique values of an array using a custom iterator without specifying whether array is sorted');
|
||||||
|
|
||||||
var iterator = function(value) { return value +1; };
|
var iterator = function(value) { return value +1; };
|
||||||
var list = [1, 2, 2, 3, 4, 4];
|
var list = [1, 2, 2, 3, 4, 4];
|
||||||
equal(_.uniq(list, true, iterator).join(', '), '1, 2, 3, 4', 'iterator works with sorted array');
|
equal(_.uniq(list, true, iterator).join(', '), '1, 2, 3, 4', 'iterator works with sorted array');
|
||||||
@@ -93,7 +99,7 @@ $(document).ready(function() {
|
|||||||
equal(result.join(', '), '1, 2, 3, 4', 'works on an arguments object');
|
equal(result.join(', '), '1, 2, 3, 4', 'works on an arguments object');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("arrays: intersection", function() {
|
test("intersection", function() {
|
||||||
var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho'];
|
var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho'];
|
||||||
equal(_.intersection(stooges, leaders).join(''), 'moe', 'can take the set intersection of two arrays');
|
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');
|
equal(_(stooges).intersection(leaders).join(''), 'moe', 'can perform an OO-style intersection');
|
||||||
@@ -101,7 +107,7 @@ $(document).ready(function() {
|
|||||||
equal(result.join(''), 'moe', 'works on an arguments object');
|
equal(result.join(''), 'moe', 'works on an arguments object');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("arrays: union", function() {
|
test("union", function() {
|
||||||
var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]);
|
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');
|
equal(result.join(' '), '1 2 3 30 40', 'takes the union of a list of arrays');
|
||||||
|
|
||||||
@@ -109,7 +115,7 @@ $(document).ready(function() {
|
|||||||
equal(result.join(' '), '1 2 3 30 40 1', 'takes the union of a list of nested arrays');
|
equal(result.join(' '), '1 2 3 30 40 1', 'takes the union of a list of nested arrays');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("arrays: difference", function() {
|
test("difference", function() {
|
||||||
var result = _.difference([1, 2, 3], [2, 30, 40]);
|
var result = _.difference([1, 2, 3], [2, 30, 40]);
|
||||||
equal(result.join(' '), '1 3', 'takes the difference of two arrays');
|
equal(result.join(' '), '1 3', 'takes the difference of two arrays');
|
||||||
|
|
||||||
@@ -117,19 +123,28 @@ $(document).ready(function() {
|
|||||||
equal(result.join(' '), '3 4', 'takes the difference of three arrays');
|
equal(result.join(' '), '3 4', 'takes the difference of three arrays');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('arrays: zip', function() {
|
test('zip', function() {
|
||||||
var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true];
|
var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true];
|
||||||
var stooges = _.zip(names, ages, leaders);
|
var stooges = _.zip(names, ages, leaders);
|
||||||
equal(String(stooges), 'moe,30,true,larry,40,,curly,50,', 'zipped together arrays of different lengths');
|
equal(String(stooges), 'moe,30,true,larry,40,,curly,50,', 'zipped together arrays of different lengths');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('arrays: zipObject', function() {
|
test('object', function() {
|
||||||
var result = _.zipObject(['moe', 'larry', 'curly'], [30, 40, 50]);
|
var result = _.object(['moe', 'larry', 'curly'], [30, 40, 50]);
|
||||||
var shouldBe = {moe: 30, larry: 40, curly: 50};
|
var shouldBe = {moe: 30, larry: 40, curly: 50};
|
||||||
ok(_.isEqual(result, shouldBe), 'two arrays zipped together into an object');
|
ok(_.isEqual(result, shouldBe), 'two arrays zipped together into an object');
|
||||||
|
|
||||||
|
result = _.object([['one', 1], ['two', 2], ['three', 3]]);
|
||||||
|
shouldBe = {one: 1, two: 2, three: 3};
|
||||||
|
ok(_.isEqual(result, shouldBe), 'an array of pairs zipped together into an object');
|
||||||
|
|
||||||
|
var stooges = {moe: 30, larry: 40, curly: 50};
|
||||||
|
ok(_.isEqual(_.object(_.pairs(stooges)), stooges), 'an object converted to pairs and back to an object');
|
||||||
|
|
||||||
|
ok(_.isEqual(_.object(null), {}), 'handles nulls');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("arrays: indexOf", function() {
|
test("indexOf", function() {
|
||||||
var numbers = [1, 2, 3];
|
var numbers = [1, 2, 3];
|
||||||
numbers.indexOf = null;
|
numbers.indexOf = null;
|
||||||
equal(_.indexOf(numbers, 2), 1, 'can compute indexOf, even without the native function');
|
equal(_.indexOf(numbers, 2), 1, 'can compute indexOf, even without the native function');
|
||||||
@@ -148,19 +163,30 @@ $(document).ready(function() {
|
|||||||
numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40;
|
numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40;
|
||||||
index = _.indexOf(numbers, num, true);
|
index = _.indexOf(numbers, num, true);
|
||||||
equal(index, 1, '40 is in the list');
|
equal(index, 1, '40 is in the list');
|
||||||
|
|
||||||
|
numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];
|
||||||
|
index = _.indexOf(numbers, 2, 5);
|
||||||
|
equal(index, 7, 'supports the fromIndex argument');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("arrays: lastIndexOf", function() {
|
test("lastIndexOf", function() {
|
||||||
var numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0];
|
var numbers = [1, 0, 1];
|
||||||
|
equal(_.lastIndexOf(numbers, 1), 2);
|
||||||
|
|
||||||
|
numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0];
|
||||||
numbers.lastIndexOf = null;
|
numbers.lastIndexOf = null;
|
||||||
equal(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function');
|
equal(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function');
|
||||||
equal(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element');
|
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);
|
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(result, 5, 'works on an arguments object');
|
||||||
equal(_.indexOf(null, 2), -1, 'handles nulls properly');
|
equal(_.indexOf(null, 2), -1, 'handles nulls properly');
|
||||||
|
|
||||||
|
numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];
|
||||||
|
var index = _.lastIndexOf(numbers, 2, 2);
|
||||||
|
equal(index, 1, 'supports the fromIndex argument');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("arrays: range", function() {
|
test("range", function() {
|
||||||
equal(_.range(0).join(''), '', 'range with 0 as a first argument generates an empty array');
|
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(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 & b, a<b generates an array of elements a,a+1,a+2,...,b-2,b-1');
|
equal(_.range(5, 8).join(' '), '5 6 7', 'range with two arguments a & b, a<b generates an array of elements a,a+1,a+2,...,b-2,b-1');
|
||||||
|
|||||||
8
vendor/underscore/test/chaining.js
vendored
8
vendor/underscore/test/chaining.js
vendored
@@ -2,7 +2,7 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
module("Chaining");
|
module("Chaining");
|
||||||
|
|
||||||
test("chaining: map/flatten/reduce", function() {
|
test("map/flatten/reduce", function() {
|
||||||
var lyrics = [
|
var lyrics = [
|
||||||
"I'm a lumberjack and I'm okay",
|
"I'm a lumberjack and I'm okay",
|
||||||
"I sleep all night and I work all day",
|
"I sleep all night and I work all day",
|
||||||
@@ -20,7 +20,7 @@ $(document).ready(function() {
|
|||||||
ok(counts['a'] == 16 && counts['e'] == 10, 'counted all the letters in the song');
|
ok(counts['a'] == 16 && counts['e'] == 10, 'counted all the letters in the song');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("chaining: select/reject/sortBy", function() {
|
test("select/reject/sortBy", function() {
|
||||||
var numbers = [1,2,3,4,5,6,7,8,9,10];
|
var numbers = [1,2,3,4,5,6,7,8,9,10];
|
||||||
numbers = _(numbers).chain().select(function(n) {
|
numbers = _(numbers).chain().select(function(n) {
|
||||||
return n % 2 == 0;
|
return n % 2 == 0;
|
||||||
@@ -32,7 +32,7 @@ $(document).ready(function() {
|
|||||||
equal(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers");
|
equal(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("chaining: select/reject/sortBy in functional style", function() {
|
test("select/reject/sortBy in functional style", function() {
|
||||||
var numbers = [1,2,3,4,5,6,7,8,9,10];
|
var numbers = [1,2,3,4,5,6,7,8,9,10];
|
||||||
numbers = _.chain(numbers).select(function(n) {
|
numbers = _.chain(numbers).select(function(n) {
|
||||||
return n % 2 == 0;
|
return n % 2 == 0;
|
||||||
@@ -44,7 +44,7 @@ $(document).ready(function() {
|
|||||||
equal(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers");
|
equal(numbers.join(', '), "10, 6, 2", "filtered and reversed the numbers");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("chaining: reverse/concat/unshift/pop/map", function() {
|
test("reverse/concat/unshift/pop/map", function() {
|
||||||
var numbers = [1,2,3,4,5];
|
var numbers = [1,2,3,4,5];
|
||||||
numbers = _(numbers).chain()
|
numbers = _(numbers).chain()
|
||||||
.reverse()
|
.reverse()
|
||||||
|
|||||||
219
vendor/underscore/test/collections.js
vendored
219
vendor/underscore/test/collections.js
vendored
@@ -2,7 +2,7 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
module("Collections");
|
module("Collections");
|
||||||
|
|
||||||
test("collections: each", function() {
|
test("each", function() {
|
||||||
_.each([1, 2, 3], function(num, i) {
|
_.each([1, 2, 3], function(num, i) {
|
||||||
equal(num, i + 1, 'each iterators provide value and iteration count');
|
equal(num, i + 1, 'each iterators provide value and iteration count');
|
||||||
});
|
});
|
||||||
@@ -22,7 +22,7 @@ $(document).ready(function() {
|
|||||||
equal(answers.join(", "), 'one, two, three', 'iterating over objects works, and ignores the object prototype.');
|
equal(answers.join(", "), 'one, two, three', 'iterating over objects works, and ignores the object prototype.');
|
||||||
delete obj.constructor.prototype.four;
|
delete obj.constructor.prototype.four;
|
||||||
|
|
||||||
answer = null;
|
var answer = null;
|
||||||
_.each([1, 2, 3], function(num, index, arr){ if (_.include(arr, num)) answer = true; });
|
_.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');
|
ok(answer, 'can reference the original collection from inside the iterator');
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ $(document).ready(function() {
|
|||||||
equal(answers, 0, 'handles a null properly');
|
equal(answers, 0, 'handles a null properly');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: map', function() {
|
test('map', function() {
|
||||||
var doubled = _.map([1, 2, 3], function(num){ return num * 2; });
|
var doubled = _.map([1, 2, 3], function(num){ return num * 2; });
|
||||||
equal(doubled.join(', '), '2, 4, 6', 'doubled numbers');
|
equal(doubled.join(', '), '2, 4, 6', 'doubled numbers');
|
||||||
|
|
||||||
@@ -44,8 +44,13 @@ $(document).ready(function() {
|
|||||||
var doubled = _([1, 2, 3]).map(function(num){ return num * 2; });
|
var doubled = _([1, 2, 3]).map(function(num){ return num * 2; });
|
||||||
equal(doubled.join(', '), '2, 4, 6', 'OO-style doubled numbers');
|
equal(doubled.join(', '), '2, 4, 6', 'OO-style doubled numbers');
|
||||||
|
|
||||||
|
if (document.querySelectorAll) {
|
||||||
|
var ids = _.map(document.querySelectorAll('#map-test *'), function(n){ return n.id; });
|
||||||
|
deepEqual(ids, ['id1', 'id2'], 'Can use collection methods on NodeLists.');
|
||||||
|
}
|
||||||
|
|
||||||
var ids = _.map($('#map-test').children(), function(n){ return n.id; });
|
var ids = _.map($('#map-test').children(), function(n){ return n.id; });
|
||||||
deepEqual(ids, ['id1', 'id2'], 'Can use collection methods on NodeLists.');
|
deepEqual(ids, ['id1', 'id2'], 'Can use collection methods on jQuery Array-likes.');
|
||||||
|
|
||||||
var ids = _.map(document.images, function(n){ return n.id; });
|
var ids = _.map(document.images, function(n){ return n.id; });
|
||||||
ok(ids[0] == 'chart_image', 'can use collection methods on HTMLCollections');
|
ok(ids[0] == 'chart_image', 'can use collection methods on HTMLCollections');
|
||||||
@@ -54,7 +59,7 @@ $(document).ready(function() {
|
|||||||
ok(_.isArray(ifnull) && ifnull.length === 0, 'handles a null properly');
|
ok(_.isArray(ifnull) && ifnull.length === 0, 'handles a null properly');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: reduce', function() {
|
test('reduce', function() {
|
||||||
var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; }, 0);
|
var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; }, 0);
|
||||||
equal(sum, 6, 'can sum up an array');
|
equal(sum, 6, 'can sum up an array');
|
||||||
|
|
||||||
@@ -84,7 +89,7 @@ $(document).ready(function() {
|
|||||||
raises(function() { _.reduce([], function(){}); }, TypeError, 'throws an error for empty arrays with no initial value');
|
raises(function() { _.reduce([], function(){}); }, TypeError, 'throws an error for empty arrays with no initial value');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: reduceRight', function() {
|
test('reduceRight', function() {
|
||||||
var list = _.reduceRight(["foo", "bar", "baz"], function(memo, str){ return memo + str; }, '');
|
var list = _.reduceRight(["foo", "bar", "baz"], function(memo, str){ return memo + str; }, '');
|
||||||
equal(list, 'bazbarfoo', 'can perform right folds');
|
equal(list, 'bazbarfoo', 'can perform right folds');
|
||||||
|
|
||||||
@@ -102,24 +107,60 @@ $(document).ready(function() {
|
|||||||
}
|
}
|
||||||
ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly');
|
ok(ifnull instanceof TypeError, 'handles a null (without inital value) properly');
|
||||||
|
|
||||||
|
var sum = _.reduceRight({a: 1, b: 2, c: 3}, function(sum, num){ return sum + num; });
|
||||||
|
equal(sum, 6, 'default initial value on object');
|
||||||
|
|
||||||
ok(_.reduceRight(null, function(){}, 138) === 138, 'handles a null (with initial 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');
|
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');
|
raises(function() { _.reduceRight([], function(){}); }, TypeError, 'throws an error for empty arrays with no initial value');
|
||||||
|
|
||||||
|
// Assert that the correct arguments are being passed.
|
||||||
|
|
||||||
|
var args,
|
||||||
|
memo = {},
|
||||||
|
object = {a: 1, b: 2},
|
||||||
|
lastKey = _.keys(object).pop();
|
||||||
|
|
||||||
|
var expected = lastKey == 'a'
|
||||||
|
? [memo, 1, 'a', object]
|
||||||
|
: [memo, 2, 'b', object];
|
||||||
|
|
||||||
|
_.reduceRight(object, function() {
|
||||||
|
args || (args = _.toArray(arguments));
|
||||||
|
}, memo);
|
||||||
|
|
||||||
|
deepEqual(args, expected);
|
||||||
|
|
||||||
|
// And again, with numeric keys.
|
||||||
|
|
||||||
|
object = {'2': 'a', '1': 'b'};
|
||||||
|
lastKey = _.keys(object).pop();
|
||||||
|
args = null;
|
||||||
|
|
||||||
|
expected = lastKey == '2'
|
||||||
|
? [memo, 'a', '2', object]
|
||||||
|
: [memo, 'b', '1', object];
|
||||||
|
|
||||||
|
_.reduceRight(object, function() {
|
||||||
|
args || (args = _.toArray(arguments));
|
||||||
|
}, memo);
|
||||||
|
|
||||||
|
deepEqual(args, expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: find', function() {
|
test('find', function() {
|
||||||
var array = [1, 2, 3, 4];
|
var array = [1, 2, 3, 4];
|
||||||
strictEqual(_.find(array, function(n) { return n > 2; }), 3, 'should return first found `value`');
|
strictEqual(_.find(array, function(n) { return n > 2; }), 3, 'should return first found `value`');
|
||||||
strictEqual(_.find(array, function() { return false; }), void 0, 'should return `undefined` if `value` is not found');
|
strictEqual(_.find(array, function() { return false; }), void 0, 'should return `undefined` if `value` is not found');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: detect', function() {
|
test('detect', function() {
|
||||||
var result = _.detect([1, 2, 3], function(num){ return num * 2 == 4; });
|
var result = _.detect([1, 2, 3], function(num){ return num * 2 == 4; });
|
||||||
equal(result, 2, 'found the first "2" and broke the loop');
|
equal(result, 2, 'found the first "2" and broke the loop');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: select', function() {
|
test('select', function() {
|
||||||
var evens = _.select([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
|
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');
|
equal(evens.join(', '), '2, 4, 6', 'selected each even number');
|
||||||
|
|
||||||
@@ -127,12 +168,20 @@ $(document).ready(function() {
|
|||||||
equal(evens.join(', '), '2, 4, 6', 'aliased as "filter"');
|
equal(evens.join(', '), '2, 4, 6', 'aliased as "filter"');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: reject', function() {
|
test('reject', function() {
|
||||||
var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });
|
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');
|
equal(odds.join(', '), '1, 3, 5', 'rejected each even number');
|
||||||
|
|
||||||
|
var context = "obj";
|
||||||
|
|
||||||
|
var evens = _.reject([1, 2, 3, 4, 5, 6], function(num){
|
||||||
|
equal(context, "obj");
|
||||||
|
return num % 2 != 0;
|
||||||
|
}, context);
|
||||||
|
equal(evens.join(', '), '2, 4, 6', 'rejected each odd number');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: all', function() {
|
test('all', function() {
|
||||||
ok(_.all([], _.identity), 'the empty set');
|
ok(_.all([], _.identity), 'the empty set');
|
||||||
ok(_.all([true, true, true], _.identity), 'all true values');
|
ok(_.all([true, true, true], _.identity), 'all true values');
|
||||||
ok(!_.all([true, false, true], _.identity), 'one false value');
|
ok(!_.all([true, false, true], _.identity), 'one false value');
|
||||||
@@ -141,9 +190,10 @@ $(document).ready(function() {
|
|||||||
ok(_.all([1], _.identity) === true, 'cast to boolean - true');
|
ok(_.all([1], _.identity) === true, 'cast to boolean - true');
|
||||||
ok(_.all([0], _.identity) === false, 'cast to boolean - false');
|
ok(_.all([0], _.identity) === false, 'cast to boolean - false');
|
||||||
ok(_.every([true, true, true], _.identity), 'aliased as "every"');
|
ok(_.every([true, true, true], _.identity), 'aliased as "every"');
|
||||||
|
ok(!_.all([undefined, undefined, undefined], _.identity), 'works with arrays of undefined');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: any', function() {
|
test('any', function() {
|
||||||
var nativeSome = Array.prototype.some;
|
var nativeSome = Array.prototype.some;
|
||||||
Array.prototype.some = null;
|
Array.prototype.some = null;
|
||||||
ok(!_.any([]), 'the empty set');
|
ok(!_.any([]), 'the empty set');
|
||||||
@@ -159,21 +209,21 @@ $(document).ready(function() {
|
|||||||
Array.prototype.some = nativeSome;
|
Array.prototype.some = nativeSome;
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: include', function() {
|
test('include', function() {
|
||||||
ok(_.include([1,2,3], 2), 'two is in the array');
|
ok(_.include([1,2,3], 2), 'two is in the array');
|
||||||
ok(!_.include([1,3,9], 2), 'two is not 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(_.contains({moe:1, larry:3, curly:9}, 3) === true, '_.include on objects checks their values');
|
||||||
ok(_([1,2,3]).include(2), 'OO-style include');
|
ok(_([1,2,3]).include(2), 'OO-style include');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: invoke', function() {
|
test('invoke', function() {
|
||||||
var list = [[5, 1, 7], [3, 2, 1]];
|
var list = [[5, 1, 7], [3, 2, 1]];
|
||||||
var result = _.invoke(list, 'sort');
|
var result = _.invoke(list, 'sort');
|
||||||
equal(result[0].join(', '), '1, 5, 7', 'first array sorted');
|
equal(result[0].join(', '), '1, 5, 7', 'first array sorted');
|
||||||
equal(result[1].join(', '), '1, 2, 3', 'second array sorted');
|
equal(result[1].join(', '), '1, 2, 3', 'second array sorted');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: invoke w/ function reference', function() {
|
test('invoke w/ function reference', function() {
|
||||||
var list = [[5, 1, 7], [3, 2, 1]];
|
var list = [[5, 1, 7], [3, 2, 1]];
|
||||||
var result = _.invoke(list, Array.prototype.sort);
|
var result = _.invoke(list, Array.prototype.sort);
|
||||||
equal(result[0].join(', '), '1, 5, 7', 'first array sorted');
|
equal(result[0].join(', '), '1, 5, 7', 'first array sorted');
|
||||||
@@ -181,7 +231,7 @@ $(document).ready(function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Relevant when using ClojureScript
|
// Relevant when using ClojureScript
|
||||||
test('collections: invoke when strings have a call method', function() {
|
test('invoke when strings have a call method', function() {
|
||||||
String.prototype.call = function() {
|
String.prototype.call = function() {
|
||||||
return 42;
|
return 42;
|
||||||
};
|
};
|
||||||
@@ -195,12 +245,30 @@ $(document).ready(function() {
|
|||||||
equal(s.call, undefined, "call function removed");
|
equal(s.call, undefined, "call function removed");
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: pluck', function() {
|
test('pluck', function() {
|
||||||
var people = [{name : 'moe', age : 30}, {name : 'curly', age : 50}];
|
var people = [{name : 'moe', age : 30}, {name : 'curly', age : 50}];
|
||||||
equal(_.pluck(people, 'name').join(', '), 'moe, curly', 'pulls names out of objects');
|
equal(_.pluck(people, 'name').join(', '), 'moe, curly', 'pulls names out of objects');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: max', function() {
|
test('where', function() {
|
||||||
|
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}];
|
||||||
|
var result = _.where(list, {a: 1});
|
||||||
|
equal(result.length, 3);
|
||||||
|
equal(result[result.length - 1].b, 4);
|
||||||
|
result = _.where(list, {b: 2});
|
||||||
|
equal(result.length, 2);
|
||||||
|
equal(result[0].a, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('findWhere', function() {
|
||||||
|
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b: 4}];
|
||||||
|
var result = _.findWhere(list, {a: 1});
|
||||||
|
deepEqual(result, {a: 1, b: 2});
|
||||||
|
result = _.findWhere(list, {b: 4});
|
||||||
|
deepEqual(result, {a: 1, b: 4});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('max', function() {
|
||||||
equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max');
|
equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max');
|
||||||
|
|
||||||
var neg = _.max([1, 2, 3], function(num){ return -num; });
|
var neg = _.max([1, 2, 3], function(num){ return -num; });
|
||||||
@@ -208,11 +276,12 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
equal(-Infinity, _.max({}), 'Maximum value of an empty object');
|
equal(-Infinity, _.max({}), 'Maximum value of an empty object');
|
||||||
equal(-Infinity, _.max([]), 'Maximum value of an empty array');
|
equal(-Infinity, _.max([]), 'Maximum value of an empty array');
|
||||||
|
equal(_.max({'a': 'a'}), -Infinity, 'Maximum value of a non-numeric collection');
|
||||||
|
|
||||||
equal(299999, _.max(_.range(1,300000)), "Maximum value of a too-big array");
|
equal(299999, _.max(_.range(1,300000)), "Maximum value of a too-big array");
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: min', function() {
|
test('min', function() {
|
||||||
equal(1, _.min([1, 2, 3]), 'can perform a regular Math.min');
|
equal(1, _.min([1, 2, 3]), 'can perform a regular Math.min');
|
||||||
|
|
||||||
var neg = _.min([1, 2, 3], function(num){ return -num; });
|
var neg = _.min([1, 2, 3], function(num){ return -num; });
|
||||||
@@ -220,6 +289,7 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
equal(Infinity, _.min({}), 'Minimum value of an empty object');
|
equal(Infinity, _.min({}), 'Minimum value of an empty object');
|
||||||
equal(Infinity, _.min([]), 'Minimum value of an empty array');
|
equal(Infinity, _.min([]), 'Minimum value of an empty array');
|
||||||
|
equal(_.min({'a': 'a'}), Infinity, 'Minimum value of a non-numeric collection');
|
||||||
|
|
||||||
var now = new Date(9999999999);
|
var now = new Date(9999999999);
|
||||||
var then = new Date(0);
|
var then = new Date(0);
|
||||||
@@ -228,7 +298,7 @@ $(document).ready(function() {
|
|||||||
equal(1, _.min(_.range(1,300000)), "Minimum value of a too-big array");
|
equal(1, _.min(_.range(1,300000)), "Minimum value of a too-big array");
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: sortBy', function() {
|
test('sortBy', function() {
|
||||||
var people = [{name : 'curly', age : 50}, {name : 'moe', age : 30}];
|
var people = [{name : 'curly', age : 50}, {name : 'moe', age : 30}];
|
||||||
people = _.sortBy(people, function(person){ return person.age; });
|
people = _.sortBy(people, function(person){ return person.age; });
|
||||||
equal(_.pluck(people, 'name').join(', '), 'moe, curly', 'stooges sorted by age');
|
equal(_.pluck(people, 'name').join(', '), 'moe, curly', 'stooges sorted by age');
|
||||||
@@ -239,9 +309,32 @@ $(document).ready(function() {
|
|||||||
var list = ["one", "two", "three", "four", "five"];
|
var list = ["one", "two", "three", "four", "five"];
|
||||||
var sorted = _.sortBy(list, 'length');
|
var sorted = _.sortBy(list, 'length');
|
||||||
equal(sorted.join(' '), 'one two four five three', 'sorted by length');
|
equal(sorted.join(' '), 'one two four five three', 'sorted by length');
|
||||||
|
|
||||||
|
function Pair(x, y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
var collection = [
|
||||||
|
new Pair(1, 1), new Pair(1, 2),
|
||||||
|
new Pair(1, 3), new Pair(1, 4),
|
||||||
|
new Pair(1, 5), new Pair(1, 6),
|
||||||
|
new Pair(2, 1), new Pair(2, 2),
|
||||||
|
new Pair(2, 3), new Pair(2, 4),
|
||||||
|
new Pair(2, 5), new Pair(2, 6),
|
||||||
|
new Pair(undefined, 1), new Pair(undefined, 2),
|
||||||
|
new Pair(undefined, 3), new Pair(undefined, 4),
|
||||||
|
new Pair(undefined, 5), new Pair(undefined, 6)
|
||||||
|
];
|
||||||
|
|
||||||
|
var actual = _.sortBy(collection, function(pair) {
|
||||||
|
return pair.x;
|
||||||
|
});
|
||||||
|
|
||||||
|
deepEqual(actual, collection, 'sortBy should be stable');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: groupBy', function() {
|
test('groupBy', function() {
|
||||||
var parity = _.groupBy([1, 2, 3, 4, 5, 6], function(num){ return num % 2; });
|
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');
|
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');
|
equal(parity[0].join(', '), '2, 4, 6', 'put each even number in the right group');
|
||||||
@@ -251,25 +344,80 @@ $(document).ready(function() {
|
|||||||
equal(grouped['3'].join(' '), 'one two six ten');
|
equal(grouped['3'].join(' '), 'one two six ten');
|
||||||
equal(grouped['4'].join(' '), 'four five nine');
|
equal(grouped['4'].join(' '), 'four five nine');
|
||||||
equal(grouped['5'].join(' '), 'three seven eight');
|
equal(grouped['5'].join(' '), 'three seven eight');
|
||||||
|
|
||||||
|
var context = {};
|
||||||
|
_.groupBy([{}], function(){ ok(this === context); }, context);
|
||||||
|
|
||||||
|
grouped = _.groupBy([4.2, 6.1, 6.4], function(num) {
|
||||||
|
return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor';
|
||||||
|
});
|
||||||
|
equal(grouped.constructor.length, 1);
|
||||||
|
equal(grouped.hasOwnProperty.length, 2);
|
||||||
|
|
||||||
|
var array = [{}];
|
||||||
|
_.groupBy(array, function(value, index, obj){ ok(obj === array); });
|
||||||
|
|
||||||
|
var array = [1, 2, 1, 2, 3];
|
||||||
|
var grouped = _.groupBy(array);
|
||||||
|
equal(grouped['1'].length, 2);
|
||||||
|
equal(grouped['3'].length, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: sortedIndex', function() {
|
test('countBy', function() {
|
||||||
|
var parity = _.countBy([1, 2, 3, 4, 5], function(num){ return num % 2 == 0; });
|
||||||
|
equal(parity['true'], 2);
|
||||||
|
equal(parity['false'], 3);
|
||||||
|
|
||||||
|
var list = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"];
|
||||||
|
var grouped = _.countBy(list, 'length');
|
||||||
|
equal(grouped['3'], 4);
|
||||||
|
equal(grouped['4'], 3);
|
||||||
|
equal(grouped['5'], 3);
|
||||||
|
|
||||||
|
var context = {};
|
||||||
|
_.countBy([{}], function(){ ok(this === context); }, context);
|
||||||
|
|
||||||
|
grouped = _.countBy([4.2, 6.1, 6.4], function(num) {
|
||||||
|
return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor';
|
||||||
|
});
|
||||||
|
equal(grouped.constructor, 1);
|
||||||
|
equal(grouped.hasOwnProperty, 2);
|
||||||
|
|
||||||
|
var array = [{}];
|
||||||
|
_.countBy(array, function(value, index, obj){ ok(obj === array); });
|
||||||
|
|
||||||
|
var array = [1, 2, 1, 2, 3];
|
||||||
|
var grouped = _.countBy(array);
|
||||||
|
equal(grouped['1'], 2);
|
||||||
|
equal(grouped['3'], 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sortedIndex', function() {
|
||||||
var numbers = [10, 20, 30, 40, 50], num = 35;
|
var numbers = [10, 20, 30, 40, 50], num = 35;
|
||||||
var indexForNum = _.sortedIndex(numbers, num);
|
var indexForNum = _.sortedIndex(numbers, num);
|
||||||
equal(indexForNum, 3, '35 should be inserted at index 3');
|
equal(indexForNum, 3, '35 should be inserted at index 3');
|
||||||
|
|
||||||
var indexFor30 = _.sortedIndex(numbers, 30);
|
var indexFor30 = _.sortedIndex(numbers, 30);
|
||||||
equal(indexFor30, 2, '30 should be inserted at index 2');
|
equal(indexFor30, 2, '30 should be inserted at index 2');
|
||||||
|
|
||||||
|
var objects = [{x: 10}, {x: 20}, {x: 30}, {x: 40}];
|
||||||
|
var iterator = function(obj){ return obj.x; };
|
||||||
|
strictEqual(_.sortedIndex(objects, {x: 25}, iterator), 2);
|
||||||
|
strictEqual(_.sortedIndex(objects, {x: 35}, 'x'), 3);
|
||||||
|
|
||||||
|
var context = {1: 2, 2: 3, 3: 4};
|
||||||
|
iterator = function(obj){ return this[obj]; };
|
||||||
|
strictEqual(_.sortedIndex([1, 3], 2, iterator, context), 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: shuffle', function() {
|
test('shuffle', function() {
|
||||||
var numbers = _.range(10);
|
var numbers = _.range(10);
|
||||||
var shuffled = _.shuffle(numbers).sort();
|
var shuffled = _.shuffle(numbers).sort();
|
||||||
notStrictEqual(numbers, shuffled, 'original object is unmodified');
|
notStrictEqual(numbers, shuffled, 'original object is unmodified');
|
||||||
equal(shuffled.join(','), numbers.join(','), 'contains the same members before and after shuffle');
|
equal(shuffled.join(','), numbers.join(','), 'contains the same members before and after shuffle');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: toArray', function() {
|
test('toArray', function() {
|
||||||
ok(!_.isArray(arguments), 'arguments object is not an array');
|
ok(!_.isArray(arguments), 'arguments object is not an array');
|
||||||
ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array');
|
ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array');
|
||||||
var a = [1,2,3];
|
var a = [1,2,3];
|
||||||
@@ -279,18 +427,27 @@ $(document).ready(function() {
|
|||||||
var numbers = _.toArray({one : 1, two : 2, three : 3});
|
var numbers = _.toArray({one : 1, two : 2, three : 3});
|
||||||
equal(numbers.join(', '), '1, 2, 3', 'object flattened into array');
|
equal(numbers.join(', '), '1, 2, 3', 'object flattened into array');
|
||||||
|
|
||||||
var objectWithToArrayFunction = {toArray: function() {
|
// test in IE < 9
|
||||||
return [1, 2, 3];
|
try {
|
||||||
}};
|
var actual = _.toArray(document.childNodes);
|
||||||
equal(_.toArray(objectWithToArrayFunction).join(', '), '1, 2, 3', 'toArray method used if present');
|
} catch(ex) { }
|
||||||
|
|
||||||
var objectWithToArrayValue = {toArray: 1};
|
ok(_.isArray(actual), 'should not throw converting a node list');
|
||||||
equal(_.toArray(objectWithToArrayValue).join(', '), '1', 'toArray property ignored if not a function');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('collections: size', function() {
|
test('size', function() {
|
||||||
equal(_.size({one : 1, two : 2, three : 3}), 3, 'can compute the size of an object');
|
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');
|
equal(_.size([1, 2, 3]), 3, 'can compute the size of an array');
|
||||||
|
|
||||||
|
var func = function() {
|
||||||
|
return _.size(arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
equal(func(1, 2, 3, 4), 4, 'can test the size of the arguments object');
|
||||||
|
|
||||||
|
equal(_.size('hello'), 5, 'can compute the size of a string');
|
||||||
|
|
||||||
|
equal(_.size(null), 0, 'handles nulls');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
161
vendor/underscore/test/functions.js
vendored
161
vendor/underscore/test/functions.js
vendored
@@ -2,7 +2,7 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
module("Functions");
|
module("Functions");
|
||||||
|
|
||||||
test("functions: bind", function() {
|
test("bind", function() {
|
||||||
var context = {name : 'moe'};
|
var context = {name : 'moe'};
|
||||||
var func = function(arg) { return "name: " + (this.name || arg); };
|
var func = function(arg) { return "name: " + (this.name || arg); };
|
||||||
var bound = _.bind(func, context);
|
var bound = _.bind(func, context);
|
||||||
@@ -18,10 +18,10 @@ $(document).ready(function() {
|
|||||||
func = _.bind(func, this, 'hello');
|
func = _.bind(func, this, 'hello');
|
||||||
equal(func('moe'), 'hello: moe', 'the function was partially applied in advance');
|
equal(func('moe'), 'hello: moe', 'the function was partially applied in advance');
|
||||||
|
|
||||||
var func = _.bind(func, this, 'curly');
|
func = _.bind(func, this, 'curly');
|
||||||
equal(func(), 'hello: curly', 'the function was completely applied in advance');
|
equal(func(), 'hello: curly', 'the function was completely applied in advance');
|
||||||
|
|
||||||
var func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; };
|
func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; };
|
||||||
func = _.bind(func, this, 'hello', 'moe', 'curly');
|
func = _.bind(func, this, 'hello', 'moe', 'curly');
|
||||||
equal(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments');
|
equal(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments');
|
||||||
|
|
||||||
@@ -34,11 +34,18 @@ $(document).ready(function() {
|
|||||||
// To test this with a modern browser, set underscore's nativeBind to undefined
|
// To test this with a modern browser, set underscore's nativeBind to undefined
|
||||||
var F = function () { return this; };
|
var F = function () { return this; };
|
||||||
var Boundf = _.bind(F, {hello: "moe curly"});
|
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");
|
equal(Boundf().hello, "moe curly", "When called without the new operator, it's OK to be bound to the context");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("functions: bindAll", function() {
|
test("partial", function() {
|
||||||
|
var obj = {name: 'moe'};
|
||||||
|
var func = function() { return this.name + ' ' + _.toArray(arguments).join(' '); };
|
||||||
|
|
||||||
|
obj.func = _.partial(func, 'a', 'b');
|
||||||
|
equal(obj.func('c', 'd'), 'moe a b c d', 'can partially apply');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("bindAll", function() {
|
||||||
var curly = {name : 'curly'}, moe = {
|
var curly = {name : 'curly'}, moe = {
|
||||||
name : 'moe',
|
name : 'moe',
|
||||||
getName : function() { return 'name: ' + this.name; },
|
getName : function() { return 'name: ' + this.name; },
|
||||||
@@ -61,7 +68,7 @@ $(document).ready(function() {
|
|||||||
equal(curly.sayHi(), 'hi: moe', 'calling bindAll with no arguments binds all functions to the object');
|
equal(curly.sayHi(), 'hi: moe', 'calling bindAll with no arguments binds all functions to the object');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("functions: memoize", function() {
|
test("memoize", function() {
|
||||||
var fib = function(n) {
|
var fib = function(n) {
|
||||||
return n < 2 ? n : fib(n - 1) + fib(n - 2);
|
return n < 2 ? n : fib(n - 1) + fib(n - 2);
|
||||||
};
|
};
|
||||||
@@ -77,104 +84,136 @@ $(document).ready(function() {
|
|||||||
equal(fastO('toString'), 'toString', 'checks hasOwnProperty');
|
equal(fastO('toString'), 'toString', 'checks hasOwnProperty');
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("functions: delay", 2, function() {
|
asyncTest("delay", 2, function() {
|
||||||
var delayed = false;
|
var delayed = false;
|
||||||
_.delay(function(){ delayed = true; }, 100);
|
_.delay(function(){ delayed = true; }, 100);
|
||||||
setTimeout(function(){ ok(!delayed, "didn't delay the function quite yet"); }, 50);
|
setTimeout(function(){ ok(!delayed, "didn't delay the function quite yet"); }, 50);
|
||||||
setTimeout(function(){ ok(delayed, 'delayed the function'); start(); }, 150);
|
setTimeout(function(){ ok(delayed, 'delayed the function'); start(); }, 150);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("functions: defer", 1, function() {
|
asyncTest("defer", 1, function() {
|
||||||
var deferred = false;
|
var deferred = false;
|
||||||
_.defer(function(bool){ deferred = bool; }, true);
|
_.defer(function(bool){ deferred = bool; }, true);
|
||||||
_.delay(function(){ ok(deferred, "deferred the function"); start(); }, 50);
|
_.delay(function(){ ok(deferred, "deferred the function"); start(); }, 50);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("functions: throttle", 2, function() {
|
asyncTest("throttle", 2, function() {
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var incr = function(){ counter++; };
|
var incr = function(){ counter++; };
|
||||||
var throttledIncr = _.throttle(incr, 100);
|
var throttledIncr = _.throttle(incr, 32);
|
||||||
throttledIncr(); throttledIncr(); throttledIncr();
|
throttledIncr(); throttledIncr();
|
||||||
setTimeout(throttledIncr, 70);
|
|
||||||
setTimeout(throttledIncr, 120);
|
equal(counter, 1, "incr was called immediately");
|
||||||
setTimeout(throttledIncr, 140);
|
_.delay(function(){ equal(counter, 2, "incr was throttled"); start(); }, 64);
|
||||||
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() {
|
asyncTest("throttle arguments", 2, function() {
|
||||||
var value = 0;
|
var value = 0;
|
||||||
var update = function(val){ value = val; };
|
var update = function(val){ value = val; };
|
||||||
var throttledUpdate = _.throttle(update, 100);
|
var throttledUpdate = _.throttle(update, 32);
|
||||||
throttledUpdate(1); throttledUpdate(2); throttledUpdate(3);
|
throttledUpdate(1); throttledUpdate(2);
|
||||||
setTimeout(function(){ throttledUpdate(4); }, 120);
|
_.delay(function(){ throttledUpdate(3); }, 64);
|
||||||
setTimeout(function(){ throttledUpdate(5); }, 140);
|
equal(value, 1, "updated to latest value");
|
||||||
setTimeout(function(){ throttledUpdate(6); }, 250);
|
_.delay(function(){ equal(value, 3, "updated to latest value"); start(); }, 96);
|
||||||
_.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() {
|
asyncTest("throttle once", 2, function() {
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var incr = function(){ return ++counter; };
|
var incr = function(){ return ++counter; };
|
||||||
var throttledIncr = _.throttle(incr, 100);
|
var throttledIncr = _.throttle(incr, 32);
|
||||||
var result = throttledIncr();
|
var result = throttledIncr();
|
||||||
_.delay(function(){
|
_.delay(function(){
|
||||||
equal(result, 1, "throttled functions return their value");
|
equal(result, 1, "throttled functions return their value");
|
||||||
equal(counter, 1, "incr was called once"); start();
|
equal(counter, 1, "incr was called once"); start();
|
||||||
}, 220);
|
}, 64);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("functions: throttle twice", 1, function() {
|
asyncTest("throttle twice", 1, function() {
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var incr = function(){ counter++; };
|
var incr = function(){ counter++; };
|
||||||
var throttledIncr = _.throttle(incr, 100);
|
var throttledIncr = _.throttle(incr, 32);
|
||||||
throttledIncr(); throttledIncr();
|
throttledIncr(); throttledIncr();
|
||||||
_.delay(function(){ equal(counter, 2, "incr was called twice"); start(); }, 220);
|
_.delay(function(){ equal(counter, 2, "incr was called twice"); start(); }, 64);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("functions: debounce", 1, function() {
|
asyncTest("throttle repeatedly with results", 6, function() {
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var incr = function(){ counter++; };
|
var incr = function(){ return ++counter; };
|
||||||
var debouncedIncr = _.debounce(incr, 50);
|
var throttledIncr = _.throttle(incr, 64);
|
||||||
debouncedIncr(); debouncedIncr(); debouncedIncr();
|
var results = [];
|
||||||
setTimeout(debouncedIncr, 30);
|
var saveResult = function() { results.push(throttledIncr()); };
|
||||||
setTimeout(debouncedIncr, 60);
|
saveResult(); saveResult();
|
||||||
setTimeout(debouncedIncr, 90);
|
_.delay(saveResult, 32);
|
||||||
setTimeout(debouncedIncr, 120);
|
_.delay(saveResult, 80);
|
||||||
setTimeout(debouncedIncr, 150);
|
_.delay(saveResult, 96);
|
||||||
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 220);
|
_.delay(saveResult, 144);
|
||||||
|
_.delay(function() {
|
||||||
|
equal(results[0], 1, "incr was called once");
|
||||||
|
equal(results[1], 1, "incr was throttled");
|
||||||
|
equal(results[2], 1, "incr was throttled");
|
||||||
|
equal(results[3], 2, "incr was called twice");
|
||||||
|
equal(results[4], 2, "incr was throttled");
|
||||||
|
equal(results[5], 3, "incr was called trailing");
|
||||||
|
start();
|
||||||
|
}, 192);
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("functions: debounce asap", 2, function() {
|
asyncTest("throttle triggers trailing call when invoked repeatedly", 2, function() {
|
||||||
|
var counter = 0;
|
||||||
|
var limit = 48;
|
||||||
|
var incr = function(){ counter++; };
|
||||||
|
var throttledIncr = _.throttle(incr, 32);
|
||||||
|
|
||||||
|
var stamp = new Date;
|
||||||
|
while ((new Date - stamp) < limit) {
|
||||||
|
throttledIncr();
|
||||||
|
}
|
||||||
|
var lastCount = counter;
|
||||||
|
ok(counter > 1);
|
||||||
|
|
||||||
|
_.delay(function() {
|
||||||
|
ok(counter > lastCount);
|
||||||
|
start();
|
||||||
|
}, 96);
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest("debounce", 1, function() {
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var incr = function(){ counter++; };
|
var incr = function(){ counter++; };
|
||||||
var debouncedIncr = _.debounce(incr, 50, true);
|
var debouncedIncr = _.debounce(incr, 32);
|
||||||
debouncedIncr(); debouncedIncr(); debouncedIncr();
|
debouncedIncr(); debouncedIncr();
|
||||||
|
_.delay(debouncedIncr, 16);
|
||||||
|
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 96);
|
||||||
|
});
|
||||||
|
|
||||||
|
asyncTest("debounce asap", 4, function() {
|
||||||
|
var a, b;
|
||||||
|
var counter = 0;
|
||||||
|
var incr = function(){ return ++counter; };
|
||||||
|
var debouncedIncr = _.debounce(incr, 64, true);
|
||||||
|
a = debouncedIncr();
|
||||||
|
b = debouncedIncr();
|
||||||
|
equal(a, 1);
|
||||||
|
equal(b, 1);
|
||||||
equal(counter, 1, 'incr was called immediately');
|
equal(counter, 1, 'incr was called immediately');
|
||||||
setTimeout(debouncedIncr, 30);
|
_.delay(debouncedIncr, 16);
|
||||||
setTimeout(debouncedIncr, 60);
|
_.delay(debouncedIncr, 32);
|
||||||
setTimeout(debouncedIncr, 90);
|
_.delay(debouncedIncr, 48);
|
||||||
setTimeout(debouncedIncr, 120);
|
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 128);
|
||||||
setTimeout(debouncedIncr, 150);
|
|
||||||
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 220);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
asyncTest("functions: debounce asap recursively", 2, function() {
|
asyncTest("debounce asap recursively", 2, function() {
|
||||||
var counter = 0;
|
var counter = 0;
|
||||||
var debouncedIncr = _.debounce(function(){
|
var debouncedIncr = _.debounce(function(){
|
||||||
counter++;
|
counter++;
|
||||||
if (counter < 5) debouncedIncr();
|
if (counter < 10) debouncedIncr();
|
||||||
}, 50, true);
|
}, 32, true);
|
||||||
debouncedIncr();
|
debouncedIncr();
|
||||||
equal(counter, 1, 'incr was called immediately');
|
equal(counter, 1, "incr was called immediately");
|
||||||
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 70);
|
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 96);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("functions: once", function() {
|
test("once", function() {
|
||||||
var num = 0;
|
var num = 0;
|
||||||
var increment = _.once(function(){ num++; });
|
var increment = _.once(function(){ num++; });
|
||||||
increment();
|
increment();
|
||||||
@@ -182,7 +221,7 @@ $(document).ready(function() {
|
|||||||
equal(num, 1);
|
equal(num, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("functions: wrap", function() {
|
test("wrap", function() {
|
||||||
var greet = function(name){ return "hi: " + name; };
|
var greet = function(name){ return "hi: " + name; };
|
||||||
var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); });
|
var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); });
|
||||||
equal(backwards('moe'), 'hi: moe eom', 'wrapped the saluation function');
|
equal(backwards('moe'), 'hi: moe eom', 'wrapped the saluation function');
|
||||||
@@ -198,7 +237,7 @@ $(document).ready(function() {
|
|||||||
deepEqual(ret, [noop, ['whats', 'your'], 'vector', 'victor']);
|
deepEqual(ret, [noop, ['whats', 'your'], 'vector', 'victor']);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("functions: compose", function() {
|
test("compose", function() {
|
||||||
var greet = function(name){ return "hi: " + name; };
|
var greet = function(name){ return "hi: " + name; };
|
||||||
var exclaim = function(sentence){ return sentence + '!'; };
|
var exclaim = function(sentence){ return sentence + '!'; };
|
||||||
var composed = _.compose(exclaim, greet);
|
var composed = _.compose(exclaim, greet);
|
||||||
@@ -208,7 +247,7 @@ $(document).ready(function() {
|
|||||||
equal(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative');
|
equal(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("functions: after", function() {
|
test("after", function() {
|
||||||
var testAfter = function(afterAmount, timesCalled) {
|
var testAfter = function(afterAmount, timesCalled) {
|
||||||
var afterCalled = 0;
|
var afterCalled = 0;
|
||||||
var after = _.after(afterAmount, function() {
|
var after = _.after(afterAmount, function() {
|
||||||
|
|||||||
202
vendor/underscore/test/objects.js
vendored
202
vendor/underscore/test/objects.js
vendored
@@ -2,7 +2,7 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
module("Objects");
|
module("Objects");
|
||||||
|
|
||||||
test("objects: keys", function() {
|
test("keys", function() {
|
||||||
equal(_.keys({one : 1, two : 2}).join(', '), 'one, two', 'can extract the keys from an object');
|
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
|
// the test above is not safe because it relies on for-in enumeration order
|
||||||
var a = []; a[1] = 0;
|
var a = []; a[1] = 0;
|
||||||
@@ -14,11 +14,26 @@ $(document).ready(function() {
|
|||||||
raises(function() { _.keys(true); }, TypeError, 'throws an error for boolean primitives');
|
raises(function() { _.keys(true); }, TypeError, 'throws an error for boolean primitives');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: values", function() {
|
test("values", function() {
|
||||||
equal(_.values({one : 1, two : 2}).join(', '), '1, 2', 'can extract the values from an object');
|
equal(_.values({one: 1, two: 2}).join(', '), '1, 2', 'can extract the values from an object');
|
||||||
|
equal(_.values({one: 1, two: 2, length: 3}).join(', '), '1, 2, 3', '... even when one of them is "length"');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: functions", function() {
|
test("pairs", function() {
|
||||||
|
deepEqual(_.pairs({one: 1, two: 2}), [['one', 1], ['two', 2]], 'can convert an object into pairs');
|
||||||
|
deepEqual(_.pairs({one: 1, two: 2, length: 3}), [['one', 1], ['two', 2], ['length', 3]], '... even when one of them is "length"');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("invert", function() {
|
||||||
|
var obj = {first: 'Moe', second: 'Larry', third: 'Curly'};
|
||||||
|
equal(_.keys(_.invert(obj)).join(' '), 'Moe Larry Curly', 'can invert an object');
|
||||||
|
ok(_.isEqual(_.invert(_.invert(obj)), obj), 'two inverts gets you back where you started');
|
||||||
|
|
||||||
|
var obj = {length: 3};
|
||||||
|
ok(_.invert(obj)['3'] == 'length', 'can invert an object with "length"')
|
||||||
|
});
|
||||||
|
|
||||||
|
test("functions", function() {
|
||||||
var obj = {a : 'dash', b : _.map, c : (/yo/), d : _.reduce};
|
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');
|
ok(_.isEqual(['b', 'd'], _.functions(obj)), 'can grab the function names of any passed-in object');
|
||||||
|
|
||||||
@@ -27,7 +42,7 @@ $(document).ready(function() {
|
|||||||
equal(_.functions(new Animal).join(''), 'run', 'also looks up functions on the prototype');
|
equal(_.functions(new Animal).join(''), 'run', 'also looks up functions on the prototype');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: extend", function() {
|
test("extend", function() {
|
||||||
var result;
|
var result;
|
||||||
equal(_.extend({}, {a:'b'}).a, 'b', 'can extend an object with the attributes of another');
|
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({a:'x'}, {a:'b'}).a, 'b', 'properties in source override destination');
|
||||||
@@ -38,9 +53,16 @@ $(document).ready(function() {
|
|||||||
ok(_.isEqual(result, {x:2, a:'b'}), 'extending from multiple source objects last property trumps');
|
ok(_.isEqual(result, {x:2, a:'b'}), 'extending from multiple source objects last property trumps');
|
||||||
result = _.extend({}, {a: void 0, b: null});
|
result = _.extend({}, {a: void 0, b: null});
|
||||||
equal(_.keys(result).join(''), 'ab', 'extend does not copy undefined values');
|
equal(_.keys(result).join(''), 'ab', 'extend does not copy undefined values');
|
||||||
|
|
||||||
|
try {
|
||||||
|
result = {};
|
||||||
|
_.extend(result, null, undefined, {a:1});
|
||||||
|
} catch(ex) {}
|
||||||
|
|
||||||
|
equal(result.a, 1, 'should not error on `null` or `undefined` sources');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: pick", function() {
|
test("pick", function() {
|
||||||
var result;
|
var result;
|
||||||
result = _.pick({a:1, b:2, c:3}, 'a', 'c');
|
result = _.pick({a:1, b:2, c:3}, 'a', 'c');
|
||||||
ok(_.isEqual(result, {a:1, c:3}), 'can restrict properties to those named');
|
ok(_.isEqual(result, {a:1, c:3}), 'can restrict properties to those named');
|
||||||
@@ -48,9 +70,27 @@ $(document).ready(function() {
|
|||||||
ok(_.isEqual(result, {b:2, c:3}), 'can restrict properties to those named in an array');
|
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');
|
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');
|
ok(_.isEqual(result, {a:1, b:2}), 'can restrict properties to those named in mixed args');
|
||||||
|
|
||||||
|
var Obj = function(){};
|
||||||
|
Obj.prototype = {a: 1, b: 2, c: 3};
|
||||||
|
ok(_.isEqual(_.pick(new Obj, 'a', 'c'), {a:1, c: 3}), 'include prototype props');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: defaults", function() {
|
test("omit", function() {
|
||||||
|
var result;
|
||||||
|
result = _.omit({a:1, b:2, c:3}, 'b');
|
||||||
|
ok(_.isEqual(result, {a:1, c:3}), 'can omit a single named property');
|
||||||
|
result = _.omit({a:1, b:2, c:3}, 'a', 'c');
|
||||||
|
ok(_.isEqual(result, {b:2}), 'can omit several named properties');
|
||||||
|
result = _.omit({a:1, b:2, c:3}, ['b', 'c']);
|
||||||
|
ok(_.isEqual(result, {a:1}), 'can omit properties named in an array');
|
||||||
|
|
||||||
|
var Obj = function(){};
|
||||||
|
Obj.prototype = {a: 1, b: 2, c: 3};
|
||||||
|
ok(_.isEqual(_.omit(new Obj, 'b'), {a:1, c: 3}), 'include prototype props');
|
||||||
|
});
|
||||||
|
|
||||||
|
test("defaults", function() {
|
||||||
var result;
|
var result;
|
||||||
var options = {zero: 0, one: 1, empty: "", nan: NaN, string: "string"};
|
var options = {zero: 0, one: 1, empty: "", nan: NaN, string: "string"};
|
||||||
|
|
||||||
@@ -63,9 +103,16 @@ $(document).ready(function() {
|
|||||||
equal(options.empty, "", 'value exists');
|
equal(options.empty, "", 'value exists');
|
||||||
ok(_.isNaN(options.nan), "NaN isn't overridden");
|
ok(_.isNaN(options.nan), "NaN isn't overridden");
|
||||||
equal(options.word, "word", 'new value is added, first one wins');
|
equal(options.word, "word", 'new value is added, first one wins');
|
||||||
|
|
||||||
|
try {
|
||||||
|
options = {};
|
||||||
|
_.defaults(options, null, undefined, {a:1});
|
||||||
|
} catch(ex) {}
|
||||||
|
|
||||||
|
equal(options.a, 1, 'should not error on `null` or `undefined` sources');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: clone", function() {
|
test("clone", function() {
|
||||||
var moe = {name : 'moe', lucky : [13, 27, 34]};
|
var moe = {name : 'moe', lucky : [13, 27, 34]};
|
||||||
var clone = _.clone(moe);
|
var clone = _.clone(moe);
|
||||||
equal(clone.name, 'moe', 'the clone as the attributes of the original');
|
equal(clone.name, 'moe', 'the clone as the attributes of the original');
|
||||||
@@ -81,7 +128,7 @@ $(document).ready(function() {
|
|||||||
equal(_.clone(null), null, 'non objects should not be changed by clone');
|
equal(_.clone(null), null, 'non objects should not be changed by clone');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: isEqual", function() {
|
test("isEqual", function() {
|
||||||
function First() {
|
function First() {
|
||||||
this.value = 1;
|
this.value = 1;
|
||||||
}
|
}
|
||||||
@@ -200,14 +247,6 @@ $(document).ready(function() {
|
|||||||
ok(_.isEqual(Array(3), Array(3)), "Sparse arrays of identical lengths are equal");
|
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");
|
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.
|
// 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", 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: /Curly/g, b: new Date(2009, 11, 13)}, {a: /Curly/g, b: new Date(2009, 11, 13)}), "Objects containing equivalent members are equal");
|
||||||
@@ -265,6 +304,12 @@ $(document).ready(function() {
|
|||||||
b.push("Curly");
|
b.push("Curly");
|
||||||
ok(!_.isEqual(a, b), "Arrays containing circular references and different properties are not equal");
|
ok(!_.isEqual(a, b), "Arrays containing circular references and different properties are not equal");
|
||||||
|
|
||||||
|
// More circular arrays #767.
|
||||||
|
a = ["everything is checked but", "this", "is not"];
|
||||||
|
a[1] = a;
|
||||||
|
b = ["everything is checked but", ["this", "array"], "is not"];
|
||||||
|
ok(!_.isEqual(a, b), "Comparison of circular references with non-circular references are not equal");
|
||||||
|
|
||||||
// Circular Objects.
|
// Circular Objects.
|
||||||
a = {abc: null};
|
a = {abc: null};
|
||||||
b = {abc: null};
|
b = {abc: null};
|
||||||
@@ -278,6 +323,12 @@ $(document).ready(function() {
|
|||||||
b.def = new Number(63);
|
b.def = new Number(63);
|
||||||
ok(!_.isEqual(a, b), "Objects containing circular references and different properties are not equal");
|
ok(!_.isEqual(a, b), "Objects containing circular references and different properties are not equal");
|
||||||
|
|
||||||
|
// More circular objects #767.
|
||||||
|
a = {everything: "is checked", but: "this", is: "not"};
|
||||||
|
a.but = a;
|
||||||
|
b = {everything: "is checked", but: {that:"object"}, is: "not"};
|
||||||
|
ok(!_.isEqual(a, b), "Comparison of circular references with non-circular object references are not equal");
|
||||||
|
|
||||||
// Cyclic Structures.
|
// Cyclic Structures.
|
||||||
a = [{abc: null}];
|
a = [{abc: null}];
|
||||||
b = [{abc: null}];
|
b = [{abc: null}];
|
||||||
@@ -300,71 +351,16 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
// Chaining.
|
// Chaining.
|
||||||
ok(!_.isEqual(_({x: 1, y: undefined}).chain(), _({x: 1, z: 2}).chain()), 'Chained objects containing different values are not equal');
|
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.
|
a = _({x: 1, y: 2}).chain();
|
||||||
var isEqualObj = {isEqual: function (o) { return o.isEqual == this.isEqual; }, unique: {}};
|
b = _({x: 1, y: 2}).chain();
|
||||||
var isEqualObjClone = {isEqual: isEqualObj.isEqual, unique: {}};
|
equal(_.isEqual(a.isEqual(b), _(true)), true, '`isEqual` can be chained');
|
||||||
|
|
||||||
ok(_.isEqual(isEqualObj, isEqualObjClone), 'Both objects implement identical `isEqual` methods');
|
// Objects from another frame.
|
||||||
ok(_.isEqual(isEqualObjClone, isEqualObj), 'Commutative equality is implemented for objects with custom `isEqual` methods');
|
ok(_.isEqual({}, iObject));
|
||||||
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() {
|
test("isEmpty", function() {
|
||||||
ok(!_([1]).isEmpty(), '[1] is not empty');
|
ok(!_([1]).isEmpty(), '[1] is not empty');
|
||||||
ok(_.isEmpty([]), '[] is empty');
|
ok(_.isEmpty([]), '[] is empty');
|
||||||
ok(!_.isEmpty({one : 1}), '{one : 1} is not empty');
|
ok(!_.isEmpty({one : 1}), '{one : 1} is not empty');
|
||||||
@@ -398,17 +394,18 @@ $(document).ready(function() {
|
|||||||
parent.iNull = null;\
|
parent.iNull = null;\
|
||||||
parent.iBoolean = new Boolean(false);\
|
parent.iBoolean = new Boolean(false);\
|
||||||
parent.iUndefined = undefined;\
|
parent.iUndefined = undefined;\
|
||||||
|
parent.iObject = {};\
|
||||||
</script>"
|
</script>"
|
||||||
);
|
);
|
||||||
iDoc.close();
|
iDoc.close();
|
||||||
|
|
||||||
test("objects: isElement", function() {
|
test("isElement", function() {
|
||||||
ok(!_.isElement('div'), 'strings are not dom elements');
|
ok(!_.isElement('div'), 'strings are not dom elements');
|
||||||
ok(_.isElement($('html')[0]), 'the html tag is a DOM element');
|
ok(_.isElement($('html')[0]), 'the html tag is a DOM element');
|
||||||
ok(_.isElement(iElement), 'even from another frame');
|
ok(_.isElement(iElement), 'even from another frame');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: isArguments", function() {
|
test("isArguments", function() {
|
||||||
var args = (function(){ return arguments; })(1, 2, 3);
|
var args = (function(){ return arguments; })(1, 2, 3);
|
||||||
ok(!_.isArguments('string'), 'a string is not an arguments object');
|
ok(!_.isArguments('string'), 'a string is not an arguments object');
|
||||||
ok(!_.isArguments(_.isArguments), 'a function is not an arguments object');
|
ok(!_.isArguments(_.isArguments), 'a function is not an arguments object');
|
||||||
@@ -418,7 +415,7 @@ $(document).ready(function() {
|
|||||||
ok(_.isArguments(iArguments), 'even from another frame');
|
ok(_.isArguments(iArguments), 'even from another frame');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: isObject", function() {
|
test("isObject", function() {
|
||||||
ok(_.isObject(arguments), 'the arguments object is object');
|
ok(_.isObject(arguments), 'the arguments object is object');
|
||||||
ok(_.isObject([1, 2, 3]), 'and arrays');
|
ok(_.isObject([1, 2, 3]), 'and arrays');
|
||||||
ok(_.isObject($('html')[0]), 'and DOM element');
|
ok(_.isObject($('html')[0]), 'and DOM element');
|
||||||
@@ -433,19 +430,19 @@ $(document).ready(function() {
|
|||||||
ok(_.isObject(new String('string')), 'but new String()');
|
ok(_.isObject(new String('string')), 'but new String()');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: isArray", function() {
|
test("isArray", function() {
|
||||||
ok(!_.isArray(arguments), 'the arguments object is not an array');
|
ok(!_.isArray(arguments), 'the arguments object is not an array');
|
||||||
ok(_.isArray([1, 2, 3]), 'but arrays are');
|
ok(_.isArray([1, 2, 3]), 'but arrays are');
|
||||||
ok(_.isArray(iArray), 'even from another frame');
|
ok(_.isArray(iArray), 'even from another frame');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: isString", function() {
|
test("isString", function() {
|
||||||
ok(!_.isString(document.body), 'the document body is not a string');
|
ok(!_.isString(document.body), 'the document body is not a string');
|
||||||
ok(_.isString([1, 2, 3].join(', ')), 'but strings are');
|
ok(_.isString([1, 2, 3].join(', ')), 'but strings are');
|
||||||
ok(_.isString(iString), 'even from another frame');
|
ok(_.isString(iString), 'even from another frame');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: isNumber", function() {
|
test("isNumber", function() {
|
||||||
ok(!_.isNumber('string'), 'a string is not a number');
|
ok(!_.isNumber('string'), 'a string is not a number');
|
||||||
ok(!_.isNumber(arguments), 'the arguments object is not a number');
|
ok(!_.isNumber(arguments), 'the arguments object is not a number');
|
||||||
ok(!_.isNumber(undefined), 'undefined is not a number');
|
ok(!_.isNumber(undefined), 'undefined is not a number');
|
||||||
@@ -456,7 +453,7 @@ $(document).ready(function() {
|
|||||||
ok(!_.isNumber('1'), 'numeric strings are not numbers');
|
ok(!_.isNumber('1'), 'numeric strings are not numbers');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: isBoolean", function() {
|
test("isBoolean", function() {
|
||||||
ok(!_.isBoolean(2), 'a number is not a boolean');
|
ok(!_.isBoolean(2), 'a number is not a boolean');
|
||||||
ok(!_.isBoolean("string"), 'a string 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("false"), 'the string "false" is not a boolean');
|
||||||
@@ -470,33 +467,35 @@ $(document).ready(function() {
|
|||||||
ok(_.isBoolean(iBoolean), 'even from another frame');
|
ok(_.isBoolean(iBoolean), 'even from another frame');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: isFunction", function() {
|
test("isFunction", function() {
|
||||||
ok(!_.isFunction([1, 2, 3]), 'arrays are not functions');
|
ok(!_.isFunction([1, 2, 3]), 'arrays are not functions');
|
||||||
ok(!_.isFunction('moe'), 'strings are not functions');
|
ok(!_.isFunction('moe'), 'strings are not functions');
|
||||||
ok(_.isFunction(_.isFunction), 'but functions are');
|
ok(_.isFunction(_.isFunction), 'but functions are');
|
||||||
ok(_.isFunction(iFunction), 'even from another frame');
|
ok(_.isFunction(iFunction), 'even from another frame');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: isDate", function() {
|
test("isDate", function() {
|
||||||
ok(!_.isDate(100), 'numbers are not dates');
|
ok(!_.isDate(100), 'numbers are not dates');
|
||||||
ok(!_.isDate({}), 'objects are not dates');
|
ok(!_.isDate({}), 'objects are not dates');
|
||||||
ok(_.isDate(new Date()), 'but dates are');
|
ok(_.isDate(new Date()), 'but dates are');
|
||||||
ok(_.isDate(iDate), 'even from another frame');
|
ok(_.isDate(iDate), 'even from another frame');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: isRegExp", function() {
|
test("isRegExp", function() {
|
||||||
ok(!_.isRegExp(_.identity), 'functions are not RegExps');
|
ok(!_.isRegExp(_.identity), 'functions are not RegExps');
|
||||||
ok(_.isRegExp(/identity/), 'but RegExps are');
|
ok(_.isRegExp(/identity/), 'but RegExps are');
|
||||||
ok(_.isRegExp(iRegExp), 'even from another frame');
|
ok(_.isRegExp(iRegExp), 'even from another frame');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: isFinite", function() {
|
test("isFinite", function() {
|
||||||
ok(!_.isFinite(undefined), 'undefined is not Finite');
|
ok(!_.isFinite(undefined), 'undefined is not Finite');
|
||||||
ok(!_.isFinite(null), 'null is not Finite');
|
ok(!_.isFinite(null), 'null is not Finite');
|
||||||
ok(!_.isFinite(NaN), 'NaN 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(-Infinity), '-Infinity is not Finite');
|
ok(!_.isFinite(-Infinity), '-Infinity is not Finite');
|
||||||
ok(!_.isFinite('12'), 'Strings are not numbers');
|
ok(_.isFinite('12'), 'Numeric strings are numbers');
|
||||||
|
ok(!_.isFinite('1a'), 'Non numeric strings are not numbers');
|
||||||
|
ok(!_.isFinite(''), 'Empty strings are not numbers');
|
||||||
var obj = new Number(5);
|
var obj = new Number(5);
|
||||||
ok(_.isFinite(obj), 'Number instances can be finite');
|
ok(_.isFinite(obj), 'Number instances can be finite');
|
||||||
ok(_.isFinite(0), '0 is Finite');
|
ok(_.isFinite(0), '0 is Finite');
|
||||||
@@ -504,22 +503,23 @@ $(document).ready(function() {
|
|||||||
ok(_.isFinite(-12.44), 'Floats are Finite');
|
ok(_.isFinite(-12.44), 'Floats are Finite');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: isNaN", function() {
|
test("isNaN", function() {
|
||||||
ok(!_.isNaN(undefined), 'undefined is not NaN');
|
ok(!_.isNaN(undefined), 'undefined is not NaN');
|
||||||
ok(!_.isNaN(null), 'null is not NaN');
|
ok(!_.isNaN(null), 'null is not NaN');
|
||||||
ok(!_.isNaN(0), '0 is not NaN');
|
ok(!_.isNaN(0), '0 is not NaN');
|
||||||
ok(_.isNaN(NaN), 'but NaN is');
|
ok(_.isNaN(NaN), 'but NaN is');
|
||||||
ok(_.isNaN(iNaN), 'even from another frame');
|
ok(_.isNaN(iNaN), 'even from another frame');
|
||||||
|
ok(_.isNaN(new Number(NaN)), 'wrapped NaN is still NaN');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: isNull", function() {
|
test("isNull", function() {
|
||||||
ok(!_.isNull(undefined), 'undefined is not null');
|
ok(!_.isNull(undefined), 'undefined is not null');
|
||||||
ok(!_.isNull(NaN), 'NaN is not null');
|
ok(!_.isNull(NaN), 'NaN is not null');
|
||||||
ok(_.isNull(null), 'but null is');
|
ok(_.isNull(null), 'but null is');
|
||||||
ok(_.isNull(iNull), 'even from another frame');
|
ok(_.isNull(iNull), 'even from another frame');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("objects: isUndefined", function() {
|
test("isUndefined", function() {
|
||||||
ok(!_.isUndefined(1), 'numbers are defined');
|
ok(!_.isUndefined(1), 'numbers are defined');
|
||||||
ok(!_.isUndefined(null), 'null is defined');
|
ok(!_.isUndefined(null), 'null is defined');
|
||||||
ok(!_.isUndefined(false), 'false is defined');
|
ok(!_.isUndefined(false), 'false is defined');
|
||||||
@@ -530,7 +530,7 @@ $(document).ready(function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (window.ActiveXObject) {
|
if (window.ActiveXObject) {
|
||||||
test("objects: IE host objects", function() {
|
test("IE host objects", function() {
|
||||||
var xml = new ActiveXObject("Msxml2.DOMDocument.3.0");
|
var xml = new ActiveXObject("Msxml2.DOMDocument.3.0");
|
||||||
ok(!_.isNumber(xml));
|
ok(!_.isNumber(xml));
|
||||||
ok(!_.isBoolean(xml));
|
ok(!_.isBoolean(xml));
|
||||||
@@ -541,7 +541,7 @@ $(document).ready(function() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
test("objects: tap", function() {
|
test("tap", function() {
|
||||||
var intercepted = null;
|
var intercepted = null;
|
||||||
var interceptor = function(obj) { intercepted = obj; };
|
var interceptor = function(obj) { intercepted = obj; };
|
||||||
var returned = _.tap(1, interceptor);
|
var returned = _.tap(1, interceptor);
|
||||||
@@ -555,4 +555,16 @@ $(document).ready(function() {
|
|||||||
value();
|
value();
|
||||||
ok(returned == 6 && intercepted == 6, 'can use tapped objects in a chain');
|
ok(returned == 6 && intercepted == 6, 'can use tapped objects in a chain');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("has", function () {
|
||||||
|
var obj = {foo: "bar", func: function () {} };
|
||||||
|
ok (_.has(obj, "foo"), "has() checks that the object has a property.");
|
||||||
|
ok (_.has(obj, "baz") == false, "has() returns false if the object doesn't have the property.");
|
||||||
|
ok (_.has(obj, "func"), "has() works for functions too.");
|
||||||
|
obj.hasOwnProperty = null;
|
||||||
|
ok (_.has(obj, "foo"), "has() works even when the hasOwnProperty method is deleted.");
|
||||||
|
var child = {};
|
||||||
|
child.prototype = obj;
|
||||||
|
ok (_.has(child, "foo") == false, "has() does not check the prototype chain for a property.")
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
71
vendor/underscore/test/utility.js
vendored
71
vendor/underscore/test/utility.js
vendored
@@ -14,28 +14,50 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("utility: identity", function() {
|
test("#750 - Return _ instance.", 2, function() {
|
||||||
|
var instance = _([]);
|
||||||
|
ok(_(instance) === instance);
|
||||||
|
ok(new _(instance) === instance);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("identity", function() {
|
||||||
var moe = {name : 'moe'};
|
var moe = {name : 'moe'};
|
||||||
equal(_.identity(moe), moe, 'moe is the same as his identity');
|
equal(_.identity(moe), moe, 'moe is the same as his identity');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("utility: uniqueId", function() {
|
test("random", function() {
|
||||||
|
var array = _.range(1000);
|
||||||
|
var min = Math.pow(2, 31);
|
||||||
|
var max = Math.pow(2, 62);
|
||||||
|
|
||||||
|
ok(_.every(array, function() {
|
||||||
|
return _.random(min, max) >= min;
|
||||||
|
}), "should produce a random number greater than or equal to the minimum number");
|
||||||
|
|
||||||
|
ok(_.some(array, function() {
|
||||||
|
return _.random(Number.MAX_VALUE) > 0;
|
||||||
|
}), "should produce a random number when passed `Number.MAX_VALUE`");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("uniqueId", function() {
|
||||||
var ids = [], i = 0;
|
var ids = [], i = 0;
|
||||||
while(i++ < 100) ids.push(_.uniqueId());
|
while(i++ < 100) ids.push(_.uniqueId());
|
||||||
equal(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids');
|
equal(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("utility: times", function() {
|
test("times", function() {
|
||||||
var vals = [];
|
var vals = [];
|
||||||
_.times(3, function (i) { vals.push(i); });
|
_.times(3, function (i) { vals.push(i); });
|
||||||
ok(_.isEqual(vals, [0,1,2]), "is 0 indexed");
|
ok(_.isEqual(vals, [0,1,2]), "is 0 indexed");
|
||||||
//
|
//
|
||||||
vals = [];
|
vals = [];
|
||||||
_(3).times(function (i) { vals.push(i); });
|
_(3).times(function(i) { vals.push(i); });
|
||||||
ok(_.isEqual(vals, [0,1,2]), "works as a wrapper");
|
ok(_.isEqual(vals, [0,1,2]), "works as a wrapper");
|
||||||
|
// collects return values
|
||||||
|
ok(_.isEqual([0, 1, 2], _.times(3, function(i) { return i; })), "collects return values");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("utility: mixin", function() {
|
test("mixin", function() {
|
||||||
_.mixin({
|
_.mixin({
|
||||||
myReverse: function(string) {
|
myReverse: function(string) {
|
||||||
return string.split('').reverse().join('');
|
return string.split('').reverse().join('');
|
||||||
@@ -45,12 +67,21 @@ $(document).ready(function() {
|
|||||||
equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper');
|
equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("utility: _.escape", function() {
|
test("_.escape", function() {
|
||||||
equal(_.escape("Curly & Moe"), "Curly & Moe");
|
equal(_.escape("Curly & Moe"), "Curly & Moe");
|
||||||
equal(_.escape("Curly & Moe"), "Curly &amp; Moe");
|
equal(_.escape("Curly & Moe"), "Curly &amp; Moe");
|
||||||
|
equal(_.escape(null), '');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("utility: template", function() {
|
test("_.unescape", function() {
|
||||||
|
var string = "Curly & Moe";
|
||||||
|
equal(_.unescape("Curly & Moe"), string);
|
||||||
|
equal(_.unescape("Curly &amp; Moe"), "Curly & Moe");
|
||||||
|
equal(_.unescape(null), '');
|
||||||
|
equal(_.unescape(_.escape(string)), string);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("template", function() {
|
||||||
var basicTemplate = _.template("<%= thing %> is gettin' on my noives!");
|
var basicTemplate = _.template("<%= thing %> is gettin' on my noives!");
|
||||||
var result = basicTemplate({thing : 'This'});
|
var result = basicTemplate({thing : 'This'});
|
||||||
equal(result, "This is gettin' on my noives!", 'can do basic attribute interpolation');
|
equal(result, "This is gettin' on my noives!", 'can do basic attribute interpolation');
|
||||||
@@ -65,7 +96,7 @@ $(document).ready(function() {
|
|||||||
equal(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.');
|
equal(escapeTemplate({a: true}), 'checked="checked"', 'can handle slash escapes in interpolations.');
|
||||||
|
|
||||||
var fancyTemplate = _.template("<ul><% \
|
var fancyTemplate = _.template("<ul><% \
|
||||||
for (key in people) { \
|
for (var key in people) { \
|
||||||
%><li><%= people[key] %></li><% } %></ul>");
|
%><li><%= people[key] %></li><% } %></ul>");
|
||||||
result = fancyTemplate({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
|
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');
|
equal(result, "<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>", 'can run arbitrary javascript in templates');
|
||||||
@@ -120,7 +151,7 @@ $(document).ready(function() {
|
|||||||
interpolate : /\{\{=([\s\S]+?)\}\}/g
|
interpolate : /\{\{=([\s\S]+?)\}\}/g
|
||||||
};
|
};
|
||||||
|
|
||||||
var custom = _.template("<ul>{{ for (key in people) { }}<li>{{= people[key] }}</li>{{ } }}</ul>");
|
var custom = _.template("<ul>{{ for (var key in people) { }}<li>{{= people[key] }}</li>{{ } }}</ul>");
|
||||||
result = custom({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
|
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');
|
equal(result, "<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>", 'can run arbitrary javascript in templates');
|
||||||
|
|
||||||
@@ -135,7 +166,7 @@ $(document).ready(function() {
|
|||||||
interpolate : /<\?=([\s\S]+?)\?>/g
|
interpolate : /<\?=([\s\S]+?)\?>/g
|
||||||
};
|
};
|
||||||
|
|
||||||
var customWithSpecialChars = _.template("<ul><? for (key in people) { ?><li><?= people[key] ?></li><? } ?></ul>");
|
var customWithSpecialChars = _.template("<ul><? for (var key in people) { ?><li><?= people[key] ?></li><? } ?></ul>");
|
||||||
result = customWithSpecialChars({people : {moe : "Moe", larry : "Larry", curly : "Curly"}});
|
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');
|
equal(result, "<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>", 'can run arbitrary javascript in templates');
|
||||||
|
|
||||||
@@ -156,6 +187,15 @@ $(document).ready(function() {
|
|||||||
equal(templateWithNull({planet : "world"}), "a null undefined world", "can handle missing escape and evaluate settings");
|
equal(templateWithNull({planet : "world"}), "a null undefined world", "can handle missing escape and evaluate settings");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('_.template provides the generated function source, when a SyntaxError occurs', function() {
|
||||||
|
try {
|
||||||
|
_.template('<b><%= if x %></b>');
|
||||||
|
} catch (ex) {
|
||||||
|
var source = ex.source;
|
||||||
|
}
|
||||||
|
ok(/__p/.test(source));
|
||||||
|
});
|
||||||
|
|
||||||
test('_.template handles \\u2028 & \\u2029', function() {
|
test('_.template handles \\u2028 & \\u2029', function() {
|
||||||
var tmpl = _.template('<p>\u2028<%= "\\u2028\\u2029" %>\u2029</p>');
|
var tmpl = _.template('<p>\u2028<%= "\\u2028\\u2029" %>\u2029</p>');
|
||||||
strictEqual(tmpl(), '<p>\u2028\u2028\u2029\u2029</p>');
|
strictEqual(tmpl(), '<p>\u2028\u2028\u2029\u2029</p>');
|
||||||
@@ -212,4 +252,15 @@ $(document).ready(function() {
|
|||||||
templateEscaped({f: function(){ ok(!(countEscaped++)); }});
|
templateEscaped({f: function(){ ok(!(countEscaped++)); }});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('#746 - _.template settings are not modified.', 1, function() {
|
||||||
|
var settings = {};
|
||||||
|
_.template('', null, settings);
|
||||||
|
deepEqual(settings, {});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('#779 - delimeters are applied to unescaped text.', 1, function() {
|
||||||
|
var template = _.template('<<\nx\n>>', null, {evaluate: /<<(.*?)>>/g});
|
||||||
|
strictEqual(template(), '<<\nx\n>>');
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
670
vendor/underscore/test/vendor/jslitmus.js
vendored
670
vendor/underscore/test/vendor/jslitmus.js
vendored
@@ -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 : '∞';
|
|
||||||
} 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();
|
|
||||||
})();
|
|
||||||
236
vendor/underscore/test/vendor/qunit.css
vendored
236
vendor/underscore/test/vendor/qunit.css
vendored
@@ -1,236 +0,0 @@
|
|||||||
/**
|
|
||||||
* QUnit v1.8.0 - A JavaScript Unit Testing Framework
|
|
||||||
*
|
|
||||||
* http://docs.jquery.com/QUnit
|
|
||||||
*
|
|
||||||
* Copyright (c) 2012 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-header label {
|
|
||||||
display: inline-block;
|
|
||||||
padding-left: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
#qunit-testresult .module-name {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Fixture */
|
|
||||||
|
|
||||||
#qunit-fixture {
|
|
||||||
position: absolute;
|
|
||||||
top: -10000px;
|
|
||||||
left: -10000px;
|
|
||||||
width: 1000px;
|
|
||||||
height: 1000px;
|
|
||||||
}
|
|
||||||
1863
vendor/underscore/test/vendor/qunit.js
vendored
1863
vendor/underscore/test/vendor/qunit.js
vendored
File diff suppressed because it is too large
Load Diff
5
vendor/underscore/underscore-min.js
vendored
Normal file
5
vendor/underscore/underscore-min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
622
vendor/underscore/underscore.js
vendored
622
vendor/underscore/underscore.js
vendored
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user