Compare commits
669 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
5defe7d975 | ||
|
|
7e79903fe8 | ||
|
|
a2fa52504c | ||
|
|
2629f85e73 | ||
|
|
8577816234 | ||
|
|
e58d47a3b2 | ||
|
|
c9c83ee7e6 | ||
|
|
139693dce6 | ||
|
|
f98193d822 | ||
|
|
8052f1ac9d | ||
|
|
4f78a06993 | ||
|
|
6c4b4b392b | ||
|
|
268fe34238 | ||
|
|
cc620205d6 | ||
|
|
f0d7c97b7b | ||
|
|
660a6e9e4c | ||
|
|
3386c2a7a5 | ||
|
|
9530efb4d4 | ||
|
|
4293515b3d | ||
|
|
61105e0679 | ||
|
|
79a289c7e2 | ||
|
|
46781e7614 | ||
|
|
1f3546a9f6 | ||
|
|
0dc88bb412 | ||
|
|
971a26c123 | ||
|
|
0976a3b721 | ||
|
|
d496361555 | ||
|
|
60ed65a73a | ||
|
|
d1407b3bd0 | ||
|
|
5ca2da76df | ||
|
|
2ac887ff74 | ||
|
|
cbdc9c0be1 | ||
|
|
b9bade8d5a | ||
|
|
eb43786641 | ||
|
|
0515db3d7c | ||
|
|
db257778c0 | ||
|
|
3b37d7489f | ||
|
|
329c7e8e05 | ||
|
|
fad9b4fa72 | ||
|
|
c1a81279ed | ||
|
|
8bb35a17d2 | ||
|
|
36415054ea | ||
|
|
3e84cbae69 | ||
|
|
f5f2bf7f46 | ||
|
|
acb6656958 | ||
|
|
9d70d7c27e | ||
|
|
648a6afb25 | ||
|
|
57ae1925b1 | ||
|
|
d49318582f | ||
|
|
83e3f830e6 | ||
|
|
04d4353c0f | ||
|
|
6d217fc097 | ||
|
|
9d7136c63c | ||
|
|
51a679d60a | ||
|
|
7d4d28614a | ||
|
|
c75cfaf692 | ||
|
|
fe6aa8a6fc | ||
|
|
a5fe1eb5fb | ||
|
|
5afd37c92c | ||
|
|
293d0409c6 | ||
|
|
4352f18dd3 | ||
|
|
0ae7fe9df5 | ||
|
|
5048f0422d | ||
|
|
c46a36f8ed | ||
|
|
90e2bd0372 | ||
|
|
10fbc8a04b | ||
|
|
fb818f3775 | ||
|
|
434e23c209 | ||
|
|
fe53bd6475 | ||
|
|
268ce91c65 | ||
|
|
3b4074bfc7 | ||
|
|
6af4652161 | ||
|
|
3717d30188 | ||
|
|
4cf2e83418 | ||
|
|
1228639103 | ||
|
|
e12d67de94 | ||
|
|
10bcb37ca5 | ||
|
|
e973598bff | ||
|
|
3a5129694d | ||
|
|
a1e0fbea8b | ||
|
|
0bf374454e | ||
|
|
5e592fbf29 | ||
|
|
ad4101bc99 | ||
|
|
2d057d92cf | ||
|
|
00d1cc9bf8 | ||
|
|
2c1ec5fe75 | ||
|
|
81b28d005d | ||
|
|
6a90616b99 | ||
|
|
d5be43695a | ||
|
|
0a93b81ae7 | ||
|
|
65f8da1654 | ||
|
|
911014db95 | ||
|
|
313ee13f18 | ||
|
|
addad04c44 | ||
|
|
e3789e5b64 | ||
|
|
410315ce35 | ||
|
|
90998da308 | ||
|
|
6fa5b13e10 | ||
|
|
93067c2d52 | ||
|
|
b2079b7007 | ||
|
|
b643dd074c | ||
|
|
a3932c75e1 | ||
|
|
1cd3b9ec47 | ||
|
|
0c77f42080 | ||
|
|
cea122db38 | ||
|
|
966f9fcd07 | ||
|
|
6ce9df8504 | ||
|
|
2a0b223896 | ||
|
|
c2db180829 | ||
|
|
3223e4ffa5 | ||
|
|
24c9b6e211 | ||
|
|
e5555dd26a | ||
|
|
ee2d0ddf8a | ||
|
|
aef130b396 | ||
|
|
fbdadec5e5 | ||
|
|
a068339079 | ||
|
|
3f07d3ec55 | ||
|
|
62e7da9d8a | ||
|
|
b60d43e5f6 | ||
|
|
a5873a3158 | ||
|
|
3a698eb0ed | ||
|
|
1e2ef542e4 | ||
|
|
94e8af4d93 | ||
|
|
250a0ab5eb | ||
|
|
2da05d88a0 | ||
|
|
7faa849a89 | ||
|
|
c5bceb8fc8 | ||
|
|
1e94b93ce6 | ||
|
|
3f7bccf2e6 | ||
|
|
181b869109 | ||
|
|
2332245be1 | ||
|
|
3c6999f3a4 | ||
|
|
5f2f15b976 | ||
|
|
47dfb5b6b7 | ||
|
|
c410c1293e | ||
|
|
ca1c732f31 | ||
|
|
5e8c373bf4 | ||
|
|
51a459fe48 | ||
|
|
03c07abbc3 | ||
|
|
5eabe1a172 | ||
|
|
5b6ea7afb2 | ||
|
|
7c1c5e70ca | ||
|
|
d475f8f965 | ||
|
|
fd239076dd | ||
|
|
5f786bbe47 | ||
|
|
f66dc6bed8 | ||
|
|
52c36ac445 | ||
|
|
8f6a78cba5 | ||
|
|
7053e9113f | ||
|
|
89f9ab9940 | ||
|
|
240bc40b39 | ||
|
|
74649b5f28 | ||
|
|
b484d4b2dc | ||
|
|
da1124dd37 | ||
|
|
210485d0be | ||
|
|
d9aee5ae60 | ||
|
|
9ac64623fc | ||
|
|
6ea4226680 | ||
|
|
c1416bba39 | ||
|
|
ddb3ab3238 | ||
|
|
5e7c9698c7 | ||
|
|
4c66b95516 | ||
|
|
2d03060a0d | ||
|
|
3313b0aa42 | ||
|
|
5d2928d2b3 | ||
|
|
f6e2ae41d6 | ||
|
|
7ccb038b6d | ||
|
|
7d62bbf74f | ||
|
|
3d8cc32302 | ||
|
|
861eea5148 | ||
|
|
b432721fe5 | ||
|
|
f13a0cc7e0 | ||
|
|
1f7e37a1a3 | ||
|
|
548e9cac26 | ||
|
|
0d2a1641c9 | ||
|
|
a67281f8e7 | ||
|
|
281475e6ef | ||
|
|
a5712fc873 | ||
|
|
205ded45e2 | ||
|
|
8ef039b9db | ||
|
|
3d2428b278 | ||
|
|
35d5704e3f | ||
|
|
c1860d30d6 | ||
|
|
e0fba5cb51 | ||
|
|
570ba189ed | ||
|
|
e335e0fd72 | ||
|
|
74a2d8dcb1 | ||
|
|
43ea0c9072 | ||
|
|
dde3eb2e36 | ||
|
|
2008bf90af | ||
|
|
06ffa93bd0 | ||
|
|
5da03cac79 | ||
|
|
8a5eb89aa8 | ||
|
|
f81ede2fd6 | ||
|
|
6f7df67ded | ||
|
|
bb9ad69219 | ||
|
|
8f7667a524 | ||
|
|
86e125a6f3 | ||
|
|
8b3ba13ff0 | ||
|
|
82f062caf2 | ||
|
|
67303eb9fb | ||
|
|
af3ded68c4 | ||
|
|
b94eb44e18 | ||
|
|
c62b24b024 | ||
|
|
baa37450cc | ||
|
|
231fd46cd2 | ||
|
|
b2728d9902 | ||
|
|
451a33f526 | ||
|
|
3670bce918 | ||
|
|
afb041b23c | ||
|
|
5315058e2d | ||
|
|
26d9cc972e | ||
|
|
52ae87812e | ||
|
|
f8af24b383 | ||
|
|
b38947146e | ||
|
|
5c48abff4b | ||
|
|
3994c7fc2b | ||
|
|
859f2b2f3b | ||
|
|
f5040a7bec | ||
|
|
a604494aa9 | ||
|
|
eaaef83ace | ||
|
|
9cf1424d8f | ||
|
|
cb74e45b89 | ||
|
|
1da0498f74 | ||
|
|
754b1de597 | ||
|
|
7e39941ad3 | ||
|
|
79a27b18ce | ||
|
|
194551fdbf | ||
|
|
5a82c8f89b | ||
|
|
2e540368eb | ||
|
|
d5966ae5db | ||
|
|
97f4dfc089 | ||
|
|
b03c2b3b8f | ||
|
|
9a81df6d77 | ||
|
|
a9d55121bb | ||
|
|
88327aeba2 | ||
|
|
8e2d972281 | ||
|
|
7b44ef1664 | ||
|
|
5204fac055 | ||
|
|
c2a1f50dc0 | ||
|
|
c8f3b128cb | ||
|
|
b32ed95597 | ||
|
|
57da1d3062 | ||
|
|
6dfe18fe18 | ||
|
|
1dd9ee2397 | ||
|
|
d31471c6a1 | ||
|
|
930f04951f | ||
|
|
8846835ab8 | ||
|
|
b080cc4d23 | ||
|
|
c910a95ee4 | ||
|
|
4601129fc7 | ||
|
|
9c79259e9c | ||
|
|
bdca0cf668 | ||
|
|
628ad0fcb2 | ||
|
|
793332beb8 | ||
|
|
4e9688cc18 | ||
|
|
ef9a6a0027 | ||
|
|
9e9222c65d | ||
|
|
9ef0d9084f | ||
|
|
36df8f7828 | ||
|
|
8ee1cc8d27 | ||
|
|
e4e2658a3b | ||
|
|
ae8e7ae992 | ||
|
|
e0c936ba03 | ||
|
|
0297e31893 | ||
|
|
5b975adc8e | ||
|
|
12fc6b3a67 | ||
|
|
cb4cc61c5b | ||
|
|
9f4404628b | ||
|
|
5441f6b55b | ||
|
|
258fc518a6 | ||
|
|
6a06bf5efa | ||
|
|
ff93f7cbb5 | ||
|
|
2e291396bd | ||
|
|
b779f8b029 | ||
|
|
04a05b4c02 | ||
|
|
90989a816d | ||
|
|
9b26b96836 | ||
|
|
972a716600 | ||
|
|
b5c4a9241b | ||
|
|
45f9d80a81 | ||
|
|
98435d2d92 | ||
|
|
ccbf965bd9 | ||
|
|
5c82104d7b | ||
|
|
4c29fbb36d | ||
|
|
88e754850d | ||
|
|
21b86980a7 | ||
|
|
98942c5e1a | ||
|
|
9c54df2de5 | ||
|
|
f31c2d24f9 | ||
|
|
52cf17b24a | ||
|
|
d26fc7154c | ||
|
|
14c8863657 | ||
|
|
6d3d5f77bc | ||
|
|
293fc695a4 | ||
|
|
a317d2471f | ||
|
|
afe7ff6d2c | ||
|
|
2f908870e7 | ||
|
|
312f0310dc | ||
|
|
1a1bd5322c | ||
|
|
04ca0ae309 | ||
|
|
221f70e609 | ||
|
|
a426109c1c | ||
|
|
d5e2489cad | ||
|
|
367f0bd6a9 | ||
|
|
8396ed3167 | ||
|
|
6cc360d613 | ||
|
|
e86eef5905 | ||
|
|
24d5fbb595 | ||
|
|
6fb7681a2d | ||
|
|
0b404d4bb1 | ||
|
|
464826e81d | ||
|
|
e871ffeff0 | ||
|
|
2847b1f08e | ||
|
|
d702e00446 | ||
|
|
142ee20bca | ||
|
|
e3f03fa2ce | ||
|
|
8dc3fb86db | ||
|
|
358ec3fb39 | ||
|
|
f4a38a25c8 | ||
|
|
dcb62a3df5 | ||
|
|
59c26957bb | ||
|
|
09d8561b3c | ||
|
|
6246e71c87 | ||
|
|
adcc2dd8d2 | ||
|
|
947fc9ce97 | ||
|
|
5caca9175d | ||
|
|
520d09e81e | ||
|
|
7fa4304097 | ||
|
|
ceed641730 | ||
|
|
1d4ce28b62 | ||
|
|
a551992c3f | ||
|
|
23b8d083a4 | ||
|
|
b3d249f2ef | ||
|
|
647633a1a0 | ||
|
|
313ffb8821 | ||
|
|
774f159e67 | ||
|
|
f9358531ad | ||
|
|
bb09d77eb5 | ||
|
|
ba8cc970d0 | ||
|
|
89c986d50f |
3
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
*.custom.*
|
||||
.DS_Store
|
||||
node_modules/
|
||||
node_modules/
|
||||
|
||||
18
.gitmodules
vendored
@@ -1,18 +0,0 @@
|
||||
[submodule "vendor/benchmark.js"]
|
||||
path = vendor/benchmark.js
|
||||
url = git://github.com/bestiejs/benchmark.js.git
|
||||
[submodule "vendor/docdown"]
|
||||
path = vendor/docdown
|
||||
url = git://github.com/jdalton/docdown.git
|
||||
[submodule "vendor/qunit"]
|
||||
path = vendor/qunit
|
||||
url = git://github.com/jquery/qunit.git
|
||||
[submodule "vendor/qunit-clib"]
|
||||
path = vendor/qunit-clib
|
||||
url = git://github.com/jdalton/qunit-clib.git
|
||||
[submodule "vendor/requirejs"]
|
||||
path = vendor/requirejs
|
||||
url = git://github.com/jrburke/requirejs.git
|
||||
[submodule "vendor/uglifyjs"]
|
||||
path = vendor/uglifyjs
|
||||
url = git://github.com/mishoo/UglifyJS.git
|
||||
14
.jamignore
Normal file
@@ -0,0 +1,14 @@
|
||||
*.custom.*
|
||||
.*
|
||||
build.js
|
||||
index.js
|
||||
build/
|
||||
doc/*.php
|
||||
node_modules/
|
||||
perf/*.sh
|
||||
test/*.sh
|
||||
test/test-build.js
|
||||
test/template/
|
||||
vendor/closure-compiler
|
||||
vendor/docdown
|
||||
vendor/uglifyjs
|
||||
14
.npmignore
@@ -1,5 +1,15 @@
|
||||
*.custom.*
|
||||
.*
|
||||
dist/*
|
||||
doc/*.php
|
||||
node_modules/
|
||||
perf/*.html
|
||||
perf/*.sh
|
||||
test/*.html
|
||||
vendor/
|
||||
test/*-ui.js
|
||||
test/*.sh
|
||||
vendor/backbone/
|
||||
vendor/docdown/
|
||||
vendor/firebug-lite/
|
||||
vendor/qunit/qunit/*.css
|
||||
vendor/requirejs/
|
||||
vendor/underscore/test/
|
||||
|
||||
4
.travis.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.6
|
||||
- 0.8
|
||||
293
README.md
@@ -1,97 +1,296 @@
|
||||
# Lo-Dash <sup>v0.1.0</sup>
|
||||
# Lo-Dash <sup>v0.8.2</sup>
|
||||
[](http://travis-ci.org/bestiejs/lodash)
|
||||
|
||||
A drop-in replacement for [Underscore.js](https://github.com/documentcloud/underscore/) that delivers up to [8x performance improvements](http://jsperf.com/lodash-underscore#chart=bar), [bug fixes](https://github.com/bestiejs/lodash/blob/master/test/test.js#L71), and additional features.
|
||||
A drop-in replacement<sup>[*](https://github.com/bestiejs/lodash/wiki/Drop-in-Disclaimer)</sup> for Underscore.js, from the devs behind [jsPerf.com](http://jsperf.com), delivering [performance](http://lodash.com/benchmarks), [bug fixes](https://github.com/bestiejs/lodash#resolved-underscorejs-issues), and [additional features](http://lodash.com/#features).
|
||||
|
||||
## BestieJS
|
||||
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.
|
||||
|
||||
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.
|
||||
## Download
|
||||
|
||||
## Documentation
|
||||
* [Development build](https://raw.github.com/bestiejs/lodash/v0.8.2/lodash.js)
|
||||
* [Production build](https://raw.github.com/bestiejs/lodash/v0.8.2/lodash.min.js)
|
||||
* [Underscore build](https://raw.github.com/bestiejs/lodash/v0.8.2/lodash.underscore.min.js) tailored for projects already using Underscore
|
||||
* CDN copies of ≤ [v0.8.2](http://cdnjs.cloudflare.com/ajax/libs/lodash.js/0.8.2/lodash.min.js) are available on [cdnjs](http://cdnjs.com/) thanks to [CloudFlare](http://www.cloudflare.com/)
|
||||
* For optimal file size, [create a custom build](https://github.com/bestiejs/lodash#custom-builds) with only the features you need
|
||||
|
||||
The documentation for Lo-Dash can be viewed here: [/doc/README.md](https://github.com/bestiejs/lodash/blob/master/doc/README.md#readme)
|
||||
## Dive in
|
||||
|
||||
Underscore's [documentation](http://documentcloud.github.com/underscore/) may also be used.
|
||||
We’ve got [API docs](http://lodash.com/docs), [benchmarks](http://lodash.com/benchmarks), and [unit tests](http://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/bestiejs/lodash/wiki/Roadmap).
|
||||
|
||||
## So What's The Secret?
|
||||
## Screencasts
|
||||
|
||||
Lo-Dash's performance is gained by avoiding native methods, instead opting for simplified non-ES5 compliant methods optimized for common usage, and by leveraging function compilation to reduce the number of overall function calls.
|
||||
For more information check out these screencasts over Lo-Dash:
|
||||
|
||||
## What else?
|
||||
* [Introducing Lo-Dash](https://vimeo.com/44154599)
|
||||
* [Lo-Dash optimizations and custom builds](https://vimeo.com/44154601)
|
||||
* [Lo-Dash’s origin and why it’s a better utility belt](https://vimeo.com/44154600)
|
||||
* [Unit testing in Lo-Dash](https://vimeo.com/45865290)
|
||||
* [Lo-Dash’s approach to native method use](https://vimeo.com/48576012)
|
||||
|
||||
Lo-Dash comes with AMD loader support baked in, chainable `_.each`, and will [soon address](https://github.com/bestiejs/lodash/wiki/Roadmap) cross-browser object iteration issues.
|
||||
## Features
|
||||
|
||||
## Screencast
|
||||
* AMD loader support ([RequireJS](http://requirejs.org/), [curl.js](https://github.com/cujojs/curl), etc.)
|
||||
* [_.clone](http://lodash.com/docs#clone) supports *“deep”* cloning
|
||||
* [_.forEach](http://lodash.com/docs#forEach) is chainable and supports exiting iteration early
|
||||
* [_.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
|
||||
* [_.isPlainObject](http://lodash.com/docs#isPlainObject) checks if values are created by the `Object` constructor
|
||||
* [_.lateBind](http://lodash.com/docs#lateBind) for late binding
|
||||
* [_.merge](http://lodash.com/docs#merge) for a *“deep”* [_.extend](http://lodash.com/docs#extend)
|
||||
* [_.partial](http://lodash.com/docs#partial) for partial application without `this` binding
|
||||
* [_.pick](http://lodash.com/docs#pick) and [_.omit](http://lodash.com/docs#omit) accept `callback` and `thisArg` arguments
|
||||
* [_.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 "_.countBy, _.every, _.filter, _.find, _.forEach, _.groupBy, _.invoke, _.map, _.pluck, _.reduce, _.reduceRight, _.reject, _.some, _.sortBy, _.where") accept strings
|
||||
|
||||
For more information check out [this screencast](http://dl.dropbox.com/u/513327/allyoucanleet/post/20/file/screencast.mp4) over Lo-Dash.
|
||||
## Support
|
||||
|
||||
Lo-Dash has been tested in at least Chrome 5~22, Firefox 1~16, IE 6-10, Opera 9.25-12, Safari 3-6, Node.js 0.4.8-0.8.11, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC5.
|
||||
|
||||
## Custom builds
|
||||
|
||||
Custom builds make it easy to create lightweight versions of Lo-Dash containing only the methods you need.
|
||||
To top it off, we handle all method dependency and alias mapping for you.
|
||||
|
||||
* Backbone builds, with only methods required by Backbone, may be created using the `backbone` modifier argument.
|
||||
```bash
|
||||
lodash backbone
|
||||
```
|
||||
|
||||
* CSP builds, supporting default Content Security Policy restrictions, may be created using the `csp` modifier argument.
|
||||
```bash
|
||||
lodash csp
|
||||
```
|
||||
|
||||
* 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`, `_.defaults`, and `_.extend` in [strict mode](http://es5.github.com/#C), may be created using the `strict` modifier argument.
|
||||
```bash
|
||||
lodash strict
|
||||
```
|
||||
|
||||
* Underscore builds, tailored for projects already using Underscore, may be created using the `underscore` modifier argument.
|
||||
```bash
|
||||
lodash underscore
|
||||
```
|
||||
|
||||
Custom builds may be created using the following commands:
|
||||
|
||||
* Use the `category` argument to pass comma separated categories of methods to include in the build.<br>
|
||||
Valid categories (case-insensitive) are *“arrays”*, *“chaining”*, *“collections”*, *“functions”*, *“objects”*, and *“utilities”*.
|
||||
```bash
|
||||
lodash category=collections,functions
|
||||
lodash category="collections, functions"
|
||||
```
|
||||
|
||||
* Use the `exports` argument to pass comma separated names of ways to export the `LoDash` function.<br>
|
||||
Valid exports are *“amd”*, *“commonjs”*, *“global”*, *“node”*, and *“none”*.
|
||||
```bash
|
||||
lodash exports=amd,commonjs,node
|
||||
lodash exports="amd, commonjs, node"
|
||||
```
|
||||
|
||||
* Use the `iife` argument to specify code to replace the immediately-invoked function expression that wraps Lo-Dash.
|
||||
```bash
|
||||
lodash iife="!function(window,undefined){%output%}(this)"
|
||||
```
|
||||
|
||||
* Use the `include` argument to pass comma separated method/category names to include in the build.
|
||||
```bash
|
||||
lodash include=each,filter,map
|
||||
lodash include="each, filter, map"
|
||||
```
|
||||
|
||||
* Use the `minus` argument to pass comma separated method/category names to remove from those included in the build.
|
||||
```bash
|
||||
lodash underscore minus=result,shuffle
|
||||
lodash underscore minus="result, shuffle"
|
||||
```
|
||||
|
||||
* Use the `plus` argument to pass comma separated method/category names to add to those included in the build.
|
||||
```bash
|
||||
lodash backbone plus=random,template
|
||||
lodash backbone plus="random, template"
|
||||
```
|
||||
|
||||
* Use the `template` argument to pass the file path pattern used to match template files to precompile
|
||||
```bash
|
||||
lodash template="./*.jst"
|
||||
```
|
||||
|
||||
* Use the `settings` argument to pass the template settings used when precompiling templates
|
||||
```bash
|
||||
lodash settings="{interpolate:/\\{\\{([\\s\\S]+?)\\}\\}/g}"
|
||||
```
|
||||
|
||||
All arguments, except `legacy` with `csp` or `mobile`, may be combined.<br>
|
||||
Unless specified by `-o` or `--output`, all files created are saved to the current working directory.
|
||||
|
||||
The following options are also supported:
|
||||
|
||||
* `-c`, `--stdout` Write output to standard output
|
||||
* `-d`, `--debug` Write only the debug output
|
||||
* `-h`, `--help` Display help information
|
||||
* `-m`, `--minify` Write only the minified output
|
||||
* `-o`, `--output` Write output to a given path/filename
|
||||
* `-s`, `--silent` Skip status updates normally logged to the console
|
||||
* `-V`, `--version` Output current version of Lo-Dash
|
||||
|
||||
The `lodash` command-line utility is available when Lo-Dash is installed as a global package (i.e. `npm install -g lodash`).
|
||||
|
||||
## Installation and usage
|
||||
|
||||
In a browser:
|
||||
In browsers:
|
||||
|
||||
~~~ html
|
||||
```html
|
||||
<script src="lodash.js"></script>
|
||||
~~~
|
||||
```
|
||||
|
||||
Via [npm](http://npmjs.org/):
|
||||
Using [npm](http://npmjs.org/):
|
||||
|
||||
~~~ bash
|
||||
```bash
|
||||
npm install lodash
|
||||
~~~
|
||||
|
||||
npm install -g lodash
|
||||
npm link lodash
|
||||
```
|
||||
|
||||
In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
|
||||
|
||||
~~~ js
|
||||
```js
|
||||
var _ = require('lodash');
|
||||
~~~
|
||||
```
|
||||
|
||||
In [Narwhal](http://narwhaljs.org/) and [RingoJS v0.7.0-](http://ringojs.org/):
|
||||
**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 attempting to `require` it.
|
||||
|
||||
~~~ js
|
||||
In [RingoJS v0.7.0-](http://ringojs.org/):
|
||||
|
||||
```js
|
||||
var _ = require('lodash')._;
|
||||
~~~
|
||||
```
|
||||
|
||||
In [Rhino](http://www.mozilla.org/rhino/):
|
||||
|
||||
~~~ js
|
||||
```js
|
||||
load('lodash.js');
|
||||
~~~
|
||||
```
|
||||
|
||||
In an AMD loader like [RequireJS](http://requirejs.org/):
|
||||
|
||||
~~~ js
|
||||
// opt-in
|
||||
define.amd.lodash = true;
|
||||
|
||||
```js
|
||||
require({
|
||||
'paths': {
|
||||
'lodash': 'path/to/lodash'
|
||||
'underscore': 'path/to/lodash'
|
||||
}
|
||||
},
|
||||
['lodash'], function(_) {
|
||||
['underscore'], function(_) {
|
||||
console.log(_.VERSION);
|
||||
});
|
||||
~~~
|
||||
```
|
||||
|
||||
## Cloning this repo
|
||||
## Resolved Underscore.js issues
|
||||
|
||||
To clone this repository including all submodules, using Git 1.6.5 or later:
|
||||
* Add AMD loader support [[#431](https://github.com/documentcloud/underscore/pull/431), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L118-140)]
|
||||
* Allow iteration of objects with a `length` property [[#799](https://github.com/documentcloud/underscore/pull/799), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L510-516)]
|
||||
* 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.8.2/test/test.js#L470-487)]
|
||||
* Fix cross-browser object iteration bugs [[#60](https://github.com/documentcloud/underscore/issues/60), [#376](https://github.com/documentcloud/underscore/issues/376), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L523-547)]
|
||||
* Methods should work on pages with incorrectly shimmed native methods [[#7](https://github.com/documentcloud/underscore/issues/7), [#742](https://github.com/documentcloud/underscore/issues/742), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L142-148)]
|
||||
* `_.clone` should allow `deep` cloning [[#595](https://github.com/documentcloud/underscore/pull/595), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L214-225)]
|
||||
* `_.contains` should work with strings [[#667](https://github.com/documentcloud/underscore/pull/667), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L267-276)]
|
||||
* `_.extend` should recursively extend objects [[#379](https://github.com/documentcloud/underscore/pull/379), [#718](https://github.com/documentcloud/underscore/issues/718), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L968-990)]
|
||||
* `_.forEach` should be chainable [[#142](https://github.com/documentcloud/underscore/issues/142), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L465-468)]
|
||||
* `_.forEach` should allow exiting iteration early [[#211](https://github.com/documentcloud/underscore/issues/211), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L553-571)]
|
||||
* `_.isEmpty` should support jQuery/MooTools DOM query collections [[#690](https://github.com/documentcloud/underscore/pull/690), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L712-717)]
|
||||
* `_.isObject` should avoid V8 bug [#2291](http://code.google.com/p/v8/issues/detail?id=2291) [[#605](https://github.com/documentcloud/underscore/issues/605), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L772-784)]
|
||||
* `_.keys` should work with `arguments` objects cross-browser [[#396](https://github.com/documentcloud/underscore/issues/396), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L865-867)]
|
||||
* `_.range` should coerce arguments to numbers [[#634](https://github.com/documentcloud/underscore/issues/634), [#683](https://github.com/documentcloud/underscore/issues/683), [test](https://github.com/bestiejs/lodash/blob/v0.8.2/test/test.js#L1243-1246)]
|
||||
|
||||
~~~ bash
|
||||
git clone --recursive https://github.com/bestiejs/lodash.git
|
||||
cd lodash.js
|
||||
~~~
|
||||
## Optimized methods <sup>(50+)</sup>
|
||||
|
||||
For older Git versions, just use:
|
||||
* `_.bind`
|
||||
* `_.bindAll`
|
||||
* `_.compact`
|
||||
* `_.contains`, `_.include`
|
||||
* `_.defaults`
|
||||
* `_.difference`
|
||||
* `_.each`
|
||||
* `_.every`, `_.all`
|
||||
* `_.extend`
|
||||
* `_.filter`, `_.select`
|
||||
* `_.find`, `_.detect`
|
||||
* `_.flatten`
|
||||
* `_.forEach`, `_.each`
|
||||
* `_.functions`, `_.methods`
|
||||
* `_.groupBy`
|
||||
* `_.indexOf`
|
||||
* `_.intersection`
|
||||
* `_.invert`
|
||||
* `_.invoke`
|
||||
* `_.isArguments`
|
||||
* `_.isDate`
|
||||
* `_.isFinite`
|
||||
* `_.isFunction`
|
||||
* `_.isObject`
|
||||
* `_.isNumber`
|
||||
* `_.isRegExp`
|
||||
* `_.isString`
|
||||
* `_.keys`
|
||||
* `_.lastIndexOf`
|
||||
* `_.map`, `_.collect`
|
||||
* `_.max`
|
||||
* `_.memoize`
|
||||
* `_.min`
|
||||
* `_.mixin`
|
||||
* `_.omit`
|
||||
* `_.pairs`
|
||||
* `_.pick`
|
||||
* `_.pluck`
|
||||
* `_.reduce`, `_.foldl`, `_.inject`
|
||||
* `_.reject`
|
||||
* `_.result`
|
||||
* `_.shuffle`
|
||||
* `_.some`, `_.any`
|
||||
* `_.sortBy`
|
||||
* `_.sortedIndex`
|
||||
* `_.template`
|
||||
* `_.throttle`
|
||||
* `_.toArray`
|
||||
* `_.union`
|
||||
* `_.uniq`, `_.unique`
|
||||
* `_.values`
|
||||
* `_.where`
|
||||
* `_.without`
|
||||
* `_.wrap`
|
||||
* `_.zip`
|
||||
* plus all `_(…)` method wrappers
|
||||
|
||||
~~~ bash
|
||||
git clone https://github.com/bestiejs/lodash.git
|
||||
cd lodash
|
||||
git submodule update --init
|
||||
~~~
|
||||
## Release Notes
|
||||
|
||||
Feel free to fork and send pull requests if you see improvements!
|
||||
### <sup>v0.8.2</sup>
|
||||
|
||||
* Ensured `_.map` returns an array when passed a falsey collection
|
||||
* Ensured `_.throttle` clears its timeout when `func` is called
|
||||
* Made `_.max`, `_.min`, `_.shuffle` support iterating objects
|
||||
* Reduced `createIterator`, `_.clone`, and `_.compact`
|
||||
* Re-optimized `_.max`, `_.min`, and `_.sortedIndex`
|
||||
|
||||
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
|
||||
|
||||
@@ -102,3 +301,5 @@ Feel free to fork and send pull requests if you see improvements!
|
||||
|
||||
* [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")
|
||||
|
||||
375
build/minify.js
Executable file
@@ -0,0 +1,375 @@
|
||||
#!/usr/bin/env node
|
||||
;(function() {
|
||||
'use strict';
|
||||
|
||||
/** The Node filesystem, path, `zlib`, and child process modules */
|
||||
var fs = require('fs'),
|
||||
gzip = require('zlib').gzip,
|
||||
path = require('path'),
|
||||
spawn = require('child_process').spawn;
|
||||
|
||||
/** The directory that is the base of the repository */
|
||||
var basePath = fs.realpathSync(path.join(__dirname, '..'));
|
||||
|
||||
/** The directory where the Closure Compiler is located */
|
||||
var closurePath = path.join(basePath, 'vendor', 'closure-compiler', 'compiler.jar');
|
||||
|
||||
/** Load other modules */
|
||||
var preprocess = require('./pre-compile'),
|
||||
postprocess = require('./post-compile'),
|
||||
uglifyJS = require('../vendor/uglifyjs/uglify-js');
|
||||
|
||||
/** Closure Compiler command-line options */
|
||||
var closureOptions = [
|
||||
'--compilation_level=ADVANCED_OPTIMIZATIONS',
|
||||
'--warning_level=QUIET'
|
||||
];
|
||||
|
||||
/** Reassign `existsSync` for older versions of Node */
|
||||
fs.existsSync || (fs.existsSync = path.existsSync);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* The exposed `minify` function minifies a given Lo-Dash `source` and invokes
|
||||
* the `onComplete` callback when finished.
|
||||
*
|
||||
* @param {Array|String} [source=''] The source to minify or array of commands.
|
||||
* @param {Object} [options={}] The options object.
|
||||
*/
|
||||
function minify(source, options) {
|
||||
source || (source = '');
|
||||
options || (options = {});
|
||||
|
||||
// juggle arguments
|
||||
if (Array.isArray(source)) {
|
||||
// convert commands to an options object
|
||||
options = source;
|
||||
|
||||
var filePath = options[options.length - 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');
|
||||
|
||||
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 = {
|
||||
'isSilent': isSilent,
|
||||
'isTemplate': isTemplate,
|
||||
'outputPath': outputPath
|
||||
};
|
||||
|
||||
source = fs.readFileSync(filePath, 'utf8');
|
||||
}
|
||||
new Minify(source, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* The Minify constructor used to keep state of each `minify` invocation.
|
||||
*
|
||||
* @private
|
||||
* @constructor
|
||||
* @param {String} source The source to minify.
|
||||
* @param {Object} options The options object.
|
||||
*/
|
||||
function Minify(source, options) {
|
||||
// juggle arguments
|
||||
if (typeof source == 'object' && source) {
|
||||
options = source || options;
|
||||
source = options.source || '';
|
||||
}
|
||||
this.compiled = {};
|
||||
this.hybrid = {};
|
||||
this.uglified = {};
|
||||
this.isSilent = !!options.isSilent;
|
||||
this.isTemplate = !!options.isTemplate;
|
||||
this.outputPath = options.outputPath;
|
||||
|
||||
source = preprocess(source, options);
|
||||
this.source = source;
|
||||
|
||||
this.onComplete = options.onComplete || function(source) {
|
||||
fs.writeFileSync(this.outputPath, source, 'utf8');
|
||||
};
|
||||
|
||||
// begin the minification process
|
||||
closureCompile.call(this, source, onClosureCompile.bind(this));
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Compresses a `source` string using the Closure Compiler. Yields the
|
||||
* minified result, and any exceptions encountered, to a `callback` function.
|
||||
*
|
||||
* @private
|
||||
* @param {String} source The JavaScript source to minify.
|
||||
* @param {String} [message] The message to log.
|
||||
* @param {Function} callback The function to call once the process completes.
|
||||
*/
|
||||
function closureCompile(source, message, callback) {
|
||||
var options = closureOptions.slice();
|
||||
|
||||
// use simple optimizations when minifying template files
|
||||
if (this.isTemplate) {
|
||||
options = options.map(function(value) {
|
||||
return value.replace(/^(compilation_level)=.+$/, '$1=SIMPLE_OPTIMIZATIONS');
|
||||
});
|
||||
}
|
||||
|
||||
// the standard error stream, standard output stream, and Closure Compiler process
|
||||
var error = '',
|
||||
output = '',
|
||||
compiler = spawn('java', ['-jar', closurePath].concat(options));
|
||||
|
||||
// juggle arguments
|
||||
if (typeof message == 'function') {
|
||||
callback = message;
|
||||
message = null;
|
||||
}
|
||||
|
||||
if (!this.isSilent) {
|
||||
console.log(message == null
|
||||
? 'Compressing ' + path.basename(this.outputPath, '.js') + ' using the Closure Compiler...'
|
||||
: message
|
||||
);
|
||||
}
|
||||
|
||||
compiler.stdout.on('data', function(data) {
|
||||
// append the data to the output stream
|
||||
output += data;
|
||||
});
|
||||
|
||||
compiler.stderr.on('data', function(data) {
|
||||
// append the error message to the error stream
|
||||
error += data;
|
||||
});
|
||||
|
||||
compiler.on('exit', function(status) {
|
||||
var exception = null;
|
||||
|
||||
// `status` contains the process exit code
|
||||
if (status) {
|
||||
exception = new Error(error);
|
||||
exception.status = status;
|
||||
}
|
||||
callback(exception, output);
|
||||
});
|
||||
|
||||
// proxy the standard input to the Closure Compiler
|
||||
compiler.stdin.end(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compresses a `source` string using UglifyJS. Yields the result to a
|
||||
* `callback` function. This function is synchronous; the `callback` is used
|
||||
* for symmetry.
|
||||
*
|
||||
* @private
|
||||
* @param {String} source The JavaScript source to minify.
|
||||
* @param {String} [message] The message to log.
|
||||
* @param {Function} callback The function to call once the process completes.
|
||||
*/
|
||||
function uglify(source, message, callback) {
|
||||
var exception,
|
||||
result,
|
||||
ugly = uglifyJS.uglify;
|
||||
|
||||
// juggle arguments
|
||||
if (typeof message == 'function') {
|
||||
callback = message;
|
||||
message = null;
|
||||
}
|
||||
|
||||
if (!this.isSilent) {
|
||||
console.log(message == null
|
||||
? 'Compressing ' + path.basename(this.outputPath, '.js') + ' using UglifyJS...'
|
||||
: message
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
result = ugly.gen_code(
|
||||
// enable unsafe transformations
|
||||
ugly.ast_squeeze_more(
|
||||
ugly.ast_squeeze(
|
||||
// munge variable and function names, excluding the special `define`
|
||||
// function exposed by AMD loaders
|
||||
ugly.ast_mangle(uglifyJS.parser.parse(source), {
|
||||
'except': ['define']
|
||||
}
|
||||
))), {
|
||||
'ascii_only': true
|
||||
});
|
||||
} catch(e) {
|
||||
exception = e;
|
||||
}
|
||||
// lines are restricted to 500 characters for consistency with the Closure Compiler
|
||||
callback(exception, result && ugly.split_lines(result, 500));
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* The `closureCompile()` callback.
|
||||
*
|
||||
* @private
|
||||
* @param {Object|Undefined} exception The error object.
|
||||
* @param {String} result The resulting minified source.
|
||||
*/
|
||||
function onClosureCompile(exception, result) {
|
||||
if (exception) {
|
||||
throw exception;
|
||||
}
|
||||
// store the post-processed Closure Compiler result and gzip it
|
||||
this.compiled.source = result = postprocess(result);
|
||||
gzip(result, onClosureGzip.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* The Closure Compiler `gzip` callback.
|
||||
*
|
||||
* @private
|
||||
* @param {Object|Undefined} exception The error object.
|
||||
* @param {Buffer} result The resulting gzipped source.
|
||||
*/
|
||||
function onClosureGzip(exception, result) {
|
||||
if (exception) {
|
||||
throw exception;
|
||||
}
|
||||
if (!this.isSilent) {
|
||||
console.log('Done. Size: %d bytes.', result.length);
|
||||
}
|
||||
|
||||
// store the gzipped result and report the size
|
||||
this.compiled.gzip = result;
|
||||
|
||||
// next, minify the source using only UglifyJS
|
||||
uglify.call(this, this.source, onUglify.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* The `uglify()` callback.
|
||||
*
|
||||
* @private
|
||||
* @param {Object|Undefined} exception The error object.
|
||||
* @param {String} result The resulting minified source.
|
||||
*/
|
||||
function onUglify(exception, result) {
|
||||
if (exception) {
|
||||
throw exception;
|
||||
}
|
||||
// store the post-processed Uglified result and gzip it
|
||||
this.uglified.source = result = postprocess(result);
|
||||
gzip(result, onUglifyGzip.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* The UglifyJS `gzip` callback.
|
||||
*
|
||||
* @private
|
||||
* @param {Object|Undefined} exception The error object.
|
||||
* @param {Buffer} result The resulting gzipped source.
|
||||
*/
|
||||
function onUglifyGzip(exception, result) {
|
||||
if (exception) {
|
||||
throw exception;
|
||||
}
|
||||
if (!this.isSilent) {
|
||||
console.log('Done. Size: %d bytes.', result.length);
|
||||
}
|
||||
var message = 'Compressing ' + path.basename(this.outputPath, '.js') + ' using hybrid minification...';
|
||||
|
||||
// store the gzipped result and report the size
|
||||
this.uglified.gzip = result;
|
||||
|
||||
// next, minify the Closure Compiler minified source using UglifyJS
|
||||
uglify.call(this, this.compiled.source, message, onHybrid.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* The hybrid `uglify()` callback.
|
||||
*
|
||||
* @private
|
||||
* @param {Object|Undefined} exception The error object.
|
||||
* @param {String} result The resulting minified source.
|
||||
*/
|
||||
function onHybrid(exception, result) {
|
||||
if (exception) {
|
||||
throw exception;
|
||||
}
|
||||
// store the post-processed Uglified result and gzip it
|
||||
this.hybrid.source = result = postprocess(result);
|
||||
gzip(result, onHybridGzip.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* The hybrid `gzip` callback.
|
||||
*
|
||||
* @private
|
||||
* @param {Object|Undefined} exception The error object.
|
||||
* @param {Buffer} result The resulting gzipped source.
|
||||
*/
|
||||
function onHybridGzip(exception, result) {
|
||||
if (exception) {
|
||||
throw exception;
|
||||
}
|
||||
if (!this.isSilent) {
|
||||
console.log('Done. Size: %d bytes.', result.length);
|
||||
}
|
||||
// store the gzipped result and report the size
|
||||
this.hybrid.gzip = result;
|
||||
|
||||
// finish by choosing the smallest compressed file
|
||||
onComplete.call(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* The callback executed after JavaScript source is minified and gzipped.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function onComplete() {
|
||||
var compiled = this.compiled,
|
||||
hybrid = this.hybrid,
|
||||
uglified = this.uglified;
|
||||
|
||||
// select the smallest gzipped file and use its minified counterpart as the
|
||||
// official minified release (ties go to Closure Compiler)
|
||||
var min = Math.min(compiled.gzip.length, hybrid.gzip.length, uglified.gzip.length);
|
||||
|
||||
// pass the minified source to the minify instances "onComplete" callback
|
||||
this.onComplete(
|
||||
compiled.gzip.length == min
|
||||
? compiled.source
|
||||
: uglified.gzip.length == min
|
||||
? uglified.source
|
||||
: hybrid.source
|
||||
);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
// expose `minify`
|
||||
if (module != require.main) {
|
||||
module.exports = minify;
|
||||
}
|
||||
else {
|
||||
// read the Lo-Dash source file from the first argument if the script
|
||||
// was invoked directly (e.g. `node minify.js source.js`) and write to
|
||||
// `<filename>.min.js`
|
||||
(function() {
|
||||
var options = process.argv;
|
||||
if (options.length < 3) {
|
||||
return;
|
||||
}
|
||||
minify(options);
|
||||
}());
|
||||
}
|
||||
}());
|
||||
@@ -6,31 +6,49 @@
|
||||
var fs = require('fs');
|
||||
|
||||
/** The minimal license/copyright template */
|
||||
var licenseTemplate =
|
||||
'/*!\n' +
|
||||
' Lo-Dash @VERSION github.com/bestiejs/lodash/blob/master/LICENSE.txt\n' +
|
||||
' Underscore.js 1.3.3 github.com/documentcloud/underscore/blob/master/LICENSE\n' +
|
||||
'*/';
|
||||
var licenseTemplate = {
|
||||
'lodash':
|
||||
'/*!\n' +
|
||||
' Lo-Dash @VERSION lodash.com/license\n' +
|
||||
' Underscore.js 1.4.2 underscorejs.org/LICENSE\n' +
|
||||
'*/',
|
||||
'underscore':
|
||||
'/*! Underscore.js @VERSION underscorejs.org/LICENSE */'
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Post-process a given minified JavaScript `source`, preparing it for
|
||||
* Post-process a given minified Lo-Dash `source`, preparing it for
|
||||
* deployment.
|
||||
*
|
||||
* @private
|
||||
* @param {String} source The source to process.
|
||||
* @returns {String} Returns the processed source.
|
||||
*/
|
||||
function postprocess(source) {
|
||||
// set the version
|
||||
var license = licenseTemplate.replace('@VERSION', (/VERSION:([\'"])(.*?)\1/).exec(source).pop());
|
||||
// move vars exposed by Closure Compiler into the IIFE
|
||||
source = source.replace(/^([^(\n]+)\s*(\(function[^)]+\){)/, '$2$1');
|
||||
// use double quotes consistently
|
||||
source = source.replace(/'use strict'/, '"use strict"');
|
||||
source = source.replace(/^((?:(['"])use strict\2;)?(?:var (?:[a-z]+=(?:!0|!1|null)[,;])+)?)([\s\S]*?function[^)]+\){)/, '$3$1');
|
||||
|
||||
// unescape properties (i.e. foo["bar"] => foo.bar)
|
||||
source = source.replace(/(\w)\["([^."]+)"\]/g, function(match, left, right) {
|
||||
return /\W/.test(right) ? match : (left + '.' + right);
|
||||
});
|
||||
|
||||
// correct AMD module definition for AMD build optimizers
|
||||
source = source.replace(/("function")\s*==\s*(typeof define)\s*&&\s*\(?\s*("object")\s*==\s*(typeof define\.amd)\s*&&\s*(define\.amd)\s*\)?/, '$2==$1&&$4==$3&&$5');
|
||||
|
||||
// add trailing semicolon
|
||||
if (source) {
|
||||
source = source.replace(/[\s;]*$/, ';');
|
||||
}
|
||||
// exit early if version snippet isn't found
|
||||
var snippet = /VERSION\s*[=:]\s*([\'"])(.*?)\1/.exec(source);
|
||||
if (!snippet) {
|
||||
return source;
|
||||
}
|
||||
// add license
|
||||
return license + '\n;' + source;
|
||||
return licenseTemplate[/call\(this\);?$/.test(source) ? 'underscore' : 'lodash']
|
||||
.replace('@VERSION', snippet[2]) + '\n;' + source;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@@ -38,13 +56,20 @@
|
||||
// expose `postprocess`
|
||||
if (module != require.main) {
|
||||
module.exports = postprocess;
|
||||
} else {
|
||||
// read the JavaScript source file from the first argument if the script
|
||||
}
|
||||
else {
|
||||
// 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
|
||||
// the same file
|
||||
(function() {
|
||||
var source = fs.readFileSync(process.argv[2], 'utf8');
|
||||
fs.writeFileSync(process.argv[2], postprocess(source), 'utf8');
|
||||
var options = process.argv;
|
||||
if (options.length < 3) {
|
||||
return;
|
||||
}
|
||||
var filePath = options[options.length - 1],
|
||||
source = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
fs.writeFileSync(filePath, postprocess(source), 'utf8');
|
||||
}());
|
||||
}
|
||||
}());
|
||||
|
||||
@@ -5,189 +5,431 @@
|
||||
/** The Node filesystem module */
|
||||
var fs = require('fs');
|
||||
|
||||
/** Used to minify string values embedded in compiled strings */
|
||||
var compiledValues = [
|
||||
'arrays',
|
||||
'objects'
|
||||
];
|
||||
|
||||
/** Used to minify variables embedded in compiled strings */
|
||||
var compiledVars = [
|
||||
'accumulator',
|
||||
'array',
|
||||
'arrayClass',
|
||||
'bind',
|
||||
'argsIndex',
|
||||
'argsLength',
|
||||
'callback',
|
||||
'className',
|
||||
'collection',
|
||||
'computed',
|
||||
'concat',
|
||||
'current',
|
||||
'false',
|
||||
'funcClass',
|
||||
'createCallback',
|
||||
'ctor',
|
||||
'hasOwnProperty',
|
||||
'identity',
|
||||
'index',
|
||||
'indexOf',
|
||||
'Infinity',
|
||||
'initial',
|
||||
'isArray',
|
||||
'isEmpty',
|
||||
'iteratee',
|
||||
'length',
|
||||
'nativeKeys',
|
||||
'object',
|
||||
'Math',
|
||||
'property',
|
||||
'ownIndex',
|
||||
'ownProps',
|
||||
'prop',
|
||||
'propertyIsEnumerable',
|
||||
'propIndex',
|
||||
'props',
|
||||
'result',
|
||||
'skipProto',
|
||||
'slice',
|
||||
'source',
|
||||
'stringClass',
|
||||
'target',
|
||||
'thisArg',
|
||||
'toString',
|
||||
'true',
|
||||
'undefined',
|
||||
'value',
|
||||
'values'
|
||||
|
||||
// lesser used variables
|
||||
'accumulator',
|
||||
'args',
|
||||
'arrayLikeClasses',
|
||||
'ArrayProto',
|
||||
'bind',
|
||||
'callee',
|
||||
'className',
|
||||
'compareAscending',
|
||||
'forIn',
|
||||
'found',
|
||||
'funcs',
|
||||
'indexOf',
|
||||
'indicator',
|
||||
'isArguments',
|
||||
'isArr',
|
||||
'isArray',
|
||||
'isFunc',
|
||||
'isFunction',
|
||||
'isPlainObject',
|
||||
'methodName',
|
||||
'noaccum',
|
||||
'noop',
|
||||
'objectClass',
|
||||
'objectTypes',
|
||||
'pass',
|
||||
'properties',
|
||||
'property',
|
||||
'propsLength',
|
||||
'source',
|
||||
'stackA',
|
||||
'stackB',
|
||||
'stackLength',
|
||||
'target'
|
||||
];
|
||||
|
||||
/** Used to minify `iterationFactory` option properties */
|
||||
var iterationFactoryOptions = [
|
||||
'afterLoop',
|
||||
/** Used to minify `compileIterator` option properties */
|
||||
var iteratorOptions = [
|
||||
'args',
|
||||
'array',
|
||||
'arrayBranch',
|
||||
'beforeLoop',
|
||||
'bottom',
|
||||
'exits',
|
||||
'firstArg',
|
||||
'hasDontEnumBug',
|
||||
'inLoop',
|
||||
'init',
|
||||
'iterate',
|
||||
'loopExp',
|
||||
'isKeysFast',
|
||||
'object',
|
||||
'returns',
|
||||
'objectBranch',
|
||||
'noArgsEnum',
|
||||
'noCharByIndex',
|
||||
'shadowed',
|
||||
'top',
|
||||
'useHas'
|
||||
'useHas',
|
||||
'useStrict'
|
||||
];
|
||||
|
||||
/** Used to minify variables and string values to a single character */
|
||||
var minNames = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
|
||||
minNames.push.apply(minNames, minNames.map(function(value) {
|
||||
return value + value;
|
||||
}));
|
||||
|
||||
/** Used protect the specified properties from getting minified */
|
||||
/** Used to protect the specified properties from getting minified */
|
||||
var propWhitelist = [
|
||||
'_',
|
||||
'__chain__',
|
||||
'__wrapped__',
|
||||
'after',
|
||||
'all',
|
||||
'amd',
|
||||
'any',
|
||||
'attachEvent',
|
||||
'bind',
|
||||
'bindAll',
|
||||
'chain',
|
||||
'clearTimeout',
|
||||
'clone',
|
||||
'collect',
|
||||
'compact',
|
||||
'compose',
|
||||
'contains',
|
||||
'countBy',
|
||||
'criteria',
|
||||
'debounce',
|
||||
'defaults',
|
||||
'defer',
|
||||
'delay',
|
||||
'detect',
|
||||
'difference',
|
||||
'drop',
|
||||
'each',
|
||||
'environment',
|
||||
'escape',
|
||||
'evaluate',
|
||||
'every',
|
||||
'exports',
|
||||
'extend',
|
||||
'filter',
|
||||
'find',
|
||||
'first',
|
||||
'flatten',
|
||||
'foldl',
|
||||
'foldr',
|
||||
'forEach',
|
||||
'forIn',
|
||||
'forOwn',
|
||||
'functions',
|
||||
'groupBy',
|
||||
'has',
|
||||
'head',
|
||||
'identity',
|
||||
'include',
|
||||
'index',
|
||||
'indexOf',
|
||||
'initial',
|
||||
'inject',
|
||||
'interpolate',
|
||||
'intersection',
|
||||
'invert',
|
||||
'invoke',
|
||||
'isArguments',
|
||||
'isArray',
|
||||
'isBoolean',
|
||||
'isDate',
|
||||
'isElement',
|
||||
'isEmpty',
|
||||
'isEqual',
|
||||
'isEqual',
|
||||
'isFinite',
|
||||
'lodash',
|
||||
'isFinite',
|
||||
'isFunction',
|
||||
'isNaN',
|
||||
'isNull',
|
||||
'isNumber',
|
||||
'isObject',
|
||||
'isPlainObject',
|
||||
'isRegExp',
|
||||
'isString',
|
||||
'isUndefined',
|
||||
'keys',
|
||||
'last',
|
||||
'lastIndexOf',
|
||||
'lateBind',
|
||||
'map',
|
||||
'max',
|
||||
'memoize',
|
||||
'merge',
|
||||
'methods',
|
||||
'min',
|
||||
'mixin',
|
||||
'noConflict',
|
||||
'object',
|
||||
'omit',
|
||||
'once',
|
||||
'opera',
|
||||
'pairs',
|
||||
'partial',
|
||||
'pick',
|
||||
'pluck',
|
||||
'random',
|
||||
'range',
|
||||
'reduce',
|
||||
'reduceRight',
|
||||
'reject',
|
||||
'rest',
|
||||
'result',
|
||||
'select',
|
||||
'setTimeout',
|
||||
'shuffle',
|
||||
'size',
|
||||
'some',
|
||||
'sortBy',
|
||||
'sortedIndex',
|
||||
'source',
|
||||
'tail',
|
||||
'take',
|
||||
'tap',
|
||||
'template',
|
||||
'templates',
|
||||
'templateSettings',
|
||||
'throttle',
|
||||
'times',
|
||||
'toArray',
|
||||
'unescape',
|
||||
'union',
|
||||
'uniq',
|
||||
'unique',
|
||||
'uniqueId',
|
||||
'value',
|
||||
'variable'
|
||||
'values',
|
||||
'variable',
|
||||
'VERSION',
|
||||
'where',
|
||||
'without',
|
||||
'wrap',
|
||||
'zip',
|
||||
|
||||
// properties used by underscore.js
|
||||
'_chain',
|
||||
'_wrapped'
|
||||
];
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Pre-process a given JavaScript `source`, preparing it for minification.
|
||||
* Pre-process a given Lo-Dash `source`, preparing it for minification.
|
||||
*
|
||||
* @private
|
||||
* @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.
|
||||
*/
|
||||
function preprocess(source) {
|
||||
function preprocess(source, options) {
|
||||
source || (source = '');
|
||||
options || (options = {});
|
||||
|
||||
// remove unrecognized JSDoc tags so Closure Compiler won't complain
|
||||
source = source.replace(/@(?:alias|category)\b.*/g, '');
|
||||
|
||||
if (options.isTemplate) {
|
||||
return source;
|
||||
}
|
||||
|
||||
// remove copyright to add later in post-compile.js
|
||||
source = source.replace(/\/\*![\s\S]+?\*\//, '');
|
||||
|
||||
// correct JSDoc tags for Closure Compiler
|
||||
source = source.replace(/@(?:alias|category)[^\n]*/g, '');
|
||||
|
||||
// add brackets to whitelisted properties so Closure Compiler won't mung them.
|
||||
// add brackets to whitelisted properties so Closure Compiler won't mung them
|
||||
// http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
|
||||
source = source.replace(RegExp('\\.(' + iterationFactoryOptions.concat(propWhitelist).join('|') + ')\\b', 'g'), "['$1']");
|
||||
source = source.replace(RegExp('\\.(' + propWhitelist.join('|') + ')\\b', 'g'), "['$1']");
|
||||
|
||||
// minify `sortBy` and `template` methods
|
||||
['sortBy', 'template'].forEach(function(methodName) {
|
||||
var properties = ['criteria', 'value'],
|
||||
snippet = source.match(RegExp('(\\n\\s*)function ' + methodName + '[\\s\\S]+?\\1}'))[0],
|
||||
result = snippet;
|
||||
// remove brackets from `_.escape()` in `_.template`
|
||||
source = source.replace(/__e *= *_\['escape']/g, '__e=_.escape');
|
||||
|
||||
// minify property strings
|
||||
properties.forEach(function(property, index) {
|
||||
result = result.replace(RegExp("'" + property + "'", 'g'), "'" + minNames[index] + "'");
|
||||
// remove brackets from `_.escape()` in underscore.js `_.template`
|
||||
source = source.replace(/_\['escape'\]\(__t'/g, '_.escape(__t');
|
||||
|
||||
// remove brackets from `collection.indexOf` in `_.contains`
|
||||
source = source.replace("collection['indexOf'](target)", 'collection.indexOf(target)');
|
||||
|
||||
// remove brackets from `result[length].value` in `_.sortBy`
|
||||
source = source.replace("result[length]['value']", 'result[length].value');
|
||||
|
||||
// remove whitespace from string literals
|
||||
source = source.replace(/'(?:(?=(\\?))\1.)*?'/g, function(string) {
|
||||
// avoids removing the '\n' of the `stringEscapes` object
|
||||
return string.replace(/\[object |delete |else |function | in |return\s+[\w']|throw |typeof |use strict|var |@ |'\\n'|\\\\n|\\n|\s+/g, function(match) {
|
||||
return match == false || match == '\\n' ? '' : match;
|
||||
});
|
||||
|
||||
// remove escaped newlines in strings
|
||||
result = result.replace(/\\n/g, '');
|
||||
|
||||
// replace with modified snippet
|
||||
source = source.replace(snippet, result);
|
||||
});
|
||||
|
||||
// minify all `iterationFactory` related snippets
|
||||
source.match(
|
||||
// add newline to `+"__p+='"` in underscore.js `_.template`
|
||||
source = source.replace(/\+"__p\+='"/g, '+"\\n__p+=\'"');
|
||||
|
||||
// remove whitespace from `_.template` related regexes
|
||||
source = source.replace(/(?:reEmptyString\w+|reInsertVariable) *=.+/g, function(match) {
|
||||
return match.replace(/ |\\n/g, '');
|
||||
});
|
||||
|
||||
// remove newline from double-quoted strings in `_.template`
|
||||
source = source
|
||||
.replace('"\';\\n__with ("', '"\';__with("')
|
||||
.replace('"\\n}__\\n__p += \'"', '"}____p+=\'"')
|
||||
.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`
|
||||
source = source.replace(/(?:\s*\/\/.*\n)* *var sourceURL[^;]+;|\+ *sourceURL/g, '');
|
||||
|
||||
// minify internal properties used by 'compareAscending', `_.merge`, and `_.sortBy`
|
||||
(function() {
|
||||
var properties = ['criteria', 'index', 'value'],
|
||||
snippets = source.match(/( +)(?:function compareAscending|var merge|var sortBy)\b[\s\S]+?\n\1}/g);
|
||||
|
||||
if (!snippets) {
|
||||
return;
|
||||
}
|
||||
snippets.forEach(function(snippet) {
|
||||
var modified = snippet,
|
||||
isCompilable = /(?:var merge|var sortBy)\b/.test(modified),
|
||||
isInlined = !/\bcreateIterator\b/.test(modified);
|
||||
|
||||
// minify properties
|
||||
properties.forEach(function(property, index) {
|
||||
var reBracketProp = RegExp("\\['(" + property + ")'\\]", 'g'),
|
||||
reDotProp = RegExp('\\.' + property + '\\b', 'g'),
|
||||
rePropColon = RegExp("([^?\\s])\\s*([\"'])?\\b" + property + "\\2 *:", 'g');
|
||||
|
||||
if (isCompilable) {
|
||||
// add quotes around properties in the inlined `_.merge` and `_.sortBy`
|
||||
// of the mobile build so Closure Compiler won't mung them
|
||||
if (isInlined) {
|
||||
modified = modified
|
||||
.replace(reBracketProp, "['" + minNames[index] + "']")
|
||||
.replace(reDotProp, "['" + minNames[index] + "']")
|
||||
.replace(rePropColon, "$1'" + minNames[index] + "':");
|
||||
}
|
||||
else {
|
||||
modified = modified
|
||||
.replace(reBracketProp, '.' + minNames[index])
|
||||
.replace(reDotProp, '.' + minNames[index])
|
||||
.replace(rePropColon, '$1' + minNames[index] + ':');
|
||||
}
|
||||
}
|
||||
else {
|
||||
modified = modified
|
||||
.replace(reBracketProp, "['" + minNames[index] + "']")
|
||||
.replace(reDotProp, '.' + minNames[index])
|
||||
.replace(rePropColon, "$1'" + minNames[index] + "':")
|
||||
|
||||
// correct `value.source` in regexp branch of `_.clone`
|
||||
if (property == 'source') {
|
||||
modified = modified.replace("value['" + minNames[index] + "']", "value['source']");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// replace with modified snippet
|
||||
source = source.replace(snippet, modified);
|
||||
});
|
||||
}());
|
||||
|
||||
// minify all compilable snippets
|
||||
var snippets = source.match(
|
||||
RegExp([
|
||||
// match variables storing `iterationFactory` options
|
||||
'var [a-zA-Z]+FactoryOptions\\s*=\\s*\\{[\\s\\S]+?};\\n',
|
||||
// match the the `iterationFactory` function
|
||||
'(\\n\\s*)function iterationFactory[\\s\\S]+?\\1}',
|
||||
// match methods created by `iterationFactor` calls
|
||||
'iterationFactory\\((?:[\'{]|[a-zA-Z]+,)[\\s\\S]+?\\);\\n'
|
||||
// match the `iteratorTemplate`
|
||||
'( +)var iteratorTemplate\\b[\\s\\S]+?\\n\\1}',
|
||||
// match methods created by `createIterator` calls
|
||||
'createIterator\\((?:{|[a-zA-Z]+)[\\s\\S]+?\\);\\n',
|
||||
// match variables storing `createIterator` options
|
||||
'( +)var [a-zA-Z]+IteratorOptions\\b[\\s\\S]+?\\n\\2}',
|
||||
// match the the `createIterator` function
|
||||
'( +)function createIterator\\b[\\s\\S]+?\\n\\3}'
|
||||
].join('|'), 'g')
|
||||
)
|
||||
.forEach(function(snippet, index) {
|
||||
var result = snippet;
|
||||
);
|
||||
|
||||
// add `true` and `false` arguments to be minified
|
||||
if (/function iterationFactory/.test(snippet)) {
|
||||
result = result
|
||||
.replace(/(Function\('[\s\S]+?)undefined/, '$1true,false,undefined')
|
||||
.replace(/\)\([^)]+/, '$&,true,false');
|
||||
// exit early if no compilable snippets
|
||||
if (!snippets) {
|
||||
return source;
|
||||
}
|
||||
|
||||
// replace with modified snippet early and clip snippet
|
||||
source = source.replace(snippet, result);
|
||||
snippet = result = result.replace(/\)\([\s\S]+$/, '');
|
||||
snippets.forEach(function(snippet, index) {
|
||||
var isCreateIterator = /function createIterator\b/.test(snippet),
|
||||
isIteratorTemplate = /var iteratorTemplate\b/.test(snippet),
|
||||
modified = snippet;
|
||||
|
||||
// add brackets to whitelisted properties so Closure Compiler won't mung them
|
||||
modified = modified.replace(RegExp('\\.(' + iteratorOptions.join('|') + ')\\b', 'g'), "['$1']");
|
||||
|
||||
if (isCreateIterator) {
|
||||
// replace with modified snippet early and clip snippet to the `factory`
|
||||
// call so other arguments aren't minified
|
||||
source = source.replace(snippet, modified);
|
||||
snippet = modified = modified.replace(/factory\([\s\S]+$/, '');
|
||||
}
|
||||
|
||||
// minify snippet variables/arguments
|
||||
// minify snippet variables / arguments
|
||||
compiledVars.forEach(function(variable, index) {
|
||||
result = result.replace(RegExp('([^.]\\b|\\\\n)' + variable + '\\b(?!\'\\s*[\\]:])', 'g'), '$1' + minNames[index]);
|
||||
// ensure properties in compiled strings aren't minified
|
||||
modified = modified.replace(RegExp('([^.]\\b)' + variable + '\\b(?!\' *[\\]:])', 'g'), '$1' + minNames[index]);
|
||||
|
||||
// correct `typeof x == 'object'`
|
||||
if (variable == 'object') {
|
||||
result = result.replace(RegExp("(typeof [^']+')" + minNames[index] + "'", 'g'), "$1object'");
|
||||
}
|
||||
// correct boolean literals
|
||||
if (variable == 'true' || variable == 'false') {
|
||||
result = result
|
||||
.replace(RegExp(':\\s*' + minNames[index] + '\\s*,', 'g'), ':' + variable + ',')
|
||||
.replace(RegExp('\\s*' + minNames[index] + '\\s*;', 'g'), variable + ';');
|
||||
modified = modified.replace(RegExp("(typeof [^']+')" + minNames[index] + "'", 'g'), "$1object'");
|
||||
}
|
||||
});
|
||||
|
||||
// minify snippet values
|
||||
compiledValues.forEach(function(value, index) {
|
||||
result = result.replace(RegExp("'" + value + "'", 'g'), "'" + minNames[index] + "'");
|
||||
});
|
||||
|
||||
// minify iterationFactory option property strings
|
||||
iterationFactoryOptions.forEach(function(property, index) {
|
||||
if (property == 'array' || property == 'object') {
|
||||
result = result.replace(RegExp("'" + property + "'(\\s*[\\]:])", 'g'), "'" + minNames[index] + "'$1");
|
||||
} else {
|
||||
result = result.replace(RegExp("'" + property + "'", 'g'), "'" + minNames[index] + "'");
|
||||
// minify `createIterator` option property names
|
||||
iteratorOptions.forEach(function(property, index) {
|
||||
if (isIteratorTemplate) {
|
||||
// minify property names as interpolated template variables
|
||||
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 regexes and accessors
|
||||
if (isCreateIterator) {
|
||||
modified = modified.replace(RegExp('([\\.|/])' + property + '\\b' , 'g'), '$1' + minNames[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// remove escaped newlines in strings
|
||||
result = result.replace(/\\n/g, '');
|
||||
|
||||
// replace with modified snippet
|
||||
source = source.replace(snippet, result);
|
||||
source = source.replace(snippet, modified);
|
||||
});
|
||||
|
||||
return source;
|
||||
@@ -198,13 +440,23 @@
|
||||
// expose `preprocess`
|
||||
if (module != require.main) {
|
||||
module.exports = preprocess;
|
||||
} else {
|
||||
// read the JavaScript source file from the first argument if the script
|
||||
}
|
||||
else {
|
||||
// read the Lo-Dash source file from the first argument if the script
|
||||
// was invoked directly (e.g. `node pre-compile.js source.js`) and write to
|
||||
// the same file
|
||||
(function() {
|
||||
var source = fs.readFileSync(process.argv[2], 'utf8');
|
||||
fs.writeFileSync(process.argv[2], preprocess(source), 'utf8');
|
||||
var options = process.argv;
|
||||
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');
|
||||
}());
|
||||
}
|
||||
}());
|
||||
|
||||
4463
doc/README.md
@@ -20,9 +20,10 @@
|
||||
|
||||
// generate Markdown
|
||||
$markdown = docdown(array(
|
||||
'path' => '../' . $file,
|
||||
'title' => 'Lo-Dash <sup>v0.1.0</sup>',
|
||||
'url' => 'https://github.com/bestiejs/lodash/blob/master/lodash.js'
|
||||
'path' => '../' . $file,
|
||||
'title' => 'Lo-Dash <sup>v0.8.2</sup>',
|
||||
'toc' => 'categories',
|
||||
'url' => 'https://github.com/bestiejs/lodash/blob/master/lodash.js'
|
||||
));
|
||||
|
||||
// save to a .md file
|
||||
|
||||
61
lodash.min.js
vendored
@@ -1,26 +1,39 @@
|
||||
/*!
|
||||
Lo-Dash 0.1.0 github.com/bestiejs/lodash/blob/master/LICENSE.txt
|
||||
Underscore.js 1.3.3 github.com/documentcloud/underscore/blob/master/LICENSE
|
||||
Lo-Dash 0.8.2 lodash.com/license
|
||||
Underscore.js 1.4.2 underscorejs.org/LICENSE
|
||||
*/
|
||||
;(function(r,h){"use strict";var n=!0,o=!1;function Q(a){return"[object Arguments]"==k.call(a)}function i(a){return new p(a)}function p(a){this.o=a}function g(){for(var a,b=-1,c={},d={},f={},e=["d","j","g","a"];++b<arguments.length;)for(a in arguments[b])f[a]=arguments[b][a];for(;a=e.pop();)"object"==typeof f[a]?(c[a]=f[a].c,d[a]=f[a].k):c[a]=d[a]=f[a]||"";a=f.b;var b=/^[^,]+/.exec(a)[0],e=f.h,j=f.i,g=!("v"==a||"b"==j),j=!("b"==a||"a"==j),h=f.n!==o;return Function("c,d,i,l,m,n,p,q,s,t,w,z,B,E,F,k,G",'"use strict";return function('+
|
||||
a+"){"+(f.m||"")+";"+("var o, y"+(e?"="+e:""))+";if("+b+"==G)return "+(f.f||"y")+";"+(g?"var u="+b+".length;o=-1;"+((j?"if(u===+u){":"")+(c.d||"")+";while("+(c.j||"++o<u")+"){"+c.g+"}"+(c.a||"")+";"+(j?"}":"")):"")+(j?(g?"else{":"")+(d.d||"")+";for("+(d.j||"o in "+b)+"){"+(h?"if(m.call("+/\S+$/.exec(d.j||b)[0]+",o)){":"")+d.g+(h?"}":"")+"}"+(d.a||"")+";"+(g?"}":""):"")+(f.e||"")+";return "+(f.l||"y")+"}")(D,u,ba,ca,s,R,E,Infinity,F,da,Math,l,G,k,n,o)}function S(a){return a.replace(ua,function(a,c){return y[c]})}
|
||||
function ea(a,b,c,d){var f=2<arguments.length;if(a==h)return c;d&&(b=u(b,d));var e=a.length;if(e===+e){for(e&&!f&&(c=a[--e]);e--;)c=b(c,a[e],e,a);return c}var j=T(a);for((e=j.length)&&!f&&(c=a[j[--e]]);e--;)f=j[e],c=b(c,a[f],f,a);return c}function fa(a,b,c){var d=0,f=a.length;for(c||(c=R);d<f;){var e=d+f>>1;c(a[e])<c(b)?d=e+1:f=e}return d}function U(a,b,c){return b==h||c?a[0]:l.call(a,0,b)}function H(a,b){return b?ba.apply([],a):z(a,function(a,b){if(F(b))return V.apply(a,H(b)),a;a.push(b);return a},
|
||||
[])}function E(a,b,c){var d;if(a==h)return-1;if(c)return c=fa(a,b),a[c]===b?c:-1;c=0;for(d=a.length;c<d;c++)if(a[c]===b)return c;return-1}function ga(a){var b=l.call(arguments,1);return W(I(a),function(a){return X(b,function(b){return 0<=E(b,a)})})}function ha(a,b,c){var d=a.length;return b==h||c?a[d-1]:l.call(a,-b||d)}function ia(a,b,c){return l.call(a,b==h||c?1:b)}function I(a,b,c){var c=c?A(a,c):a,d=[];3>a.length&&(b=n);z(c,function(c,e,j){if(b?ha(c)!==e||!c.length:0>E(c,e))c.push(e),d.push(a[j]);
|
||||
return c},[]);return d}function u(a,b){var c=l.call(arguments,2),d=c.length;return function(){c.length=d;V.apply(c,arguments);return a.apply(b,c)}}function ja(a,b,c){var d;return function(){var f=arguments,e=this;c&&!d&&a.apply(e,f);va(d);d=J(function(){d=h;c||a.apply(e,f)},b)}}function Y(a,b,c){c||(c=[]);if(a===b)return 0!==a||1/a==1/b;if(a==h||b==h)return a===b;a.p&&(a=a.o);b.p&&(b=b.o);if(a.isEqual&&q(a.isEqual))return a.isEqual(b);if(b.isEqual&&q(b.isEqual))return b.isEqual(a);var d=k.call(a);
|
||||
if(d!=k.call(b))return o;switch(d){case G:return a==""+b;case K:return a!=+a?b!=+b:0==a?1/a==1/b:a==+b;case ka:case la:return+a==+b;case ma:return a.source==b.source&&a.global==b.global&&a.multiline==b.multiline&&a.ignoreCase==b.ignoreCase}if("object"!=typeof a||"object"!=typeof b)return o;for(var f=c.length;f--;)if(c[f]==a)return n;var f=n,e=0;c.push(a);if(d==D){if(e=a.length,f=e==b.length)for(;e--&&(f=e in a==e in b&&Y(a[e],b[e],c)););}else{if("constructor"in a!="constructor"in b||a.constructor!=
|
||||
b.constructor)return o;for(var j in a)if(s.call(a,j)&&(e++,!(f=s.call(b,j)&&Y(a[j],b[j],c))))break;if(f){for(j in b)if(s.call(b,j)&&!e--)break;f=!e}}c.pop();return f}function q(a){return k.call(a)==ca}function R(a){return a}function na(a){t(L(a),function(b){var c=i[b]=a[b];i.prototype[b]=function(){var a=l.call(arguments);wa.call(a,this.o);a=c.apply(i,a);return this.p?(new p(a)).chain():a}})}var y={"\\":"\\","'":"'",r:"\r",n:"\n",t:"\t",u2028:"\u2028",u2029:"\u2029"};(function(){for(var a in y)y[y[a]]=
|
||||
a})();var Z="object"==typeof exports&&exports&&("object"==typeof global&&global&&global==global.global&&(r=global),exports),xa=0,ya=r._,za=/\\|'|\r|\n|\t|\u2028|\u2029/g,$=/.^/,ua=/\\(\\|'|r|n|t|u2028|u2029)/g,D="[object Array]",ka="[object Boolean]",la="[object Date]",ca="[object Function]",K="[object Number]",ma="[object RegExp]",G="[object String]",v=Array.prototype,M=Object.prototype,ba=v.concat,s=M.hasOwnProperty,V=v.push,l=v.slice,k=M.toString,wa=v.unshift,Aa=r.isFinite,M=Object.keys,va=r.clearTimeout,
|
||||
J=r.setTimeout,N={b:"b",m:"var I=i.apply([],z.call(arguments,1))",h:"[]",g:"if(p(I,b[o])<0)y.push(b[o])"},w={h:"F",g:"if(!e(g[o],o,g))return !y"},aa={b:"v",h:"v",d:"for(var A,j=1,u=arguments.length;j<u;j++){A=arguments[j]",j:"o in A",g:"v[o]=A[o]",n:o,a:"}"},B={h:"[]",g:"e(g[o],o,g)&&y.push(g[o])"},m={b:"g,e,D",m:"if(!e){e=n}else if(D){e=d(e,D)}",h:"g",g:"e(g[o],o,g)"},oa={b:"v",m:"if(v!==Object(v))throw TypeError()",h:"[]",g:"y.push(o)"},C={h:"",f:"[]",d:{c:"y=Array(u)",k:"y=[]"},g:{c:"y[o]=e(g[o],o,g)",
|
||||
k:"y[y.length]=e(g[o],o,g)"}},x={m:"var j,y=-q,h=y;if(!e){if(s(g)&&g[0]===+g[0])return w.max.apply(w,g);if(t(g))return y;}else if(D)e=d(e,D)",g:"j=e?e(g[o],o,g):g[o];if(j>=h)h=j,y=g[o]"},F=Array.isArray||function(a){return k.call(a)==D},da=g({b:"H",i:"b",m:"var f=E.call(H)",h:"F",d:"if(f==c||f==B)return !H.length",g:"return k"}),pa=g({b:"g,C",h:"k",g:"if(g[o]===C)return F"}),X=g(m,w),W=g(m,B),qa=g(m,{g:"if(e(g[o],o,g))return g[o]"}),t=g(m),A=g(m,C),ra=g(m,x),x=g(m,x,{m:x.m.replace("-","").replace("max",
|
||||
"min"),g:x.g.replace(">=","<")}),O=g(C,{b:"g,x",g:{c:"y[o]=g[o][x]",k:"y[y.length]=g[o][x]"}}),z=g({b:"g,e,a,D",m:"var r=arguments.length>2;if(D)e=d(e,D)",h:"a",d:{c:"if(!r)y=g[++o]"},g:{c:"y=e(y,g[o],o,g)",k:"y=r?e(y,g[o],o,g):(r=F,g[o])"}}),B=g(m,B,{g:"!"+B.g}),w=g(m,w,{h:"k",g:w.g.replace("!","")}),sa=g(C,{b:"g",g:{c:"y[o]=g[o]",k:"y[y.length]=g[o]"}}),C=g({b:"b",h:"[]",g:"if(b[o])y.push(b[o])"}),m=g(N),N=g(N,{m:"var I=z.call(arguments,1)",h:"[]"}),ta=g(aa,{g:"if(v[o]==G)"+aa.g}),P=g(aa),L=g(oa,
|
||||
{m:"",n:o,g:"if(E.call(v[o])==l)y.push(o)",l:"y.sort()"});Q(arguments)||(Q=function(a){return!(!a||!s.call(a,"callee"))});var T=M||g(oa);P(i,{VERSION:"0.1.0",templateSettings:{escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g},after:function(a,b){return 1>a?b():function(){if(1>--a)return b.apply(this,arguments)}},bind:u,bindAll:function(a){var b=arguments,c=1;1==b.length&&(c=0,b=L(a));for(var d=b.length;c<d;c++)a[b[c]]=u(a[b[c]],a);return a},chain:function(a){return(new p(a)).chain()},
|
||||
clone:function(a){return a!==Object(a)?a:F(a)?a.slice():P({},a)},compact:C,compose:function(){var a=arguments;return function(){for(var b=arguments,c=a.length;c--;)b=[a[c].apply(this,b)];return b[0]}},contains:pa,debounce:ja,defaults:ta,defer:function(a){var b=l.call(arguments,1);return J(function(){return a.apply(h,b)},1)},delay:function(a,b){var c=l.call(arguments,2);return J(function(){return a.apply(h,c)},b)},difference:m,escape:function(a){return(a+"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,
|
||||
">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/")},every:X,extend:P,filter:W,find:qa,first:U,flatten:H,forEach:t,functions:L,groupBy:function(a,b){var c={};if(!q(b))var d=b,b=function(a){return a[d]};t(a,function(a,e,d){e=b(a,e,d);(c[e]||(c[e]=[])).push(a)});return c},has:function(a,b){return s.call(a,b)},identity:R,indexOf:E,initial:function(a,b,c){return l.call(a,0,-(b==h||c?1:b))},intersection:ga,invoke:function(a,b){var c=l.call(arguments,2),d=q(b);return A(a,function(a){return(d?
|
||||
b||a:a[b]).apply(a,c)})},isArguments:Q,isArray:F,isBoolean:function(a){return a===n||a===o||k.call(a)==ka},isDate:function(a){return k.call(a)==la},isElement:function(a){return!!(a&&1==a.nodeType)},isEmpty:da,isEqual:Y,isFinite:function(a){return Aa(a)&&k.call(a)==K},isFunction:q,isNaN:function(a){return k.call(a)==K&&a!=+a},isNull:function(a){return null===a},isNumber:function(a){return k.call(a)==K},isObject:function(a){return a===Object(a)},isRegExp:function(a){return k.call(a)==ma},isString:function(a){return k.call(a)==
|
||||
G},isUndefined:function(a){return a===h},keys:T,last:ha,lastIndexOf:function(a,b){if(a==h)return-1;for(var c=a.length;c--;)if(a[c]===b)return c;return-1},map:A,max:ra,memoize:function(a,b){var c={};return function(){var d=b?b.apply(this,arguments):arguments[0];return s.call(c,d)?c[d]:c[d]=a.apply(this,arguments)}},min:x,mixin:na,noConflict:function(){r._=ya;return this},once:function(a){var b,c=o;return function(){if(c)return b;c=n;return b=a.apply(this,arguments)}},pick:function(a){for(var b,c=-1,
|
||||
d=H(l.call(arguments,1)),f=d.length,e={};++c<f;)b=d[c],b in a&&(e[b]=a[b]);return e},pluck:O,range:function(a,b,c){c||(c=1);2>arguments.length&&(b=a||0,a=0);for(var d=-1,f=Math.max(Math.ceil((b-a)/c),0),e=Array(f);++d<f;)e[d]=a,a+=c;return e},reduce:z,reduceRight:ea,reject:B,rest:ia,result:function(a,b){if(a==h)return null;var c=a[b];return q(c)?a[b]():c},shuffle:function(a){var b,c=[];t(a,function(a,f){b=Math.floor(Math.random()*(f+1));c[f]=c[b];c[b]=a});return c},size:function(a){var b=k.call(a);
|
||||
return b==D||b==G?a.length:T(a).length},some:w,sortBy:function(a,b,c){if(q(b))c&&(b=u(b,c));else var d=b,b=function(a){return a[d]};return O(A(a,function(c,e){return{a:b(c,e,a),b:c}}).sort(function(a,b){var c=a.a,d=b.a;return c===h?1:d===h?-1:c<d?-1:c>d?1:0}),"b")},sortedIndex:fa,tap:function(a,b){b(a);return a},template:function(a,b,c){function d(a){return f.call(this,a,i)}c=ta(c||{},i.templateSettings);a="__p+='"+a.replace(za,function(a){return"\\"+y[a]}).replace(c.escape||$,function(a,b){return"'+((__t=("+
|
||||
S(b)+"))==null?'':_['escape'](__t))+'"}).replace(c.interpolate||$,function(a,b){return"'+((__t=("+S(b)+"))==null?'':__t)+'"}).replace(c.evaluate||$,function(a,b){return"';"+S(b)+";__p+='"})+"';";c.variable||(a="with(object||{}){"+a+"}");var a='var __t,__j=Array.prototype.join,__p="";function print(){__p+=__j.call(arguments,"")}'+a+"return __p",f=Function(c.variable||"object","_",a);if(b)return f(b,i);d.source="function("+(c.variable||"object")+"){"+a+"}";return d},throttle:function(a,b){var c,d,f,
|
||||
e,g,i,k=ja(function(){d=g=o},b);return function(){c=arguments;e=this;i||(i=J(function(){i=h;d&&a.apply(e,c);k()},b));g?d=n:f=a.apply(e,c);k();g=n;return f}},times:function(a,b,c){c&&(b=u(b,c));for(c=0;c<a;c++)b(c)},toArray:function(a){if(!a)return[];if(q(a.toArray))return a.toArray();var b=a.length;return b===+b?l.call(a):sa(a)},union:function(){return I(H(arguments,n))},uniq:I,uniqueId:function(a){var b=xa++;return a?a+b:b},values:sa,without:N,wrap:function(a,b){return function(){var c=[a];V.apply(c,
|
||||
arguments);return b.apply(this,c)}},zip:function(){for(var a=-1,b=ra(O(arguments,"length")),c=Array(b);++a<b;)c[a]=O(arguments,a);return c},all:X,any:w,collect:A,detect:qa,each:t,foldl:z,foldr:ea,head:U,include:pa,inject:z,intersect:ga,methods:L,select:W,tail:ia,take:U,unique:I});p.prototype=i.prototype;na(i);t("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=v[a];i.prototype[a]=function(){var a=this.o;b.apply(a,arguments);a.length===0&&delete a[0];return this.p?(new p(a)).chain():
|
||||
a}});t(["concat","join","slice"],function(a){var b=v[a];p.prototype[a]=function(){var a=b.apply(this.o,arguments);return this.p?(new p(a)).chain():a}});P(p.prototype,{chain:function(){this.p=n;return this},value:function(){return this.o}});Z?"object"==typeof module&&module&&module.q==Z?(module.q=i)._=i:Z._=i:(r._=i,"function"==typeof define&&"object"==typeof define.amd&&define.amd&&define.amd.lodash&&define("lodash",function(){return i}))})(this);
|
||||
;(function(e,t){function s(e){if(e&&e.__wrapped__)return e;if(!(this instanceof s))return new s(e);this.__wrapped__=e}function o(e,t,n){t||(t=0);var r=e.length,i=r-t>=(n||H),s=i?{}:e;if(i)for(n=t-1;++n<r;){var o=e[n]+"";(Z.call(s,o)?s[o]:s[o]=[]).push(e[n])}return function(e){if(i){var n=e+"";return Z.call(s,n)&&-1<T(s[n],e)}return-1<T(s,e,t)}}function u(e,n){var r=e.b,i=n.b,e=e.a,n=n.a;if(e!==n){if(e>n||e===t)return 1;if(e<n||n===t)return-1}return r<i?-1:1}function a(e,t,n){function r(){var u=arguments
|
||||
,a=s?this:t;return i||(e=t[o]),n.length&&(u=u.length?n.concat(nt.call(u)):n),this instanceof r?(p.prototype=e.prototype,a=new p,(u=e.apply(a,u))&&Ht[typeof u]?u:a):e.apply(a,u)}var i=m(e),s=!n,o=e;return s&&(n=t),r}function f(e,n){return e?"function"!=typeof e?function(t){return t[e]}:n!==t?function(t,r,i){return e.call(n,t,r,i)}:e:A}function l(){for(var e={e:"",g:Et,i:"",j:Mt,m:Tt,n:kt,o:J,p:"",q:n,r:_t,c:{d:""},l:{d:""}},t,i=-1;t=arguments[++i];)for(var s in t){var o=t[s];/d|h/.test(s)?("string"==typeof
|
||||
o&&(o={b:o,k:o}),e.c[s]=o.b,e.l[s]=o.k):e[s]=o}t=e.a;if("d"!=(e.f=/^[^,]+/.exec(t)[0])||!e.c.h)e.c=r;i="",e.r&&(i+="'use strict';"),i+="var i,A,j="+e.f+",t="+(e.i||e.f)+";if(!"+e.f+")return t;"+e.p+";",e.c&&(i+="var k=j.length;i=-1;",e.l&&(i+="if(k===+k){"),e.n&&(i+="if(y.call(j)==w){j=j.split('')}"),i+=e.c.d+";while(++i<k){A=j[i];"+e.c.h+"}",e.l&&(i+="}"));if(e.l){e.c?i+="else {":e.m&&(i+="var k=j.length;i=-1;if(k&&O(j)){while(++i<k){A=j[i+=''];"+e.l.h+"}}else {"),e.g||(i+="var u=typeof j=='function'&&q.call(j,'prototype');"
|
||||
);if(e.j&&e.q)i+="var n=-1,o=Y[typeof j]?l(j):[],k=o.length;"+e.l.d+";while(++n<k){i=o[n];",e.g||(i+="if(!(u&&i=='prototype')){"),i+="A=j[i];"+e.l.h+"",e.g||(i+="}");else{i+=e.l.d+";for(i in j){";if(!e.g||e.q)i+="if(",e.g||(i+="!(u&&i=='prototype')"),!e.g&&e.q&&(i+="&&"),e.q&&(i+="h.call(j,i)"),i+="){";i+="A=j[i];"+e.l.h+";";if(!e.g||e.q)i+="}"}i+="}";if(e.g){i+="var g=j.constructor;";for(s=0;7>s;s++)i+="i='"+e.o[s]+"';if(","constructor"==e.o[s]&&(i+="!(g&&g.prototype===j)&&"),i+="h.call(j,i)){A=j[i];"+
|
||||
e.l.h+"}"}if(e.c||e.m)i+="}"}return i+=e.e+";return t",Function("D,E,F,I,e,f,J,h,M,O,Q,S,T,X,Y,l,q,v,w,y,z","var G=function("+t+"){"+i+"};return G")(Dt,_,L,u,Q,f,en,Z,T,v,$t,m,Jt,mt,Ht,ut,tt,nt,yt,rt)}function c(e){return"\\"+Bt[e]}function h(e){return Qt[e]}function p(){}function d(e){return Gt[e]}function v(e){return rt.call(e)==ct}function m(e){return"function"==typeof e}function g(e){var t=i;if(!e||"object"!=typeof e||v(e))return t;var n=e.constructor;return(!Lt||"function"==typeof e.toString||"string"!=typeof
|
||||
(e+""))&&(!m(n)||n instanceof n)?xt?(en(e,function(e,n,r){return t=!Z.call(r,n),i}),t===i):(en(e,function(e,n){t=n}),t===i||Z.call(e,t)):t}function y(e,t,n,s,o){if(e==r)return e;n&&(t=i);if(n=Ht[typeof e]){var u=rt.call(e);if(!Pt[u]||Nt&&v(e))return e;var a=u==ht,n=a||(u==mt?Jt(e):n)}if(!n||!t)return n?a?nt.call(e):Zt({},e):e;n=e.constructor;switch(u){case pt:case dt:return new n(+e);case vt:case yt:return new n(e);case gt:return n(e.source,U.exec(e))}s||(s=[]),o||(o=[]);for(u=s.length;u--;)if(s[
|
||||
u]==e)return o[u];var f=a?n(e.length):{};return s.push(e),o.push(f),(a?mn:tn)(e,function(e,n){f[n]=y(e,t,r,s,o)}),f}function b(e,t,s,o){if(e==r||t==r)return e===t;if(e===t)return 0!==e||1/e==1/t;if(Ht[typeof e]||Ht[typeof t])e=e.__wrapped__||e,t=t.__wrapped__||t;var u=rt.call(e);if(u!=rt.call(t))return i;switch(u){case pt:case dt:return+e==+t;case vt:return e!=+e?t!=+t:0==e?1/e==1/t:e==+t;case gt:case yt:return e==t+""}var a=Dt[u];if(Nt&&!a&&(a=v(e))&&!v(t)||!a&&(u!=mt||Lt&&("function"!=typeof e.
|
||||
toString&&"string"==typeof (e+"")||"function"!=typeof t.toString&&"string"==typeof (t+""))))return i;s||(s=[]),o||(o=[]);for(u=s.length;u--;)if(s[u]==e)return o[u]==t;var u=-1,f=n,l=0;s.push(e),o.push(t);if(a){l=e.length;if(f=l==t.length)for(;l--&&(f=b(e[l],t[l],s,o)););return f}a=e.constructor,f=t.constructor;if(a!=f&&(!m(a)||!(a instanceof a&&m(f)&&f instanceof f)))return i;for(var c in e)if(Z.call(e,c)&&(l++,!Z.call(t,c)||!b(e[c],t[c],s,o)))return i;for(c in t)if(Z.call(t,c)&&!(l--))return i;if(
|
||||
Et)for(;7>++u;)if(c=J[u],Z.call(e,c)&&(!Z.call(t,c)||!b(e[c],t[c],s,o)))return i;return n}function w(e,t,n){var r=-Infinity,i=-1,s=e?e.length:0,o=r;if(t||s!==+s)t=f(t,n),mn(e,function(e,n,i){n=t(e,n,i),n>r&&(r=n,o=e)});else for(;++i<s;)e[i]>o&&(o=e[i]);return o}function E(e,t,n,r){var s=e,o=e?e.length:0,u=3>arguments.length;if(o!==+o)var a=sn(e),o=a.length;else kt&&rt.call(e)==yt&&(s=e.split(""));return mn(e,function(e,f,l){f=a?a[--o]:--o,n=u?(u=i,s[f]):t.call(r,n,s[f],f,l)}),n}function S(e,t,n){
|
||||
if(e)return t==r||n?e[0]:nt.call(e,0,t)}function x(e,t){for(var n=-1,r=e?e.length:0,i=[];++n<r;){var s=e[n];$t(s)?et.apply(i,t?s:x(s)):i.push(s)}return i}function T(e,t,n){var r=-1,i=e?e.length:0;if("number"==typeof n)r=(0>n?at(0,i+n):n||0)-1;else if(n)return r=C(e,t),e[r]===t?r:-1;for(;++r<i;)if(e[r]===t)return r;return-1}function N(e,t,n){return e?nt.call(e,t==r||n?1:t):[]}function C(e,t,n,r){var i=0,s=e?e.length:i;if(n){n=f(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 k(e,t,n,r){var s=-1,o=e?e.length:0,u=[],a=[];"function"==typeof t&&(r=n,n=t,t=i);for(n=f(n,r);++s<o;)if(r=n(e[s],s,e),t?!s||a[a.length-1]!==r:0>T(a,r))a.push(r),u.push(e[s]);return u}function L(e,t){return Ot||it&&2<arguments.length?it.call.apply(it,arguments):a(e,t,nt.call(arguments,2))}function A(e){return e}function O(e){mn(nn(e),function(t){var r=s[t]=e[t];s.prototype[t]=function(){var e=[this.__wrapped__];return arguments.length&&et.apply(e,arguments)
|
||||
,e=r.apply(s,e),this.__chain__&&(e=new s(e),e.__chain__=n),e}})}var n=!0,r=null,i=!1,M="object"==typeof exports&&exports&&("object"==typeof global&&global&&global==global.global&&(e=global),exports),_=Array.prototype,D=Object.prototype,P=0,H=30,B=e._,j=/[-?+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/,F=/&(?:amp|lt|gt|quot|#x27);/g,I=/\b__p\+='';/g,q=/\b(__p\+=)''\+/g,R=/(__e\(.*?\)|\b__t\))\+'';/g,U=/\w*$/,z=/(?:__e|__t=)\(\s*(?![\d\s"']|this\.)/g,W=RegExp("^"+(D.valueOf+""
|
||||
).replace(/[.*+?^=!:${}()|[\]\/\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),X=/($^)/,V=/[&<>"']/g,$=/['\n\r\t\u2028\u2029\\]/g,J="constructor hasOwnProperty isPrototypeOf propertyIsEnumerable toLocaleString toString valueOf".split(" "),K=Math.ceil,Q=_.concat,G=Math.floor,Y=W.test(Y=Object.getPrototypeOf)&&Y,Z=D.hasOwnProperty,et=_.push,tt=D.propertyIsEnumerable,nt=_.slice,rt=D.toString,it=W.test(it=nt.bind)&&it,st=W.test(st=Array.isArray)&&st,ot=e.isFinite,ut=W.test(ut=Object.keys)&&ut
|
||||
,at=Math.max,ft=Math.min,lt=Math.random,ct="[object Arguments]",ht="[object Array]",pt="[object Boolean]",dt="[object Date]",vt="[object Number]",mt="[object Object]",gt="[object RegExp]",yt="[object String]",bt=e.clearTimeout,wt=e.setTimeout,Et,St,xt,Tt=n;(function(){function e(){this.x=1}var t={0:1,length:1},n=[];e.prototype={valueOf:1,y:1};for(var r in new e)n.push(r);for(r in arguments)Tt=!r;Et=4>(n+"").length,xt="x"!=n[0],St=(n.splice.call(t,0,1),t[0])})(1);var Nt=!v(arguments),Ct="x"!=nt.call("x"
|
||||
)[0],kt="xx"!="x"[0]+Object("x")[0];try{var Lt=("[object Object]",rt.call(e.document||0)==mt)}catch(At){}var Ot=it&&/\n|Opera/.test(it+rt.call(e.opera)),Mt=ut&&/^.+$|true/.test(ut+!!e.attachEvent),_t=!Ot,Dt={};Dt[pt]=Dt[dt]=Dt["[object Function]"]=Dt[vt]=Dt[mt]=Dt[gt]=i,Dt[ct]=Dt[ht]=Dt[yt]=n;var Pt={};Pt[ct]=Pt["[object Function]"]=i,Pt[ht]=Pt[pt]=Pt[dt]=Pt[vt]=Pt[mt]=Pt[gt]=Pt[yt]=n;var Ht={"boolean":i,"function":n,object:n,number:i,string:i,"undefined":i,unknown:n},Bt={"\\":"\\","'":"'","\n":"n"
|
||||
,"\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};s.templateSettings={escape:/<%-([\s\S]+?)%>/g,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""};var jt={a:"d,c,x",p:"c=f(c,x)",h:"if(c(A,i,d)===false)return t"},Ft={i:"{}",p:"c=f(c,x)",h:"var p=c(A,i,d);(h.call(t,p)?t[p]++:t[p]=1)"},It={i:"true",h:"if(!c(A,i,d))return!t"},qt={q:i,r:i,a:"m",p:"for(var a=1,b=arguments.length;a<b;a++){if(j=arguments[a]){",h:"t[i]=A",e:"}}"},Rt={i:"[]",h:"c(A,i,d)&&t.push(A)"},Ut={p:"c=f(c,x)"}
|
||||
,zt={h:{k:jt.h}},Wt={i:"d||[]",d:{b:"t=Array(k)",k:"t="+(Mt?"Array(k)":"[]")},h:{b:"t[i]=c(A,i,d)",k:"t"+(Mt?"[n]=":".push")+"(c(A,i,d))"}},Xt={q:i,a:"m,c,x",i:"{}",p:"var R=typeof c=='function';if(R)c=f(c,x);else var s=e.apply(E,arguments)",h:"if(R?!c(A,i,m):M(s,i)<0)t[i]=A"},Vt=l({a:"m",i:"{}",h:"t[A]=i"});Nt&&(v=function(e){return e?Z.call(e,"callee"):i});var $t=st||function(e){return rt.call(e)==ht};m(/x/)&&(m=function(e){return"[object Function]"==rt.call(e)});var Jt=Y?function(e){if(!e||"object"!=typeof
|
||||
e)return i;var t=e.valueOf,n="function"==typeof t&&(n=Y(t))&&Y(n);return n?e==n||Y(e)==n&&!v(e):g(e)}:g,Kt=l({a:"m",i:"[]",h:"t.push(i)"}),Qt={"&":"&","<":"<",">":">",'"':""","'":"'"},Gt=Vt(Qt),Yt=l(qt,{h:"if(t[i]==null)"+qt.h}),Zt=l(qt),en=l(jt,Ut,zt,{q:i}),tn=l(jt,Ut,zt),nn=l({q:i,a:"m",i:"[]",h:"S(A)&&t.push(i)",e:"t.sort()"}),rn=l({a:"A",i:"true",p:"var H=y.call(A),k=A.length;if(D[H]"+(Nt?"||O(A)":"")+"||(H==X&&k===+k&&S(A.splice)))return!k",h:{k:"return false"}}),sn=ut?function(
|
||||
e){var t=typeof e;return"function"==t&&tt.call(e,"prototype")?Kt(e):e&&Ht[t]?ut(e):[]}:Kt,on=l(qt,{a:"m,dd,N",p:"var P,C=arguments,a=0;if(N==I){var b=2,ee=C[3],ff=C[4]}else var b=C.length,ee=[],ff=[];while(++a<b){if(j=C[a]){",h:"if((dd=A)&&((P=Q(dd))||T(dd))){var K=false,gg=ee.length;while(gg--)if(K=ee[gg]==dd)break;if(K){t[i]=ff[gg]}else {ee.push(dd);ff.push(A=(A=t[i],P)?(Q(A)?A:[]):(T(A)?A:{}));t[i]=G(A,dd,I,ee,ff)}}else if(dd!=null)t[i]=dd"}),un=l(Xt),an=l({a:"m",i:"[]",h:"t"+(Mt?"[n]=":".push"
|
||||
)+"([i,A])"}),fn=l(Xt,{p:"if(typeof c!='function'){var i=0,s=e.apply(E,arguments),k=s.length;while(++i<k){var p=s[i];if(p in m)t[p]=m[p]}}else {c=f(c,x)",h:"if(c(A,i,m))t[i]=A",e:"}"}),ln=l({a:"m",i:"[]",h:"t.push(A)"}),cn=l({a:"d,hh",i:"false",n:i,d:{b:"if(y.call(d)==w)return d.indexOf(hh)>-1"},h:"if(A===hh)return true"}),hn=l(jt,Ft),pn=l(jt,It),dn=l(jt,Rt),vn=l(jt,Ut,{i:"z",h:"if(c(A,i,d))return A"}),mn=l(jt,Ut),gn=l(jt,Ft,{h:"var p=c(A,i,d);(h.call(t,p)?t[p]:t[p]=[]).push(A)"}),yn=l(Wt,{a:"d,U"
|
||||
,p:"var C=v.call(arguments,2),R=typeof U=='function'",h:{b:"t[i]=(R?U:A[U]).apply(A,C)",k:"t"+(Mt?"[n]=":".push")+"((R?U:A[U]).apply(A,C))"}}),bn=l(jt,Wt),wn=l(Wt,{a:"d,bb",h:{b:"t[i]=A[bb]",k:"t"+(Mt?"[n]=":".push")+"(A[bb])"}}),En=l({a:"d,c,B,x",i:"B",p:"var V=arguments.length<3;c=f(c,x)",d:{b:"if(V)t=j[++i]"},h:{b:"t=c(t,A,i,d)",k:"t=V?(V=false,A):c(t,A,i,d)"}}),Sn=l(jt,Rt,{h:"!"+Rt.h}),xn=l(jt,It,{i:"false",h:It.h.replace("!","")}),Tn=l(jt,Ft,Wt,{h:{b:"t[i]={a:c(A,i,d),b:i,c:A}",k:"t"+(Mt?"[n]="
|
||||
:".push")+"({a:c(A,i,d),b:i,c:A})"},e:"t.sort(I);k=t.length;while(k--)t[k]=t[k].c"}),Nn=l(Rt,{a:"d,aa",p:"var s=[];J(aa,function(A,p){s.push(p)});var cc=s.length",h:"for(var Z=true,r=0;r<cc;r++){var p=s[r];if(!(Z=A[p]===aa[p]))break}Z&&t.push(A)"}),Cn=l({q:i,r:i,a:"m",p:"var L=arguments,i=0,k=L.length;if(k>1){while(++i<k)t[L[i]]=F(t[L[i]],t);return t}",h:"if(S(A))t[i]=F(A,t)"});s.VERSION="0.8.2",s.after=function(e,t){return 1>e?t():function(){if(1>--e)return t.apply(this,arguments)}},s.bind=L,s.bindAll=
|
||||
Cn,s.chain=function(e){return e=new s(e),e.__chain__=n,e},s.clone=y,s.compact=function(e){for(var t=-1,n=e?e.length:0,r=[];++t<n;){var i=e[t];i&&r.push(i)}return r},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=cn,s.countBy=hn,s.debounce=function(e,t,n){function i(){a=r,n||(o=e.apply(u,s))}var s,o,u,a;return function(){var r=n&&!a;return s=arguments,u=this,bt(a),a=wt(i,t),r&&(o=e.apply(u,s)),o}},s.defaults=
|
||||
Yt,s.defer=function(e){var n=nt.call(arguments,1);return wt(function(){return e.apply(t,n)},1)},s.delay=function(e,n){var r=nt.call(arguments,2);return wt(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=Q.apply(_,arguments),i=o(i,r);++n<r;){var s=e[n];i(s)||t.push(s)}return t},s.escape=function(e){return e==r?"":(e+"").replace(V,h)},s.every=pn,s.extend=Zt,s.filter=dn,s.find=vn,s.first=S,s.flatten=x,s.forEach=mn,s.forIn=en,s.forOwn=tn,
|
||||
s.functions=nn,s.groupBy=gn,s.has=function(e,t){return e?Z.call(e,t):i},s.identity=A,s.indexOf=T,s.initial=function(e,t,n){return e?nt.call(e,0,-(t==r||n?1:t)):[]},s.intersection=function(e){var t=arguments.length,n=[],r=-1,i=e?e.length:0,s=[];e:for(;++r<i;){var u=e[r];if(0>T(s,u)){for(var a=1;a<t;a++)if(!(n[a]||(n[a]=o(arguments[a])))(u))continue e;s.push(u)}}return s},s.invert=Vt,s.invoke=yn,s.isArguments=v,s.isArray=$t,s.isBoolean=function(e){return e===n||e===i||rt.call(e)==pt},s.isDate=function(
|
||||
e){return rt.call(e)==dt},s.isElement=function(e){return e?1===e.nodeType:i},s.isEmpty=rn,s.isEqual=b,s.isFinite=function(e){return ot(e)&&rt.call(e)==vt},s.isFunction=m,s.isNaN=function(e){return rt.call(e)==vt&&e!=+e},s.isNull=function(e){return e===r},s.isNumber=function(e){return rt.call(e)==vt},s.isObject=function(e){return e?Ht[typeof e]:i},s.isPlainObject=Jt,s.isRegExp=function(e){return rt.call(e)==gt},s.isString=function(e){return rt.call(e)==yt},s.isUndefined=function(e){return e===t},s
|
||||
.keys=sn,s.last=function(e,t,n){if(e){var i=e.length;return t==r||n?e[i-1]:nt.call(e,-t||i)}},s.lastIndexOf=function(e,t,n){var r=e?e.length:0;for("number"==typeof n&&(r=(0>n?at(0,r+n):ft(n,r-1))+1);r--;)if(e[r]===t)return r;return-1},s.lateBind=function(e,t){return a(t,e,nt.call(arguments,2))},s.map=bn,s.max=w,s.memoize=function(e,t){var n={};return function(){var r=t?t.apply(this,arguments):arguments[0];return Z.call(n,r)?n[r]:n[r]=e.apply(this,arguments)}},s.merge=on,s.min=function(e,t,n){var r=
|
||||
Infinity,i=-1,s=e?e.length:0,o=r;if(t||s!==+s)t=f(t,n),mn(e,function(e,n,i){n=t(e,n,i),n<r&&(r=n,o=e)});else for(;++i<s;)e[i]<o&&(o=e[i]);return o},s.mixin=O,s.noConflict=function(){return e._=B,this},s.object=function(e,t){for(var n=-1,r=e?e.length:0,i={};++n<r;){var s=e[n];t?i[s]=t[n]:i[s[0]]=s[1]}return i},s.omit=un,s.once=function(e){var t,s=i;return function(){return s?t:(s=n,t=e.apply(this,arguments),e=r,t)}},s.pairs=an,s.partial=function(e){return a(e,nt.call(arguments,1))},s.pick=fn,s.pluck=
|
||||
wn,s.random=function(e,t){return e==r&&t==r&&(t=1),e=+e||0,t==r&&(t=e,e=0),e+G(lt()*((+t||0)-e+1))},s.range=function(e,t,n){e=+e||0,n=+n||1,t==r&&(t=e,e=0);for(var i=-1,t=at(0,K((t-e)/n)),s=Array(t);++i<t;)s[i]=e,e+=n;return s},s.reduce=En,s.reduceRight=E,s.reject=Sn,s.rest=N,s.result=function(e,t){var n=e?e[t]:r;return m(n)?e[t]():n},s.shuffle=function(e){var t=-1,n=Array(e?e.length:0);return mn(e,function(e){var r=G(lt()*(++t+1));n[t]=n[r],n[r]=e}),n},s.size=function(e){var t=e?e.length:0;return t===+
|
||||
t?t:sn(e).length},s.some=xn,s.sortBy=Tn,s.sortedIndex=C,s.tap=function(e,t){return t(e),e},s.template=function(e,t,n){e||(e=""),n||(n={});var r,i,o=0,u=s.templateSettings,a="__p += '",f=n.variable||u.variable,l=f;e.replace(RegExp((n.escape||u.escape||X).source+"|"+(n.interpolate||u.interpolate||X).source+"|"+(n.evaluate||u.evaluate||X).source+"|$","g"),function(t,n,i,s,u){a+=e.slice(o,u).replace($,c),a+=n?"'+__e("+n+")+'":s?"';"+s+";__p+='":i?"'+((__t=("+i+"))==null?'':__t)+'":"",r||(r=s||j.test(
|
||||
n||i)),o=u+t.length}),a+="';",l||(f="obj",r?a="with("+f+"){"+a+"}":(n=RegExp("(\\(\\s*)"+f+"\\."+f+"\\b","g"),a=a.replace(z,"$&"+f+".").replace(n,"$1__d"))),a=(r?a.replace(I,""):a).replace(q,"$1").replace(R,"$1;"),a="function("+f+"){"+(l?"":f+"||("+f+"={});")+"var __t,__p='',__e=_.escape"+(r?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":(l?"":",__d="+f+"."+f+"||"+f)+";")+a+"return __p}";try{i=Function("_","return "+a)(s)}catch(h){throw h.source=a,h}return t?i(t):(i.source=
|
||||
a,i)},s.throttle=function(e,t){function n(){a=new Date,u=r,s=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?(bt(u),a=r,s=e.apply(o,i)):u||(u=wt(n,f)),s}},s.times=function(e,t,n){for(var e=+e||0,r=-1,i=Array(e);++r<e;)i[r]=t.call(n,r);return i},s.toArray=function(e){if(!e)return[];var t=e.length;return t===+t?(Ct?rt.call(e)==yt:"string"==typeof e)?e.split(""):nt.call(e):ln(e)},s.unescape=function(e){return e==r?"":(e+"").replace(F,d)},s.union=
|
||||
function(){for(var e=-1,t=Q.apply(_,arguments),n=t.length,r=[];++e<n;){var i=t[e];0>T(r,i)&&r.push(i)}return r},s.uniq=k,s.uniqueId=function(e){var t=P++;return e?e+t:t},s.values=ln,s.where=Nn,s.without=function(e){for(var t=-1,n=e?e.length:0,r=o(arguments,1,20),i=[];++t<n;){var s=e[t];r(s)||i.push(s)}return i},s.wrap=function(e,t){return function(){var n=[e];return arguments.length&&et.apply(n,arguments),t.apply(this,n)}},s.zip=function(e){for(var t=-1,n=e?w(wn(arguments,"length")):0,r=Array(n);++
|
||||
t<n;)r[t]=wn(arguments,t);return r},s.all=pn,s.any=xn,s.collect=bn,s.detect=vn,s.drop=N,s.each=mn,s.foldl=En,s.foldr=E,s.head=S,s.include=cn,s.inject=En,s.methods=nn,s.select=dn,s.tail=N,s.take=S,s.unique=k,O(s),s.prototype.chain=function(){return this.__chain__=n,this},s.prototype.value=function(){return this.__wrapped__},mn("pop push reverse shift sort splice unshift".split(" "),function(e){var t=_[e];s.prototype[e]=function(){var e=this.__wrapped__;return t.apply(e,arguments),St&&e.length===0&&delete
|
||||
e[0],this.__chain__&&(e=new s(e),e.__chain__=n),e}}),mn(["concat","join","slice"],function(e){var t=_[e];s.prototype[e]=function(){var e=t.apply(this.__wrapped__,arguments);return this.__chain__&&(e=new s(e),e.__chain__=n),e}}),typeof define=="function"&&typeof define.amd=="object"&&define.amd?(e._=s,define(function(){return s})):M?"object"==typeof module&&module&&module.exports==M?(module.exports=s)._=s:M._=s:e._=s})(this);
|
||||
36
lodash.underscore.min.js
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
/*!
|
||||
Lo-Dash 0.8.2 lodash.com/license
|
||||
Underscore.js 1.4.2 underscorejs.org/LICENSE
|
||||
*/
|
||||
;(function(e,t){function s(e,t,r){var s;if(!e)return i;var t=x(t,r),o=e.length,r=-1;if(o===+o){for(;++r<o;)if(s=e[r],t(s,r,e))return n}else for(r in e)if(it.call(e,r)&&(s=e[r],t(s,r,e)))return n;return i}function o(e,t,n,r){var s,o,u=n;if(!e)return u;var a=3>arguments.length,t=x(t,r),f=e.length;s=-1;if(f===+f)for(a&&(u=e[++s]);++s<f;)o=e[s],u=t(u,o,s,e);else for(s in e)it.call(e,s)&&(o=e[s],u=a?(a=i,o):t(u,o,s,e));return u}function u(e,t){var n,r,i=e||[];if(!e)return i;var s=e.length;n=-1;if(s===+
|
||||
s)for(i=Array(s);++n<s;)r=e[n],i[n]=r[t];else for(n in i=[],e)it.call(e,n)&&(r=e[n],i.push(r[t]));return i}function a(e,t,n){var r,i=e||[];if(!e)return i;var t=x(t,n),s=e.length,n=-1;if(s===+s)for(i=Array(s);++n<s;)r=e[n],i[n]=t(r,n,e);else for(n in i=[],e)it.call(e,n)&&(r=e[n],i.push(t(r,n,e)));return i}function f(e,t,n){var r;if(!e)return e;var t=x(t,n),i=e.length,n=-1;if(i===+i)for(;++n<i;)r=e[n],t(r,n,e);else for(n in e)it.call(e,n)&&(r=e[n],t(r,n,e));return e}function l(e,n,r){var i,s=t;if(!
|
||||
e)return s;var n=x(n,r),o=e.length,r=-1;if(o===+o){for(;++r<o;)if(i=e[r],n(i,r,e))return i}else for(r in e)if(it.call(e,r)&&(i=e[r],n(i,r,e)))return i;return s}function c(e,t,n){var r,i=[];if(!e)return i;var t=x(t,n),s=e.length,n=-1;if(s===+s)for(;++n<s;)r=e[n],t(r,n,e)&&i.push(r);else for(n in e)it.call(e,n)&&(r=e[n],t(r,n,e)&&i.push(r));return i}function h(e,t,r){var s;if(!e)return n;var t=x(t,r),o=e.length,r=-1;if(o===+o){for(;++r<o;)if(s=e[r],!t(s,r,e))return i}else for(r in e)if(it.call(e,r)&&
|
||||
(s=e[r],!t(s,r,e)))return i;return n}function p(e,t){var r,s;if(!e)return i;var o=e.length;r=-1;if(o===+o){if(ut.call(e)==wt)return-1<e.indexOf(t);for(;++r<o;)if(s=e[r],s===t)return n}else for(r in e)if(it.call(e,r)&&(s=e[r],s===t))return n;return i}function d(e){var t,n,r=[];if(!e)return r;for(t in e)it.call(e,t)&&(n=e[t],r.push(n));return r}function v(e){var t,n,r=[];if(!e)return r;for(t in e)n=e[t],L(n)&&r.push(t);return r.sort(),r}function m(e,t,n){var r;if(!e)return e;t=x(t,n);for(r in e)n=e
|
||||
[r],t(n,r,e);return e}function g(e){var t,n,r=e;if(!e)return e;for(var i=1,s=arguments.length;i<s;i++)if(r=arguments[i])for(t in r)n=r[t],e[t]=n;return e}function y(e){var t,n=[];if(!e)return n;for(t in e)it.call(e,t)&&n.push(t);return n}function b(e){var t,n,r={};if(!e)return r;for(t in e)it.call(e,t)&&(n=e[t],r[n]=t);return r}function w(e){if(e&&e.__wrapped__)return e;if(!(this instanceof w))return new w(e);this.__wrapped__=e}function E(e,n){var r=e.b,i=n.b,e=e.a,n=n.a;if(e!==n){if(e>n||e===t)return 1
|
||||
;if(e<n||n===t)return-1}return r<i?-1:1}function S(e,t,n){function r(){var i=arguments,s=t;return n.length&&(i=i.length?n.concat(ot.call(i)):n),this instanceof r?(C.prototype=e.prototype,s=new C,(i=e.apply(s,i))&&Tt[typeof i]?i:s):e.apply(s,i)}return r}function x(e,n){return e?"function"!=typeof e?function(t){return t[e]}:n!==t?function(t,r,i){return e.call(n,t,r,i)}:e:q}function T(e){return"\\"+Nt[e]}function N(e){return kt[e]}function C(){}function k(e){return Lt[e]}function L(e){return"function"==typeof
|
||||
e}function A(e){var t=i;if(!e||"object"!=typeof e||isArguments(e))return t;var n=e.constructor;return!L(n)||n instanceof n?(m(e,function(e,n){t=n}),t===i||it.call(e,t)):t}function O(e,t,s,o){if(e==r||t==r)return e===t;if(e===t)return 0!==e||1/e==1/t;if(Tt[typeof e]||Tt[typeof t])e=e.__wrapped__||e,t=t.__wrapped__||t;var u=ut.call(e);if(u!=ut.call(t))return i;switch(u){case vt:case mt:return+e==+t;case gt:return e!=+e?t!=+t:0==e?1/e==1/t:e==+t;case bt:case wt:return e==t+""}var a=Ct(e);if(!a&&u!=yt
|
||||
)return i;s||(s=[]),o||(o=[]);for(u=s.length;u--;)if(s[u]==e)return o[u]==t;var f=n,u=0;s.push(e),o.push(t);if(a){u=e.length;if(f=u==t.length)for(;u--&&(f=O(e[u],t[u],s,o)););return f}a=e.constructor,f=t.constructor;if(a!=f&&(!L(a)||!(a instanceof a&&L(f)&&f instanceof f)))return i;for(var l in e)if(it.call(e,l)&&(u++,!it.call(t,l)||!O(e[l],t[l],s,o)))return i;for(l in t)if(it.call(t,l)&&!(u--))return i;return n}function M(e,t,n){var r=-Infinity,i=-1,s=e?e.length:0,o=r;if(t||s!==+s)t=x(t,n),f(e,function(
|
||||
e,n,i){n=t(e,n,i),n>r&&(r=n,o=e)});else for(;++i<s;)e[i]>o&&(o=e[i]);return o}function _(e,t,n,r){var s=e?e.length:0,o=3>arguments.length;if(s!==+s)var u=At(e),s=u.length;return f(e,function(a,f,l){f=u?u[--s]:--s,n=o?(o=i,e[f]):t.call(r,n,e[f],f,l)}),n}function D(e,t,n){if(e)return t==r||n?e[0]:ot.call(e,0,t)}function P(e,t){for(var n=-1,r=e?e.length:0,i=[];++n<r;){var s=e[n];Ct(s)?st.apply(i,t?s:P(s)):i.push(s)}return i}function H(e,t,n){var r=-1,i=e?e.length:0;if("number"==typeof n)r=(0>n?ht(0,
|
||||
i+n):n||0)-1;else if(n)return r=j(e,t),e[r]===t?r:-1;for(;++r<i;)if(e[r]===t)return r;return-1}function B(e,t,n){return e?ot.call(e,t==r||n?1:t):[]}function j(e,t,n,r){var i=0,s=e?e.length:i;if(n){n=x(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 F(e,t,n,r){var s=-1,o=e?e.length:0,u=[],a=[];"function"==typeof t&&(r=n,n=t,t=i);for(n=x(n,r);++s<o;)if(r=n(e[s],s,e),t?!s||a[a.length-1]!==r:0>H(a,r))a.push(r),u.push(e[s]);return u}function I
|
||||
(e,t){return xt||at&&2<arguments.length?at.call.apply(at,arguments):S(e,t,ot.call(arguments,2))}function q(e){return e}function R(e){f(v(e),function(t){var r=w[t]=e[t];w.prototype[t]=function(){var e=[this.__wrapped__];return arguments.length&&st.apply(e,arguments),e=r.apply(w,e),this.__chain__&&(e=new w(e),e.__chain__=n),e}})}var n=!0,r=null,i=!1,U="object"==typeof exports&&exports&&("object"==typeof global&&global&&global==global.global&&(e=global),exports),z=Array.prototype,W=Object.prototype,
|
||||
X=0,V=e._,$=/[-?+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/,J=/&(?:amp|lt|gt|quot|#x27);/g,K=/(?:__e|__t=)\(\s*(?![\d\s"']|this\.)/g,Q=RegExp("^"+(W.valueOf+"").replace(/[.*+?^=!:${}()|[\]\/\\]/g,"\\$&").replace(/valueOf|for [^\]]+/g,".+?")+"$"),G=/($^)/,Y=/[&<>"']/g,Z=/['\n\r\t\u2028\u2029\\]/g,et=Math.ceil,tt=z.concat,nt=Math.floor,rt=Q.test(rt=Object.getPrototypeOf)&&rt,it=W.hasOwnProperty,st=z.push,ot=z.slice,ut=W.toString,at=Q.test(at=ot.bind)&&at,ft=Q.test(ft=Array.isArray
|
||||
)&&ft,lt=e.isFinite,ct=Q.test(ct=Object.keys)&&ct,ht=Math.max,pt=Math.min,dt=Math.random,vt="[object Boolean]",mt="[object Date]",gt="[object Number]",yt="[object Object]",bt="[object RegExp]",wt="[object String]",Et=e.clearTimeout,St=e.setTimeout,xt=at&&/\n|Opera/.test(at+ut.call(e.opera)),Tt={"boolean":i,"function":n,object:n,number:i,string:i,"undefined":i,unknown:n},Nt={"\\":"\\","'":"'","\n":"n","\r":"r"," ":"t","\u2028":"u2028","\u2029":"u2029"};w.templateSettings={escape:/<%-([\s\S]+?)%>/g
|
||||
,evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,variable:""},w.isArguments=function(e){return"[object Arguments]"==ut.call(e)},w.isArguments(arguments)||(w.isArguments=function(e){return e?it.call(e,"callee"):i});var Ct=ft||function(e){return"[object Array]"==ut.call(e)};L(/x/)&&(L=function(e){return"[object Function]"==ut.call(e)});var W=rt?function(e){if(!e||"object"!=typeof e)return i;var t=e.valueOf,n="function"==typeof t&&(n=rt(t))&&rt(n);return n?e==n||rt(e)==n&&!isArguments(e):A
|
||||
(e)}:A,kt={"&":"&","<":"<",">":">",'"':""","'":"'"},Lt=b(kt),At=ct?function(e){return e&&Tt[typeof e]?ct(e):[]}:y;w.VERSION="0.8.2",w.after=function(e,t){return 1>e?t():function(){if(1>--e)return t.apply(this,arguments)}},w.bind=I,w.bindAll=function(e){var t,n,r=e,i=e;if(!e)return i;n=arguments,t=0;var s=n.length;if(1<s){for(;++t<s;)i[n[t]]=I(i[n[t]],i);return i}for(t in r)n=r[t],L(n)&&(i[t]=I(n,i));return i},w.chain=function(e){return e=new w(e),e.__chain__=n,e},w.clone=function(
|
||||
e){return e&&Tt[typeof e]?Ct(e)?ot.call(e):g({},e):e},w.compact=function(e){for(var t=-1,n=e?e.length:0,r=[];++t<n;){var i=e[t];i&&r.push(i)}return r},w.compose=function(){var e=arguments;return function(){for(var t=arguments,n=e.length;n--;)t=[e[n].apply(this,t)];return t[0]}},w.contains=p,w.countBy=function(e,t,n){var r,i={};if(!e)return i;var t=x(t,n),s=e.length,n=-1;if(s===+s)for(;++n<s;)r=e[n],r=t(r,n,e),it.call(i,r)?i[r]++:i[r]=1;else for(n in e)it.call(e,n)&&(r=e[n],r=t(r,n,e),it.call(i,r)?
|
||||
i[r]++:i[r]=1);return i},w.debounce=function(e,t,n){function i(){a=r,n||(o=e.apply(u,s))}var s,o,u,a;return function(){var r=n&&!a;return s=arguments,u=this,Et(a),a=St(i,t),r&&(o=e.apply(u,s)),o}},w.defaults=function(e){var t,n,i=e;if(!e)return e;for(var s=1,o=arguments.length;s<o;s++)if(i=arguments[s])for(t in i)n=i[t],e[t]==r&&(e[t]=n);return e},w.defer=function(e){var n=ot.call(arguments,1);return St(function(){return e.apply(t,n)},1)},w.delay=function(e,n){var r=ot.call(arguments,2);return St
|
||||
(function(){return e.apply(t,r)},n)},w.difference=function(e){for(var t=-1,n=e.length,r=tt.apply(z,arguments),i=[];++t<n;){var s=e[t];0>H(r,s,n)&&i.push(s)}return i},w.escape=function(e){return e==r?"":(e+"").replace(Y,N)},w.every=h,w.extend=g,w.filter=c,w.find=l,w.first=D,w.flatten=P,w.forEach=f,w.forIn=m,w.forOwn=function(e,t,n){var r;if(!e)return e;t=x(t,n);for(r in e)it.call(e,r)&&(n=e[r],t(n,r,e));return e},w.functions=v,w.groupBy=function(e,t,n){var r,i={};if(!e)return i;var t=x(t,n),s=e.length
|
||||
,n=-1;if(s===+s)for(;++n<s;){r=e[n];var o=t(r,n,e);(it.call(i,o)?i[o]:i[o]=[]).push(r)}else for(n in e)it.call(e,n)&&(r=e[n],o=t(r,n,e),(it.call(i,o)?i[o]:i[o]=[]).push(r));return i},w.has=function(e,t){return e?it.call(e,t):i},w.identity=q,w.indexOf=H,w.initial=function(e,t,n){return e?ot.call(e,0,-(t==r||n?1:t)):[]},w.intersection=function(e){var t=arguments.length,n=-1,r=e.length,i=[];e:for(;++n<r;){var s=e[n];if(0>H(i,s)){for(var o=1;o<t;o++)if(0>H(arguments[o],s))continue e;i.push(s)}}return i
|
||||
},w.invert=b,w.invoke=function(e,t){var n,r,i=e,s=e||[];if(!e)return s;var o=ot.call(arguments,2),u="function"==typeof t,a=i.length;n=-1;if(a===+a)for(s=Array(a);++n<a;)r=i[n],s[n]=(u?t:r[t]).apply(r,o);else for(n in s=[],i)it.call(i,n)&&(r=i[n],s.push((u?t:r[t]).apply(r,o)));return s},w.isArray=Ct,w.isBoolean=function(e){return e===n||e===i||ut.call(e)==vt},w.isDate=function(e){return ut.call(e)==mt},w.isElement=function(e){return e?1===e.nodeType:i},w.isEmpty=function(e){var t;if(!e)return n;var r=
|
||||
ut.call(e),s=e.length;if(Ct(e)||r==wt||r==yt&&s===+s&&L(e.splice))return!s;for(t in e)if(it.call(e,t))return i;return n},w.isEqual=O,w.isFinite=function(e){return lt(e)&&ut.call(e)==gt},w.isFunction=L,w.isNaN=function(e){return ut.call(e)==gt&&e!=+e},w.isNull=function(e){return e===r},w.isNumber=function(e){return ut.call(e)==gt},w.isObject=function(e){return e?Tt[typeof e]:i},w.isPlainObject=W,w.isRegExp=function(e){return ut.call(e)==bt},w.isString=function(e){return ut.call(e)==wt},w.isUndefined=
|
||||
function(e){return e===t},w.keys=At,w.last=function(e,t,n){if(e){var i=e.length;return t==r||n?e[i-1]:ot.call(e,-t||i)}},w.lastIndexOf=function(e,t,n){var r=e?e.length:0;for("number"==typeof n&&(r=(0>n?ht(0,r+n):pt(n,r-1))+1);r--;)if(e[r]===t)return r;return-1},w.map=a,w.max=M,w.memoize=function(e,t){var n={};return function(){var r=t?t.apply(this,arguments):arguments[0];return it.call(n,r)?n[r]:n[r]=e.apply(this,arguments)}},w.min=function(e,t,n){var r=Infinity,i=-1,s=e?e.length:0,o=r;if(t||s!==+
|
||||
s)t=x(t,n),f(e,function(e,n,i){n=t(e,n,i),n<r&&(r=n,o=e)});else for(;++i<s;)e[i]<o&&(o=e[i]);return o},w.mixin=R,w.noConflict=function(){return e._=V,this},w.object=function(e,t){for(var n=-1,r=e?e.length:0,i={};++n<r;){var s=e[n];t?i[s]=t[n]:i[s[0]]=s[1]}return i},w.omit=function(e,t,n){var r,i,s=e,o={};if(!e)return o;var u="function"==typeof t;if(u)t=x(t,n);else var a=tt.apply(z,arguments);for(r in s)if(i=s[r],u?!t(i,r,e):0>H(a,r))o[r]=i;return o},w.once=function(e){var t,s=i;return function(){
|
||||
return s?t:(s=n,t=e.apply(this,arguments),e=r,t)}},w.pairs=function(e){var t,n,r=[];if(!e)return r;for(t in e)it.call(e,t)&&(n=e[t],r.push([t,n]));return r},w.pick=function(e,t,n){var r,i,s=e,o={};if(!e)return o;if("function"!=typeof t){r=0,i=tt.apply(z,arguments);for(s=i.length;++r<s;){var u=i[r];u in e&&(o[u]=e[u])}}else for(r in t=x(t,n),s)i=s[r],t(i,r,e)&&(o[r]=i);return o},w.pluck=u,w.random=function(e,t){return e==r&&t==r&&(t=1),e=+e||0,t==r&&(t=e,e=0),e+nt(dt()*((+t||0)-e+1))},w.range=function(
|
||||
e,t,n){e=+e||0,n=+n||1,t==r&&(t=e,e=0);for(var i=-1,t=ht(0,et((t-e)/n)),s=Array(t);++i<t;)s[i]=e,e+=n;return s},w.reduce=o,w.reduceRight=_,w.reject=function(e,t,n){var r,i=[];if(!e)return i;var t=x(t,n),s=e.length,n=-1;if(s===+s)for(;++n<s;)r=e[n],!t(r,n,e)&&i.push(r);else for(n in e)it.call(e,n)&&(r=e[n],!t(r,n,e)&&i.push(r));return i},w.rest=B,w.result=function(e,t){var n=e?e[t]:r;return L(n)?e[t]():n},w.shuffle=function(e){var t=-1,n=Array(e?e.length:0);return f(e,function(e){var r=nt(dt()*(++
|
||||
t+1));n[t]=n[r],n[r]=e}),n},w.size=function(e){var t=e?e.length:0;return t===+t?t:At(e).length},w.some=s,w.sortBy=function(e,t,n){var r,i=e||[];if(!e)return i;var t=x(t,n),s=e.length,n=-1;if(s===+s)for(i=Array(s);++n<s;)r=e[n],i[n]={a:t(r,n,e),b:n,c:r};else for(n in i=[],e)it.call(e,n)&&(r=e[n],i.push({a:t(r,n,e),b:n,c:r}));i.sort(E);for(s=i.length;s--;)i[s]=i[s].c;return i},w.sortedIndex=j,w.tap=function(e,t){return t(e),e},w.template=function(e,t,n){e||(e=""),n||(n={});var r,i,s=0,o=w.templateSettings
|
||||
,u="__p += '",a=n.variable||o.variable,f=a;e.replace(RegExp((n.escape||o.escape||G).source+"|"+(n.interpolate||o.interpolate||G).source+"|"+(n.evaluate||o.evaluate||G).source+"|$","g"),function(t,n,i,o,a){u+=e.slice(s,a).replace(Z,T),u+=n?"'+__e("+n+")+'":o?"';"+o+";__p+='":i?"'+((__t=("+i+"))==null?'':__t)+'":"",r||(r=o||$.test(n||i)),s=a+t.length}),u+="';",f||(a="obj",r?u="with("+a+"){"+u+"}":(n=RegExp("(\\(\\s*)"+a+"\\."+a+"\\b","g"),u=u.replace(K,"$&"+a+".").replace(n,"$1__d"))),u="function("+
|
||||
a+"){"+(f?"":a+"||("+a+"={});")+"var __t,__p='',__e=_.escape"+(r?",__j=Array.prototype.join;function print(){__p+=__j.call(arguments,'')}":(f?"":",__d="+a+"."+a+"||"+a)+";")+u+"return __p}";try{i=Function("_","return "+u)(w)}catch(l){throw l.source=u,l}return t?i(t):(i.source=u,i)},w.throttle=function(e,t){function n(){a=new Date,u=r,s=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?(Et(u),a=r,s=e.apply(o,i)):u||(u=St(n,f)),s}},w.times=function(
|
||||
e,t,n){for(var e=+e||0,r=-1,i=Array(e);++r<e;)i[r]=t.call(n,r);return i},w.toArray=function(e){if(!e)return[];var t=e.length;return t===+t?"string"==typeof e?e.split(""):ot.call(e):d(e)},w.unescape=function(e){return e==r?"":(e+"").replace(J,k)},w.union=function(){for(var e=-1,t=tt.apply(z,arguments),n=t.length,r=[];++e<n;){var i=t[e];0>H(r,i)&&r.push(i)}return r},w.uniq=F,w.uniqueId=function(e){var t=X++;return e?e+t:t},w.values=d,w.where=function(e,t){var r,i,s=[];if(!e)return s;var o=[];m(t,function(
|
||||
e,t){o.push(t)});var u=o.length,a=e.length;r=-1;if(a===+a)for(;++r<a;){i=e[r];for(var f=n,l=0;l<u&&(f=o[l],f=i[f]===t[f]);l++);f&&s.push(i)}else for(r in e)if(it.call(e,r)){i=e[r],f=n;for(l=0;l<u&&(f=o[l],f=i[f]===t[f]);l++);f&&s.push(i)}return s},w.without=function(e){for(var t=-1,n=e.length,r=[];++t<n;){var i=e[t];0>H(arguments,i,1)&&r.push(i)}return r},w.wrap=function(e,t){return function(){var n=[e];return arguments.length&&st.apply(n,arguments),t.apply(this,n)}},w.zip=function(e){for(var t=-1
|
||||
,n=e?M(u(arguments,"length")):0,r=Array(n);++t<n;)r[t]=u(arguments,t);return r},w.all=h,w.any=s,w.collect=a,w.detect=l,w.drop=B,w.each=f,w.foldl=o,w.foldr=_,w.head=D,w.include=p,w.inject=o,w.methods=v,w.select=c,w.tail=B,w.take=D,w.unique=F,R(w),w.prototype.chain=function(){return this.__chain__=n,this},w.prototype.value=function(){return this.__wrapped__},f("pop push reverse shift sort splice unshift".split(" "),function(e){var t=z[e];w.prototype[e]=function(){var e=this.__wrapped__;return t.apply
|
||||
(e,arguments),this.__chain__&&(e=new w(e),e.__chain__=n),e}}),f(["concat","join","slice"],function(e){var t=z[e];w.prototype[e]=function(){var e=t.apply(this.__wrapped__,arguments);return this.__chain__&&(e=new w(e),e.__chain__=n),e}}),U?"object"==typeof module&&module&&module.exports==U?(module.exports=w)._=w:U._=w:e._=w})(this);
|
||||
30
package.json
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "lodash",
|
||||
"version": "0.1.0",
|
||||
"description": "A drop-in replacement for Underscore.js that delivers up to 8x performance improvements, bug fixes, and additional features.",
|
||||
"homepage": "https://github.com/bestiejs/lodash",
|
||||
"main": "lodash",
|
||||
"version": "0.8.2",
|
||||
"description": "A drop-in replacement for Underscore.js delivering performance, bug fixes, and additional features.",
|
||||
"homepage": "http://lodash.com",
|
||||
"main": "./lodash",
|
||||
"keywords": [
|
||||
"browser",
|
||||
"client",
|
||||
@@ -16,12 +16,12 @@
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "http://mths.be/mit"
|
||||
"url": "http://lodash.com/license"
|
||||
}
|
||||
],
|
||||
"author": {
|
||||
"name": "John-David Dalton",
|
||||
"email": "john@fusejs.com",
|
||||
"email": "john.david.dalton@gmail.com",
|
||||
"web": "http://allyoucanleet.com/"
|
||||
},
|
||||
"bugs": {
|
||||
@@ -31,12 +31,22 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/bestiejs/lodash.git"
|
||||
},
|
||||
"bin": {
|
||||
"lodash": "./build.js"
|
||||
},
|
||||
"directories": {
|
||||
"doc": "./doc",
|
||||
"test": "./test"
|
||||
},
|
||||
"engines": [
|
||||
"node",
|
||||
"rhino"
|
||||
],
|
||||
"directories": {
|
||||
"doc": "./doc",
|
||||
"test": "./test"
|
||||
"jam": {
|
||||
"main": "./lodash.js"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "node build",
|
||||
"test": "node test/test && node test/test-build"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
59
perf/index.html
Normal file
@@ -0,0 +1,59 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Lo-Dash Performance Suite</title>
|
||||
<style>
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
}
|
||||
applet {
|
||||
position: absolute;
|
||||
left: -9999em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<script src="../lodash.min.js"></script>
|
||||
<script>
|
||||
var lodash = _.noConflict();
|
||||
</script>
|
||||
<script src="../vendor/underscore/underscore-min.js"></script>
|
||||
<script src="../vendor/platform.js/platform.js"></script>
|
||||
<script src="../vendor/benchmark.js/benchmark.js"></script>
|
||||
<script src="../vendor/firebug-lite/src/firebug-lite-debug.js"></script>
|
||||
<script src="perf.js"></script>
|
||||
<script>
|
||||
(function() {
|
||||
var measured,
|
||||
perfNow,
|
||||
begin = new Date;
|
||||
|
||||
function init() {
|
||||
var fbUI = document.getElementById('FirebugUI'),
|
||||
fbDoc = fbUI && (fbDoc = fbUI.contentWindow || fbUI.contentDocument).document || fbDoc,
|
||||
fbCommandLine = fbDoc && fbDoc.getElementById('fbCommandLine');
|
||||
|
||||
if (!fbCommandLine) {
|
||||
return setTimeout(init, 15);
|
||||
}
|
||||
fbUI.style.height = fbDoc.body.style.height = fbDoc.documentElement.style.height = '100%';
|
||||
setTimeout(run, 15);
|
||||
}
|
||||
|
||||
// is the applet permitted?
|
||||
if (!/[?&]nojava=true(?:&|$)/.test(location.search)) {
|
||||
// is the applet really needed?
|
||||
while (!(measured = new Date - begin)) { }
|
||||
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;
|
||||
}());
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
1549
perf/perf.js
Normal file
9
perf/run-perf.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
cd "$(dirname "$0")"
|
||||
for cmd in node narwhal ringo rhino; do
|
||||
echo ""
|
||||
echo "Running performance suite in $cmd..."
|
||||
$cmd perf.js
|
||||
done
|
||||
echo ""
|
||||
echo "Running performance suite in a browser..."
|
||||
open index.html
|
||||
49
test/backbone.html
Normal file
@@ -0,0 +1,49 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Backbone Test Suite</title>
|
||||
<link rel="stylesheet" href="../vendor/backbone/test/vendor/qunit.css">
|
||||
<style>
|
||||
body > #qunit-header {
|
||||
display: none;
|
||||
}
|
||||
#jslitmus {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="qunit"></div>
|
||||
<h1 id="qunit-header"><a href="#">Backbone Speed Suite</a></h1>
|
||||
<div id="qunit-fixture">
|
||||
<div id='testElement'>
|
||||
<h1>Test</h1>
|
||||
</div>
|
||||
</div>
|
||||
<script src="../vendor/backbone/test/vendor/json2.js"></script>
|
||||
<script src="../vendor/backbone/test/vendor/jquery-1.7.1.js"></script>
|
||||
<script src="../vendor/backbone/test/vendor/jslitmus.js"></script>
|
||||
<script src="../vendor/platform.js/platform.js"></script>
|
||||
<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>
|
||||
document.write('<script src="../' + QUnit.config.lodashFilename + '.js"><\/script>');
|
||||
</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/events.js"></script>
|
||||
<script src="../vendor/backbone/test/model.js"></script>
|
||||
<script src="../vendor/backbone/test/collection.js"></script>
|
||||
<script src="../vendor/backbone/test/router.js"></script>
|
||||
<script src="../vendor/backbone/test/view.js"></script>
|
||||
<script src="../vendor/backbone/test/sync.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
107
test/index.html
@@ -6,34 +6,87 @@
|
||||
<link rel="stylesheet" href="../vendor/qunit/qunit/qunit.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1 id="qunit-header">Lo-Dash Test Suite</h1>
|
||||
<h2 id="qunit-banner"></h2>
|
||||
<div id="qunit-testrunner-toolbar"></div>
|
||||
<h2 id="qunit-userAgent"></h2>
|
||||
<ol id="qunit-tests"></ol>
|
||||
<script src="../vendor/qunit/qunit/qunit.js"></script>
|
||||
<script>var _2, _ = 1;</script>
|
||||
<script src="../lodash.js"></script>
|
||||
<script src="../vendor/requirejs/require.js"></script>
|
||||
<div id="qunit"></div>
|
||||
<script src="../vendor/platform.js/platform.js"></script>
|
||||
<script>
|
||||
if (/[?&]norequire=true(?:&|$)/.test(location.search)) {
|
||||
require = define = null;
|
||||
document.write('<script src="test.js"><\/script>');
|
||||
}
|
||||
else {
|
||||
define.amd.lodash = true;
|
||||
require({
|
||||
'baseUrl': '../vendor/requirejs/',
|
||||
'urlArgs': 't=' + (+new Date),
|
||||
'paths': {
|
||||
'lodash': '../../lodash'
|
||||
}
|
||||
// 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>
|
||||
// set a bad shim
|
||||
Object._keys = Object.keys;
|
||||
Object.keys = function() { return []; };
|
||||
|
||||
// load Lo-Dash and expose it to the bad `Object.keys` shim
|
||||
document.write('<script src="../' + QUnit.config.lodashFilename + '.js"><\/script>');
|
||||
</script>
|
||||
<script>
|
||||
// store Lo-Dash to test for bad shim detection
|
||||
var lodashBadShim = _;
|
||||
|
||||
// restore nativeKeys
|
||||
Object.keys = Object._keys;
|
||||
delete Object._keys;
|
||||
|
||||
// load Lo-Dash again to overwrite the existing `_` value
|
||||
document.write('<script src="../' + QUnit.config.lodashFilename + '.js"><\/script>');
|
||||
|
||||
// load test.js if not using require.js
|
||||
document.write(QUnit.urlParams.norequire
|
||||
? '<script src="test.js"><\/script>'
|
||||
: '<script src="../vendor/requirejs/require.js"><\/script>'
|
||||
);
|
||||
</script>
|
||||
<script>
|
||||
// load Lo-Dash as a module
|
||||
var lodashModule,
|
||||
shimmedModule,
|
||||
underscoreModule;
|
||||
|
||||
window.require && require({
|
||||
'baseUrl': '../vendor/requirejs/',
|
||||
'urlArgs': 't=' + (+new Date),
|
||||
'paths': {
|
||||
'lodash': '../../' + QUnit.config.lodashFilename,
|
||||
'shimmed': './../../' + QUnit.config.lodashFilename,
|
||||
'underscore': '../underscore/../../' + QUnit.config.lodashFilename
|
||||
},
|
||||
['lodash'], function(_) {
|
||||
_2 = _.noConflict();
|
||||
require(['test.js']);
|
||||
});
|
||||
}
|
||||
'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';
|
||||
}
|
||||
require(['test.js']);
|
||||
});
|
||||
|
||||
// set a more readable browser name
|
||||
window.onload = function() {
|
||||
var timeoutId = setInterval(function() {
|
||||
var ua = document.getElementById('qunit-userAgent');
|
||||
if (ua) {
|
||||
ua.innerHTML = platform;
|
||||
clearInterval(timeoutId);
|
||||
}
|
||||
}, 15);
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
cd "$(dirname "$0")"
|
||||
for cmd in rhino ringo narwhal node; do
|
||||
echo "Testing in $cmd..."
|
||||
$cmd test.js
|
||||
echo ""
|
||||
echo "Testing in $cmd..."
|
||||
$cmd test.js
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Testing build..."
|
||||
node test-build.js
|
||||
|
||||
echo ""
|
||||
echo "Testing in a browser..."
|
||||
open index.html
|
||||
open index.html
|
||||
|
||||
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
@@ -0,0 +1 @@
|
||||
<% print("Hello " + epithet); %>.
|
||||
1
test/template/c.tpl
Normal file
@@ -0,0 +1 @@
|
||||
Hello {{ name }}!
|
||||
968
test/test-build.js
Normal file
@@ -0,0 +1,968 @@
|
||||
#!/usr/bin/env node
|
||||
;(function(undefined) {
|
||||
'use strict';
|
||||
|
||||
/** Load modules */
|
||||
var fs = require('fs'),
|
||||
path = require('path'),
|
||||
vm = require('vm'),
|
||||
build = require('../build.js'),
|
||||
minify = require('../build/minify'),
|
||||
_ = require('../lodash.js');
|
||||
|
||||
/** The unit testing framework */
|
||||
var QUnit = global.QUnit = require('../vendor/qunit/qunit/qunit.js');
|
||||
require('../vendor/qunit-clib/qunit-clib.js');
|
||||
|
||||
/** Used to associate aliases with their real names */
|
||||
var aliasToRealMap = {
|
||||
'all': 'every',
|
||||
'any': 'some',
|
||||
'collect': 'map',
|
||||
'detect': 'find',
|
||||
'drop': 'rest',
|
||||
'each': 'forEach',
|
||||
'foldl': 'reduce',
|
||||
'foldr': 'reduceRight',
|
||||
'head': 'first',
|
||||
'include': 'contains',
|
||||
'inject': 'reduce',
|
||||
'methods': 'functions',
|
||||
'select': 'filter',
|
||||
'tail': 'rest',
|
||||
'take': 'first',
|
||||
'unique': 'uniq'
|
||||
};
|
||||
|
||||
/** Used to associate real names with their aliases */
|
||||
var realToAliasMap = {
|
||||
'contains': ['include'],
|
||||
'every': ['all'],
|
||||
'filter': ['select'],
|
||||
'find': ['detect'],
|
||||
'first': ['head', 'take'],
|
||||
'forEach': ['each'],
|
||||
'functions': ['methods'],
|
||||
'map': ['collect'],
|
||||
'reduce': ['foldl', 'inject'],
|
||||
'reduceRight': ['foldr'],
|
||||
'rest': ['drop', 'tail'],
|
||||
'some': ['any'],
|
||||
'uniq': ['unique']
|
||||
};
|
||||
|
||||
/** List of all Lo-Dash methods */
|
||||
var allMethods = _.functions(_).filter(function(methodName) {
|
||||
return !/^_/.test(methodName);
|
||||
});
|
||||
|
||||
/** List of "Arrays" category methods */
|
||||
var arraysMethods = [
|
||||
'compact',
|
||||
'difference',
|
||||
'drop',
|
||||
'first',
|
||||
'flatten',
|
||||
'head',
|
||||
'indexOf',
|
||||
'initial',
|
||||
'intersection',
|
||||
'last',
|
||||
'lastIndexOf',
|
||||
'object',
|
||||
'range',
|
||||
'rest',
|
||||
'sortedIndex',
|
||||
'tail',
|
||||
'take',
|
||||
'union',
|
||||
'uniq',
|
||||
'unique',
|
||||
'without',
|
||||
'zip'
|
||||
];
|
||||
|
||||
/** List of "Chaining" category methods */
|
||||
var chainingMethods = [
|
||||
'chain',
|
||||
'mixin',
|
||||
'tap',
|
||||
'value'
|
||||
];
|
||||
|
||||
/** List of "Collections" category methods */
|
||||
var collectionsMethods = [
|
||||
'all',
|
||||
'any',
|
||||
'collect',
|
||||
'contains',
|
||||
'countBy',
|
||||
'detect',
|
||||
'each',
|
||||
'every',
|
||||
'filter',
|
||||
'find',
|
||||
'foldl',
|
||||
'foldr',
|
||||
'forEach',
|
||||
'groupBy',
|
||||
'include',
|
||||
'inject',
|
||||
'invoke',
|
||||
'map',
|
||||
'max',
|
||||
'min',
|
||||
'pluck',
|
||||
'reduce',
|
||||
'reduceRight',
|
||||
'reject',
|
||||
'select',
|
||||
'shuffle',
|
||||
'size',
|
||||
'some',
|
||||
'sortBy',
|
||||
'toArray',
|
||||
'where'
|
||||
];
|
||||
|
||||
/** List of "Functions" category methods */
|
||||
var functionsMethods = [
|
||||
'after',
|
||||
'bind',
|
||||
'bindAll',
|
||||
'compose',
|
||||
'debounce',
|
||||
'defer',
|
||||
'delay',
|
||||
'lateBind',
|
||||
'memoize',
|
||||
'once',
|
||||
'partial',
|
||||
'throttle',
|
||||
'wrap'
|
||||
];
|
||||
|
||||
/** List of "Objects" category methods */
|
||||
var objectsMethods = [
|
||||
'clone',
|
||||
'defaults',
|
||||
'extend',
|
||||
'forIn',
|
||||
'forOwn',
|
||||
'functions',
|
||||
'has',
|
||||
'invert',
|
||||
'isArguments',
|
||||
'isArray',
|
||||
'isBoolean',
|
||||
'isDate',
|
||||
'isElement',
|
||||
'isEmpty',
|
||||
'isEqual',
|
||||
'isFinite',
|
||||
'isFunction',
|
||||
'isNaN',
|
||||
'isNull',
|
||||
'isNumber',
|
||||
'isObject',
|
||||
'isPlainObject',
|
||||
'isRegExp',
|
||||
'isString',
|
||||
'isUndefined',
|
||||
'keys',
|
||||
'methods',
|
||||
'merge',
|
||||
'omit',
|
||||
'pairs',
|
||||
'pick',
|
||||
'values'
|
||||
];
|
||||
|
||||
/** List of "Utilities" category methods */
|
||||
var utilityMethods = [
|
||||
'escape',
|
||||
'identity',
|
||||
'noConflict',
|
||||
'random',
|
||||
'result',
|
||||
'template',
|
||||
'times',
|
||||
'unescape',
|
||||
'uniqueId'
|
||||
];
|
||||
|
||||
/** List of Backbone's Lo-Dash dependencies */
|
||||
var backboneDependencies = [
|
||||
'bind',
|
||||
'bindAll',
|
||||
'clone',
|
||||
'contains',
|
||||
'escape',
|
||||
'every',
|
||||
'extend',
|
||||
'filter',
|
||||
'find',
|
||||
'first',
|
||||
'forEach',
|
||||
'groupBy',
|
||||
'has',
|
||||
'indexOf',
|
||||
'initial',
|
||||
'invoke',
|
||||
'isArray',
|
||||
'isEmpty',
|
||||
'isEqual',
|
||||
'isFunction',
|
||||
'isObject',
|
||||
'isRegExp',
|
||||
'keys',
|
||||
'last',
|
||||
'lastIndexOf',
|
||||
'map',
|
||||
'max',
|
||||
'min',
|
||||
'mixin',
|
||||
'reduce',
|
||||
'reduceRight',
|
||||
'reject',
|
||||
'rest',
|
||||
'result',
|
||||
'shuffle',
|
||||
'size',
|
||||
'some',
|
||||
'sortBy',
|
||||
'sortedIndex',
|
||||
'toArray',
|
||||
'uniqueId',
|
||||
'without'
|
||||
];
|
||||
|
||||
/** List of methods used by Underscore */
|
||||
var underscoreMethods = _.without.apply(_, [allMethods].concat([
|
||||
'forIn',
|
||||
'forOwn',
|
||||
'isPlainObject',
|
||||
'lateBind',
|
||||
'merge',
|
||||
'partial'
|
||||
]));
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Creates a context object to use with `vm.runInContext`.
|
||||
*
|
||||
* @private
|
||||
* @returns {Object} Returns a new context object.
|
||||
*/
|
||||
function createContext() {
|
||||
return vm.createContext({
|
||||
'clearTimeout': clearTimeout,
|
||||
'setTimeout': setTimeout
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands a list of method names to include real and alias names.
|
||||
*
|
||||
* @private
|
||||
* @param {Array} methodNames The array of method names to expand.
|
||||
* @returns {Array} Returns a new array of expanded method names.
|
||||
*/
|
||||
function expandMethodNames(methodNames) {
|
||||
return methodNames.reduce(function(result, methodName) {
|
||||
var realName = getRealName(methodName);
|
||||
result.push.apply(result, [realName].concat(getAliases(realName)));
|
||||
return result;
|
||||
}, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the aliases associated with a given function name.
|
||||
*
|
||||
* @private
|
||||
* @param {String} funcName The name of the function to get aliases for.
|
||||
* @returns {Array} Returns an array of aliases.
|
||||
*/
|
||||
function getAliases(funcName) {
|
||||
return realToAliasMap[funcName] || [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the names of methods belonging to the given `category`.
|
||||
*
|
||||
* @private
|
||||
* @param {String} category The category to filter by.
|
||||
* @returns {Array} Returns a new array of method names belonging to the given category.
|
||||
*/
|
||||
function getMethodsByCategory(category) {
|
||||
switch (category) {
|
||||
case 'Arrays':
|
||||
return arraysMethods.slice();
|
||||
case 'Chaining':
|
||||
return chainingMethods.slice();
|
||||
case 'Collections':
|
||||
return collectionsMethods.slice();
|
||||
case 'Functions':
|
||||
return functionsMethods.slice();
|
||||
case 'Objects':
|
||||
return objectsMethods.slice();
|
||||
case 'Utilities':
|
||||
return utilityMethods.slice();
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the real name, not alias, of a given function name.
|
||||
*
|
||||
* @private
|
||||
* @param {String} funcName The name of the function to resolve.
|
||||
* @returns {String} Returns the real name.
|
||||
*/
|
||||
function getRealName(funcName) {
|
||||
return aliasToRealMap[funcName] || funcName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if a given method on the `lodash` object can be called successfully.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} lodash The built Lo-Dash object.
|
||||
* @param {String} methodName The name of the Lo-Dash method to test.
|
||||
* @param {String} message The unit test message.
|
||||
*/
|
||||
function testMethod(lodash, methodName, message) {
|
||||
var pass = true,
|
||||
array = [['a', 1], ['b', 2], ['c', 3]],
|
||||
object = { 'a': 1, 'b': 2, 'c': 3 },
|
||||
noop = function() {},
|
||||
string = 'abc',
|
||||
func = lodash[methodName];
|
||||
|
||||
try {
|
||||
if (arraysMethods.indexOf(methodName) > -1) {
|
||||
if (/(?:indexOf|sortedIndex|without)$/i.test(methodName)) {
|
||||
func(array, string);
|
||||
} else if (/^(?:difference|intersection|union|uniq|zip)/.test(methodName)) {
|
||||
func(array, array);
|
||||
} else if (methodName == 'range') {
|
||||
func(2, 4);
|
||||
} else {
|
||||
func(array);
|
||||
}
|
||||
}
|
||||
else if (chainingMethods.indexOf(methodName) > -1) {
|
||||
if (methodName == 'chain') {
|
||||
lodash.chain(array);
|
||||
lodash(array).chain();
|
||||
}
|
||||
else if (methodName == 'mixin') {
|
||||
lodash.mixin({});
|
||||
}
|
||||
else {
|
||||
lodash(array)[methodName](noop);
|
||||
}
|
||||
}
|
||||
else if (collectionsMethods.indexOf(methodName) > -1) {
|
||||
if (/^(?:count|group|sort)By$/.test(methodName)) {
|
||||
func(array, noop);
|
||||
func(array, string);
|
||||
func(object, noop);
|
||||
func(object, string);
|
||||
}
|
||||
else if (/^(?:size|toArray)$/.test(methodName)) {
|
||||
func(array);
|
||||
func(object);
|
||||
}
|
||||
else if (methodName == 'invoke') {
|
||||
func(array, 'slice');
|
||||
func(object, 'toFixed');
|
||||
}
|
||||
else if (methodName == 'where') {
|
||||
func(array, object);
|
||||
func(object, object);
|
||||
}
|
||||
else {
|
||||
func(array, noop, object);
|
||||
func(object, noop, object);
|
||||
}
|
||||
}
|
||||
else if (functionsMethods.indexOf(methodName) > -1) {
|
||||
if (methodName == 'after') {
|
||||
func(1, noop);
|
||||
} else if (methodName == 'bindAll') {
|
||||
func({ 'noop': noop });
|
||||
} else if (methodName == 'lateBind') {
|
||||
func(lodash, 'identity', array, string);
|
||||
} else if (/^(?:bind|partial)$/.test(methodName)) {
|
||||
func(noop, object, array, string);
|
||||
} else if (/^(?:compose|memoize|wrap)$/.test(methodName)) {
|
||||
func(noop, noop);
|
||||
} else if (/^(?:debounce|throttle)$/.test(methodName)) {
|
||||
func(noop, 100);
|
||||
} else {
|
||||
func(noop);
|
||||
}
|
||||
}
|
||||
else if (objectsMethods.indexOf(methodName) > -1) {
|
||||
if (methodName == 'clone') {
|
||||
func(object);
|
||||
func(object, true);
|
||||
}
|
||||
else if (/^(?:defaults|extend|merge)$/.test(methodName)) {
|
||||
func({}, object);
|
||||
} else if (/^(?:forIn|forOwn)$/.test(methodName)) {
|
||||
func(object, noop);
|
||||
} else if (/^(?:omit|pick)$/.test(methodName)) {
|
||||
func(object, 'b');
|
||||
} else if (methodName == 'has') {
|
||||
func(object, string);
|
||||
} else {
|
||||
func(object);
|
||||
}
|
||||
}
|
||||
else if (utilityMethods.indexOf(methodName) > -1) {
|
||||
if (methodName == 'result') {
|
||||
func(object, 'b');
|
||||
} else if (methodName == 'times') {
|
||||
func(2, noop, object);
|
||||
} else {
|
||||
func(string, object);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
console.log(e);
|
||||
pass = false;
|
||||
}
|
||||
equal(pass, true, '_.' + methodName + ': ' + message);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('minified AMD snippet');
|
||||
|
||||
(function() {
|
||||
var start = _.once(QUnit.start);
|
||||
|
||||
asyncTest('`lodash`', function() {
|
||||
build(['-s'], function(source, filePath) {
|
||||
// used by r.js build optimizer
|
||||
var defineHasRegExp = /typeof\s+define\s*==(=)?\s*['"]function['"]\s*&&\s*typeof\s+define\.amd\s*==(=)?\s*['"]object['"]\s*&&\s*define\.amd/g,
|
||||
basename = path.basename(filePath, '.js');
|
||||
|
||||
ok(!!defineHasRegExp.exec(source), basename);
|
||||
start();
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('template builds');
|
||||
|
||||
(function() {
|
||||
var templatePath = __dirname + '/template';
|
||||
|
||||
asyncTest('`lodash template=*.jst`', function() {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
build(['-s', 'template=' + templatePath + '/*.jst'], function(source, filePath) {
|
||||
var basename = path.basename(filePath, '.js'),
|
||||
context = createContext();
|
||||
|
||||
var data = {
|
||||
'a': { 'people': ['moe', 'larry', 'curly'] },
|
||||
'b': { 'epithet': 'stooge' }
|
||||
};
|
||||
|
||||
context._ = _;
|
||||
vm.runInContext(source, context);
|
||||
var templates = context._.templates;
|
||||
|
||||
equal(templates.a(data.a).replace(/[\r\n]+/g, ''), '<ul><li>moe</li><li>larry</li><li>curly</li></ul>', basename);
|
||||
equal(templates.b(data.b), 'Hello stooge.', basename);
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('`lodash settings=...`', function() {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
build(['-s', 'template=' + templatePath + '/*.tpl', 'settings={interpolate:/\\{\\{([\\s\\S]+?)\\}\\}/}'], function(source, filePath) {
|
||||
var basename = path.basename(filePath, '.js'),
|
||||
context = createContext();
|
||||
|
||||
var data = {
|
||||
'c': { 'name': 'Mustache' }
|
||||
};
|
||||
|
||||
context._ = _;
|
||||
vm.runInContext(source, context);
|
||||
var templates = context._.templates;
|
||||
|
||||
equal(templates.c(data.c), 'Hello Mustache!', basename);
|
||||
start();
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('independent builds');
|
||||
|
||||
(function() {
|
||||
asyncTest('debug only', function() {
|
||||
var start = _.once(QUnit.start);
|
||||
build(['-d', '-s'], function(source, filePath) {
|
||||
equal(path.basename(filePath, '.js'), 'lodash');
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('debug custom', function () {
|
||||
var start = _.once(QUnit.start);
|
||||
build(['-d', '-s', 'backbone'], function(source, filePath) {
|
||||
equal(path.basename(filePath, '.js'), 'lodash.custom');
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('minified only', function() {
|
||||
var start = _.once(QUnit.start);
|
||||
build(['-m', '-s'], function(source, filePath) {
|
||||
equal(path.basename(filePath, '.js'), 'lodash.min');
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('minified custom', function () {
|
||||
var start = _.once(QUnit.start);
|
||||
build(['-m', '-s', 'backbone'], function(source, filePath) {
|
||||
equal(path.basename(filePath, '.js'), 'lodash.custom.min');
|
||||
start();
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('strict modifier');
|
||||
|
||||
(function() {
|
||||
var object = Object.create(Object.prototype, {
|
||||
'a': { 'value': _.identify },
|
||||
'b': { 'value': null }
|
||||
});
|
||||
|
||||
['non-strict', 'strict'].forEach(function(strictMode, index) {
|
||||
asyncTest(strictMode + ' should ' + (index ? 'error': 'silently fail') + ' attempting to overwrite read-only properties', function() {
|
||||
var commands = ['-s', 'include=bindAll,defaults,extend'],
|
||||
start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
if (index) {
|
||||
commands.push('strict');
|
||||
}
|
||||
build(commands, function(source, filePath) {
|
||||
var basename = path.basename(filePath, '.js'),
|
||||
context = createContext(),
|
||||
pass = !index;
|
||||
|
||||
vm.runInContext(source, context);
|
||||
var lodash = context._;
|
||||
|
||||
try {
|
||||
lodash.bindAll(object);
|
||||
lodash.extend(object, { 'a': 1 });
|
||||
lodash.defaults(object, { 'b': 2 });
|
||||
} catch(e) {
|
||||
pass = !!index;
|
||||
}
|
||||
equal(pass, true, basename);
|
||||
start();
|
||||
});
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('underscore modifier');
|
||||
|
||||
(function() {
|
||||
asyncTest('modified methods should work correctly', function() {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
build(['-s', 'underscore'], function(source, filePath) {
|
||||
var last,
|
||||
array = [{ 'value': 1 }, { 'value': 2 }],
|
||||
basename = path.basename(filePath, '.js'),
|
||||
context = createContext();
|
||||
|
||||
vm.runInContext(source, context);
|
||||
var lodash = context._;
|
||||
|
||||
lodash.each(array, function(value) {
|
||||
last = value;
|
||||
return false;
|
||||
});
|
||||
|
||||
equal(last.value, 2, '_.each: ' + basename);
|
||||
equal(lodash.isEmpty('moe'), false, '_.isEmpty: ' + basename);
|
||||
|
||||
var object = { 'fn': lodash.bind(function(x) { return this.x + x; }, { 'x': 1 }, 1) };
|
||||
equal(object.fn(), 2, '_.bind: ' + basename);
|
||||
|
||||
ok(lodash.clone(array, true)[0] === array[0], '_.clone: ' + basename);
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('`lodash underscore include=partial`', function() {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
build(['-s', 'underscore', 'include=partial'], function(source, filePath) {
|
||||
var basename = path.basename(filePath, '.js'),
|
||||
context = createContext();
|
||||
|
||||
vm.runInContext(source, context);
|
||||
var lodash = context._;
|
||||
|
||||
equal(lodash.partial(_.identity, 2)(), 2, '_.partial: ' + basename);
|
||||
start();
|
||||
});
|
||||
});
|
||||
|
||||
asyncTest('`lodash underscore plus=clone`', function() {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
build(['-s', 'underscore', 'plus=clone'], function(source, filePath) {
|
||||
var array = [{ 'value': 1 }],
|
||||
basename = path.basename(filePath, '.js'),
|
||||
context = createContext();
|
||||
|
||||
vm.runInContext(source, context);
|
||||
var lodash = context._,
|
||||
clone = lodash.clone(array, true);
|
||||
|
||||
deepEqual(array, clone, basename);
|
||||
notEqual(array, clone, basename);
|
||||
start();
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('exports command');
|
||||
|
||||
(function() {
|
||||
var commands = [
|
||||
'exports=amd',
|
||||
'exports=commonjs',
|
||||
'exports=global',
|
||||
'exports=node',
|
||||
'exports=none'
|
||||
];
|
||||
|
||||
commands.forEach(function(command, index) {
|
||||
asyncTest('`lodash ' + command +'`', function() {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
build(['-s', command], function(source, filePath) {
|
||||
var basename = path.basename(filePath, '.js'),
|
||||
context = createContext(),
|
||||
pass = false;
|
||||
|
||||
switch(index) {
|
||||
case 0:
|
||||
context.define = function(fn) {
|
||||
pass = true;
|
||||
context._ = fn();
|
||||
};
|
||||
context.define.amd = {};
|
||||
vm.runInContext(source, context);
|
||||
ok(pass, basename);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
context.exports = {};
|
||||
vm.runInContext(source, context);
|
||||
ok(context._ === undefined, basename);
|
||||
ok(_.isFunction(context.exports._), basename)
|
||||
break;
|
||||
|
||||
case 2:
|
||||
vm.runInContext(source, context);
|
||||
ok(_.isFunction(context._), basename);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
context.exports = {};
|
||||
context.module = { 'exports': context.exports };
|
||||
vm.runInContext(source, context);
|
||||
ok(context._ === undefined, basename);
|
||||
ok(_.isFunction(context.module.exports), basename);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
vm.runInContext(source, context);
|
||||
ok(context._ === undefined, basename);
|
||||
}
|
||||
start();
|
||||
});
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('iife command');
|
||||
|
||||
(function() {
|
||||
var commands = [
|
||||
'iife=this["lodash"]=(function(window,undefined){%output%;return lodash}(this))',
|
||||
'iife=define(function(window,undefined){return function(){%output%;return lodash}}(this));'
|
||||
];
|
||||
|
||||
commands.forEach(function(command) {
|
||||
asyncTest('`lodash ' + command +'`', function() {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
build(['-s', 'exports=none', command], function(source, filePath) {
|
||||
var basename = path.basename(filePath, '.js'),
|
||||
context = createContext();
|
||||
|
||||
context.define = function(func) {
|
||||
context.lodash = func();
|
||||
};
|
||||
|
||||
try {
|
||||
vm.runInContext(source, context);
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
var lodash = context.lodash || {};
|
||||
ok(_.isString(lodash.VERSION), basename);
|
||||
start();
|
||||
});
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('output options');
|
||||
|
||||
(function() {
|
||||
['-o a.js', '--output a.js'].forEach(function(command, index) {
|
||||
asyncTest('`lodash ' + command +'`', function() {
|
||||
var start = _.once(QUnit.start);
|
||||
|
||||
build(['-s'].concat(command.split(' ')), function(source, filePath) {
|
||||
equal(path.basename(filePath, '.js'), 'a', command);
|
||||
start();
|
||||
});
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('stdout options');
|
||||
|
||||
(function() {
|
||||
['-c', '--stdout'].forEach(function(command, index) {
|
||||
asyncTest('`lodash ' + command +'`', function() {
|
||||
var written,
|
||||
start = _.once(QUnit.start),
|
||||
write = process.stdout.write;
|
||||
|
||||
process.stdout.write = function(string) {
|
||||
written = string;
|
||||
};
|
||||
|
||||
build([command, 'exports=', 'include='], function(source) {
|
||||
process.stdout.write = write;
|
||||
equal(written, source);
|
||||
equal(arguments.length, 1);
|
||||
start();
|
||||
});
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('minify underscore');
|
||||
|
||||
(function() {
|
||||
asyncTest('`node minify underscore.js`', function() {
|
||||
var source = fs.readFileSync(path.join(__dirname, '..', 'vendor', 'underscore', 'underscore.js'), 'utf8'),
|
||||
start = _.once(QUnit.start);
|
||||
|
||||
minify(source, {
|
||||
'isSilent': true,
|
||||
'workingName': 'underscore.min',
|
||||
'onComplete': function(result) {
|
||||
var context = createContext();
|
||||
|
||||
try {
|
||||
vm.runInContext(result, context);
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
var underscore = context._ || {};
|
||||
ok(_.isString(underscore.VERSION));
|
||||
ok(!/Lo-Dash/.test(result) && result.match(/\n/g).length < source.match(/\n/g).length);
|
||||
start();
|
||||
}
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('mobile build');
|
||||
|
||||
(function() {
|
||||
asyncTest('`lodash mobile`', function() {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
build(['-s', 'mobile'], function(source, filePath) {
|
||||
var basename = path.basename(filePath, '.js'),
|
||||
context = createContext();
|
||||
|
||||
try {
|
||||
vm.runInContext(source, context);
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
var array = [1, 2, 3],
|
||||
object1 = [{ 'a': 1 }],
|
||||
object2 = [{ 'b': 2 }],
|
||||
object3 = [{ 'a': 1, 'b': 2 }],
|
||||
circular1 = { 'a': 1 },
|
||||
circular2 = { 'a': 1 },
|
||||
lodash = context._;
|
||||
|
||||
circular1.b = circular1;
|
||||
circular2.b = circular2;
|
||||
|
||||
deepEqual(lodash.merge(object1, object2), object3, basename);
|
||||
deepEqual(lodash.sortBy([3, 2, 1], _.identity), array, basename);
|
||||
equal(lodash.isEqual(circular1, circular2), true, basename);
|
||||
|
||||
var actual = lodash.clone(circular1, true);
|
||||
ok(actual != circular1 && actual.b == actual, basename);
|
||||
start();
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
QUnit.module('lodash build');
|
||||
|
||||
(function() {
|
||||
var commands = [
|
||||
'backbone',
|
||||
'csp',
|
||||
'legacy',
|
||||
'mobile',
|
||||
'strict',
|
||||
'underscore',
|
||||
'category=arrays',
|
||||
'category=chaining',
|
||||
'category=collections',
|
||||
'category=functions',
|
||||
'category=objects',
|
||||
'category=utilities',
|
||||
'exclude=union,uniq,zip',
|
||||
'include=each,filter,map',
|
||||
'include=once plus=bind,Chaining',
|
||||
'category=collections,functions',
|
||||
'underscore backbone',
|
||||
'backbone legacy category=utilities minus=first,last',
|
||||
'underscore include=debounce,throttle plus=after minus=throttle',
|
||||
'underscore mobile strict category=functions exports=amd,global plus=pick,uniq',
|
||||
]
|
||||
.concat(
|
||||
allMethods.map(function(methodName) {
|
||||
return 'include=' + methodName;
|
||||
})
|
||||
);
|
||||
|
||||
commands.forEach(function(command) {
|
||||
asyncTest('`lodash ' + command +'`', function() {
|
||||
var start = _.after(2, _.once(QUnit.start));
|
||||
|
||||
build(['--silent'].concat(command.split(' ')), function(source, filePath) {
|
||||
var methodNames,
|
||||
basename = path.basename(filePath, '.js'),
|
||||
context = createContext();
|
||||
|
||||
try {
|
||||
vm.runInContext(source, context);
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
}
|
||||
// add method names explicitly
|
||||
if (/include/.test(command)) {
|
||||
methodNames = command.match(/include=(\S*)/)[1].split(/, */);
|
||||
}
|
||||
// add method names required by Backbone and Underscore builds
|
||||
if (/backbone/.test(command) && !methodNames) {
|
||||
methodNames = backboneDependencies.slice();
|
||||
}
|
||||
if (/underscore/.test(command) && !methodNames) {
|
||||
methodNames = underscoreMethods.slice();
|
||||
}
|
||||
// add method names explicitly by category
|
||||
if (/category/.test(command)) {
|
||||
// resolve method names belonging to each category (case-insensitive)
|
||||
methodNames = command.match(/category=(\S*)/)[1].split(/, */).reduce(function(result, category) {
|
||||
var capitalized = category[0].toUpperCase() + category.toLowerCase().slice(1);
|
||||
return result.concat(getMethodsByCategory(capitalized));
|
||||
}, methodNames || []);
|
||||
}
|
||||
// init `methodNames` if it hasn't been inited
|
||||
if (!methodNames) {
|
||||
methodNames = allMethods.slice();
|
||||
}
|
||||
if (/plus/.test(command)) {
|
||||
methodNames = methodNames.concat(command.match(/plus=(\S*)/)[1].split(/, */));
|
||||
}
|
||||
if (/minus/.test(command)) {
|
||||
methodNames = _.without.apply(_, [methodNames]
|
||||
.concat(expandMethodNames(command.match(/minus=(\S*)/)[1].split(/, */))));
|
||||
}
|
||||
if (/exclude/.test(command)) {
|
||||
methodNames = _.without.apply(_, [methodNames]
|
||||
.concat(expandMethodNames(command.match(/exclude=(\S*)/)[1].split(/, */))));
|
||||
}
|
||||
|
||||
// expand aliases and categories to real method names
|
||||
methodNames = expandMethodNames(methodNames).reduce(function(result, methodName) {
|
||||
return result.concat(methodName, getMethodsByCategory(methodName));
|
||||
}, []);
|
||||
|
||||
// remove nonexistent and duplicate method names
|
||||
methodNames = _.uniq(_.intersection(allMethods, expandMethodNames(methodNames)));
|
||||
|
||||
var lodash = context._ || {};
|
||||
methodNames.forEach(function(methodName) {
|
||||
testMethod(lodash, methodName, basename);
|
||||
});
|
||||
|
||||
start();
|
||||
});
|
||||
});
|
||||
});
|
||||
}());
|
||||
|
||||
}());
|
||||
93
test/test-ui.js
Normal file
@@ -0,0 +1,93 @@
|
||||
;(function(window) {
|
||||
'use strict';
|
||||
|
||||
/** `QUnit.addEvent` shortcut */
|
||||
var addEvent = QUnit.addEvent;
|
||||
|
||||
/** The Lo-Dash build to load */
|
||||
var build = (/build=([^&]+)/.exec(location.search) || [])[1];
|
||||
|
||||
/** A flag to determine if RequireJS should be loaded */
|
||||
var norequire = /[?&]norequire=true(?:&|$)/.test(location.search);
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
// assign `QUnit.config` properties
|
||||
QUnit.config.lodashFilename = (function() {
|
||||
switch (build) {
|
||||
case 'prod': return 'lodash.min';
|
||||
case 'custom': return 'lodash.custom.min';
|
||||
case 'custom-debug': return 'lodash.custom';
|
||||
}
|
||||
return 'lodash';
|
||||
}());
|
||||
|
||||
// assign `QUnit.urlParams` properties
|
||||
QUnit.extend(QUnit.urlParams, {
|
||||
'build': build,
|
||||
'norequire': norequire
|
||||
});
|
||||
|
||||
// initialize the build dropdown
|
||||
addEvent(window, 'load', function() {
|
||||
function eventHandler(event) {
|
||||
var search = location.search.replace(/^\?|&?(?:build|norequire)=[^&]*&?/g, '');
|
||||
if (event.stopPropagation) {
|
||||
event.stopPropagation();
|
||||
} else {
|
||||
event.cancelBubble = true;
|
||||
}
|
||||
location.href =
|
||||
location.href.split('?')[0] + '?' +
|
||||
(search ? search + '&' : '') + 'build=' +
|
||||
dropdown[dropdown.selectedIndex].value +
|
||||
(checkbox.checked ? '&norequire=true' : '');
|
||||
}
|
||||
|
||||
function init() {
|
||||
var toolbar = document.getElementById('qunit-testrunner-toolbar');
|
||||
if (toolbar) {
|
||||
toolbar.appendChild(span1);
|
||||
toolbar.appendChild(span2);
|
||||
|
||||
dropdown.selectedIndex = (function() {
|
||||
switch (build) {
|
||||
case 'prod': return 1;
|
||||
case 'custom': return 2;
|
||||
case 'custom-debug': return 3;
|
||||
}
|
||||
return 0;
|
||||
}());
|
||||
|
||||
checkbox.checked = norequire;
|
||||
addEvent(checkbox, 'click', eventHandler);
|
||||
addEvent(dropdown, 'change', eventHandler);
|
||||
}
|
||||
else {
|
||||
setTimeout(init, 15);
|
||||
}
|
||||
}
|
||||
|
||||
var span1 = document.createElement('span');
|
||||
span1.innerHTML =
|
||||
'<input id="qunit-norequire" type="checkbox">' +
|
||||
'<label for="qunit-norequire">No RequireJS</label>';
|
||||
|
||||
var span2 = document.createElement('span');
|
||||
span2.style.cssText = 'float:right';
|
||||
span2.innerHTML =
|
||||
'<label for="qunit-build">Build: </label>' +
|
||||
'<select id="qunit-build">' +
|
||||
'<option value="dev">Developement</option>' +
|
||||
'<option value="prod">Production</option>' +
|
||||
'<option value="custom">Custom</option>' +
|
||||
'<option value="custom-debug">Custom (debug)</option>' +
|
||||
'</select>';
|
||||
|
||||
var checkbox = span1.firstChild,
|
||||
dropdown = span2.lastChild;
|
||||
|
||||
init();
|
||||
});
|
||||
|
||||
}(this));
|
||||
1785
test/test.js
49
test/underscore.html
Normal file
@@ -0,0 +1,49 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Underscore Test Suite</title>
|
||||
<link rel="stylesheet" href="../vendor/underscore/test/vendor/qunit.css">
|
||||
<style>
|
||||
#jslitmus, iframe {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture">
|
||||
<div id="map-test">
|
||||
<div id="id1"></div>
|
||||
<div id="id2"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="../vendor/backbone/test/vendor/json2.js"></script>
|
||||
<script src="../vendor/underscore/test/vendor/jquery.js"></script>
|
||||
<script src="../vendor/underscore/test/vendor/jslitmus.js"></script>
|
||||
<script src="../vendor/platform.js/platform.js"></script>
|
||||
<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>
|
||||
document.write('<script src="../' + QUnit.config.lodashFilename + '.js"><\/script>');
|
||||
</script>
|
||||
<script src="../vendor/underscore/test/collections.js"></script>
|
||||
<script src="../vendor/underscore/test/arrays.js"></script>
|
||||
<script src="../vendor/underscore/test/functions.js"></script>
|
||||
<script src="../vendor/underscore/test/objects.js"></script>
|
||||
<script src="../vendor/underscore/test/utility.js"></script>
|
||||
<script src="../vendor/underscore/test/chaining.js"></script>
|
||||
<script type="text/html" id="template">
|
||||
<%
|
||||
// a comment
|
||||
if (data) { data += 12345; }; %>
|
||||
<li><%= data %></li>
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,44 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Underscore Test Suite</title>
|
||||
<link rel="stylesheet" href="vendor/qunit.css" type="text/css" media="screen" />
|
||||
<script type="text/javascript" src="vendor/jquery.js"></script>
|
||||
<script type="text/javascript" src="vendor/qunit.js"></script>
|
||||
<script type="text/javascript" src="vendor/jslitmus.js"></script>
|
||||
<script type="text/javascript" src="../../lodash.js"></script>
|
||||
<script type="text/javascript" src="collections.js"></script>
|
||||
<script type="text/javascript" src="arrays.js"></script>
|
||||
<script type="text/javascript" src="functions.js"></script>
|
||||
<script type="text/javascript" src="objects.js"></script>
|
||||
<script type="text/javascript" src="utility.js"></script>
|
||||
<script type="text/javascript" src="chaining.js"></script>
|
||||
<script type="text/javascript" src="speed.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="underscore-test">
|
||||
<h1 id="qunit-header">Underscore Test Suite</h1>
|
||||
<div id="qunit-testrunner-toolbar"></div>
|
||||
<h2 id="qunit-banner"></h2>
|
||||
<h2 id="qunit-userAgent"></h2>
|
||||
<ol id="qunit-tests"></ol>
|
||||
<br />
|
||||
<h1 class="qunit-header">Underscore Speed Suite</h1>
|
||||
<p>
|
||||
A representative sample of the functions are benchmarked here, to provide
|
||||
a sense of how fast they might run in different browsers.
|
||||
Each iteration runs on an array of 1000 elements.<br /><br />
|
||||
For example, the 'intersect' test measures the number of times you can
|
||||
find the intersection of two thousand-element arrays in one second.
|
||||
</p>
|
||||
<br />
|
||||
|
||||
<script type="text/html" id="template">
|
||||
<%
|
||||
// a comment
|
||||
if (data) { data += 12345; }; %>
|
||||
<li><%= data %></li>
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,70 +0,0 @@
|
||||
(function() {
|
||||
|
||||
var numbers = [];
|
||||
for (var i=0; i<1000; i++) numbers.push(i);
|
||||
var objects = _.map(numbers, function(n){ return {num : n}; });
|
||||
var randomized = _.sortBy(numbers, function(){ return Math.random(); });
|
||||
|
||||
JSLitmus.test('_.each()', function() {
|
||||
var timesTwo = [];
|
||||
_.each(numbers, function(num){ timesTwo.push(num * 2); });
|
||||
return timesTwo;
|
||||
});
|
||||
|
||||
JSLitmus.test('_(list).each()', function() {
|
||||
var timesTwo = [];
|
||||
_(numbers).each(function(num){ timesTwo.push(num * 2); });
|
||||
return timesTwo;
|
||||
});
|
||||
|
||||
JSLitmus.test('jQuery.each()', function() {
|
||||
var timesTwo = [];
|
||||
jQuery.each(numbers, function(){ timesTwo.push(this * 2); });
|
||||
return timesTwo;
|
||||
});
|
||||
|
||||
JSLitmus.test('_.map()', function() {
|
||||
return _.map(objects, function(obj){ return obj.num; });
|
||||
});
|
||||
|
||||
JSLitmus.test('jQuery.map()', function() {
|
||||
return jQuery.map(objects, function(obj){ return obj.num; });
|
||||
});
|
||||
|
||||
JSLitmus.test('_.pluck()', function() {
|
||||
return _.pluck(objects, 'num');
|
||||
});
|
||||
|
||||
JSLitmus.test('_.uniq()', function() {
|
||||
return _.uniq(randomized);
|
||||
});
|
||||
|
||||
JSLitmus.test('_.uniq() (sorted)', function() {
|
||||
return _.uniq(numbers, true);
|
||||
});
|
||||
|
||||
JSLitmus.test('_.sortBy()', function() {
|
||||
return _.sortBy(numbers, function(num){ return -num; });
|
||||
});
|
||||
|
||||
JSLitmus.test('_.isEqual()', function() {
|
||||
return _.isEqual(numbers, randomized);
|
||||
});
|
||||
|
||||
JSLitmus.test('_.keys()', function() {
|
||||
return _.keys(objects);
|
||||
});
|
||||
|
||||
JSLitmus.test('_.values()', function() {
|
||||
return _.values(objects);
|
||||
});
|
||||
|
||||
JSLitmus.test('_.intersect()', function() {
|
||||
return _.intersect(numbers, randomized);
|
||||
});
|
||||
|
||||
JSLitmus.test('_.range()', function() {
|
||||
return _.range(1000);
|
||||
});
|
||||
|
||||
})();
|
||||
19
test/underscore/vendor/jquery.js
vendored
1597
test/underscore/vendor/qunit.js
vendored
22
vendor/backbone/LICENSE
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
Copyright (c) 2010-2012 Jeremy Ashkenas, DocumentCloud
|
||||
|
||||
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.
|
||||
26
vendor/backbone/README.md
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
____ __ __
|
||||
/\ _`\ /\ \ /\ \ __
|
||||
\ \ \ \ \ __ ___\ \ \/'\\ \ \____ ___ ___ __ /\_\ ____
|
||||
\ \ _ <' /'__`\ /'___\ \ , < \ \ '__`\ / __`\ /' _ `\ /'__`\ \/\ \ /',__\
|
||||
\ \ \ \ \/\ \ \.\_/\ \__/\ \ \\`\\ \ \ \ \/\ \ \ \/\ \/\ \/\ __/ __ \ \ \/\__, `\
|
||||
\ \____/\ \__/.\_\ \____\\ \_\ \_\ \_,__/\ \____/\ \_\ \_\ \____\/\_\_\ \ \/\____/
|
||||
\/___/ \/__/\/_/\/____/ \/_/\/_/\/___/ \/___/ \/_/\/_/\/____/\/_/\ \_\ \/___/
|
||||
\ \____/
|
||||
\/___/
|
||||
(_'_______________________________________________________________________________'_)
|
||||
(_.———————————————————————————————————————————————————————————————————————————————._)
|
||||
|
||||
|
||||
Backbone supplies structure to JavaScript-heavy applications by providing models key-value binding and custom events, collections with a rich API of enumerable functions, views with declarative event handling, and connects it all to your existing application over a RESTful JSON interface.
|
||||
|
||||
For Docs, License, Tests, pre-packed downloads, and everything else, really, see:
|
||||
http://backbonejs.org
|
||||
|
||||
To suggest a feature, report a bug, or general discussion:
|
||||
http://github.com/documentcloud/backbone/issues/
|
||||
|
||||
All contributors are listed here:
|
||||
http://github.com/documentcloud/backbone/contributors
|
||||
|
||||
Special thanks to Robert Kieffer for the original philosophy behind Backbone.
|
||||
http://github.com/broofa
|
||||
1479
vendor/backbone/backbone.js
vendored
Normal file
704
vendor/backbone/test/collection.js
vendored
Normal file
@@ -0,0 +1,704 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
var a, b, c, d, e, col, otherCol;
|
||||
|
||||
module("Backbone.Collection", _.extend(new Environment, {
|
||||
|
||||
setup: function() {
|
||||
Environment.prototype.setup.apply(this, arguments);
|
||||
|
||||
a = new Backbone.Model({id: 3, label: 'a'});
|
||||
b = new Backbone.Model({id: 2, label: 'b'});
|
||||
c = new Backbone.Model({id: 1, label: 'c'});
|
||||
d = new Backbone.Model({id: 0, label: 'd'});
|
||||
e = null;
|
||||
col = new Backbone.Collection([a,b,c,d]);
|
||||
otherCol = new Backbone.Collection();
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
test("new and sort", 7, function() {
|
||||
equal(col.first(), a, "a should be first");
|
||||
equal(col.last(), d, "d should be last");
|
||||
col.comparator = function(a, b) {
|
||||
return a.id > b.id ? -1 : 1;
|
||||
};
|
||||
col.sort();
|
||||
equal(col.first(), a, "a should be first");
|
||||
equal(col.last(), d, "d should be last");
|
||||
col.comparator = function(model) { return model.id; };
|
||||
col.sort();
|
||||
equal(col.first(), d, "d should be first");
|
||||
equal(col.last(), a, "a should be last");
|
||||
equal(col.length, 4);
|
||||
});
|
||||
|
||||
test("String comparator.", 1, function() {
|
||||
var collection = new Backbone.Collection([
|
||||
{id: 3},
|
||||
{id: 1},
|
||||
{id: 2}
|
||||
], {comparator: 'id'});
|
||||
deepEqual(collection.pluck('id'), [1, 2, 3]);
|
||||
});
|
||||
|
||||
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, getByCid", 3, function() {
|
||||
equal(col.get(0), d);
|
||||
equal(col.get(2), b);
|
||||
equal(col.getByCid(col.first().cid), col.first());
|
||||
});
|
||||
|
||||
test("get with non-default ids", 2, function() {
|
||||
var col = new Backbone.Collection();
|
||||
var MongoModel = Backbone.Model.extend({
|
||||
idAttribute: '_id'
|
||||
});
|
||||
var model = new MongoModel({_id: 100});
|
||||
col.push(model);
|
||||
equal(col.get(100), model);
|
||||
model.set({_id: 101});
|
||||
equal(col.get(101), model);
|
||||
});
|
||||
|
||||
test("update index when id changes", 3, function() {
|
||||
var col = new Backbone.Collection();
|
||||
col.add([
|
||||
{id : 0, name : 'one'},
|
||||
{id : 1, name : 'two'}
|
||||
]);
|
||||
var one = col.get(0);
|
||||
equal(one.get('name'), 'one');
|
||||
one.set({id : 101});
|
||||
equal(col.get(0), null);
|
||||
equal(col.get(101).get('name'), 'one');
|
||||
});
|
||||
|
||||
test("at", 1, function() {
|
||||
equal(col.at(2), c);
|
||||
});
|
||||
|
||||
test("pluck", 1, function() {
|
||||
equal(col.pluck('label').join(' '), 'a b c d');
|
||||
});
|
||||
|
||||
test("add", 10, function() {
|
||||
var added, opts, secondAdded;
|
||||
added = opts = secondAdded = null;
|
||||
e = new Backbone.Model({id: 10, label : 'e'});
|
||||
otherCol.add(e);
|
||||
otherCol.on('add', function() {
|
||||
secondAdded = true;
|
||||
});
|
||||
col.on('add', function(model, collection, options){
|
||||
added = model.get('label');
|
||||
opts = options;
|
||||
});
|
||||
col.add(e, {amazing: true});
|
||||
equal(added, 'e');
|
||||
equal(col.length, 5);
|
||||
equal(col.last(), e);
|
||||
equal(otherCol.length, 1);
|
||||
equal(secondAdded, null);
|
||||
ok(opts.amazing);
|
||||
|
||||
var f = new Backbone.Model({id: 20, label : 'f'});
|
||||
var g = new Backbone.Model({id: 21, label : 'g'});
|
||||
var h = new Backbone.Model({id: 22, label : 'h'});
|
||||
var atCol = new Backbone.Collection([f, g, h]);
|
||||
equal(atCol.length, 3);
|
||||
atCol.add(e, {at: 1});
|
||||
equal(atCol.length, 4);
|
||||
equal(atCol.at(1), e);
|
||||
equal(atCol.last(), h);
|
||||
});
|
||||
|
||||
test("add multiple models", 6, function() {
|
||||
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});
|
||||
for (var i = 0; i <= 5; i++) {
|
||||
equal(col.at(i).get('at'), i);
|
||||
}
|
||||
});
|
||||
|
||||
test("add; at should have preference over comparator", 1, function() {
|
||||
var Col = Backbone.Collection.extend({
|
||||
comparator: function(a,b) {
|
||||
return a.id > b.id ? -1 : 1;
|
||||
}
|
||||
});
|
||||
|
||||
var col = new Col([{id: 2}, {id: 3}]);
|
||||
col.add(new Backbone.Model({id: 1}), {at: 1});
|
||||
|
||||
equal(col.pluck('id').join(' '), '3 1 2');
|
||||
});
|
||||
|
||||
test("can't add model to collection twice", function() {
|
||||
var col = new Backbone.Collection([{id: 1}, {id: 2}, {id: 1}, {id: 2}, {id: 3}]);
|
||||
equal(col.pluck('id').join(' '), '1 2 3');
|
||||
});
|
||||
|
||||
test("can't add different model with same id to collection twice", 1, function() {
|
||||
var col = new Backbone.Collection;
|
||||
col.unshift({id: 101});
|
||||
col.add({id: 101});
|
||||
equal(col.length, 1);
|
||||
});
|
||||
|
||||
test("merge in duplicate models with {merge: true}", 3, function() {
|
||||
var col = new Backbone.Collection;
|
||||
col.add([{id: 1, name: 'Moe'}, {id: 2, name: 'Curly'}, {id: 3, name: 'Larry'}]);
|
||||
col.add({id: 1, name: 'Moses'});
|
||||
equal(col.first().get('name'), 'Moe');
|
||||
col.add({id: 1, name: 'Moses'}, {merge: true});
|
||||
equal(col.first().get('name'), 'Moses');
|
||||
col.add({id: 1, name: 'Tim'}, {merge: true, silent: true});
|
||||
equal(col.first().get('name'), 'Tim');
|
||||
});
|
||||
|
||||
test("add model to multiple collections", 10, function() {
|
||||
var counter = 0;
|
||||
var e = new Backbone.Model({id: 10, label : 'e'});
|
||||
e.on('add', function(model, collection) {
|
||||
counter++;
|
||||
equal(e, model);
|
||||
if (counter > 1) {
|
||||
equal(collection, colF);
|
||||
} else {
|
||||
equal(collection, colE);
|
||||
}
|
||||
});
|
||||
var colE = new Backbone.Collection([]);
|
||||
colE.on('add', function(model, collection) {
|
||||
equal(e, model);
|
||||
equal(colE, collection);
|
||||
});
|
||||
var colF = new Backbone.Collection([]);
|
||||
colF.on('add', function(model, collection) {
|
||||
equal(e, model);
|
||||
equal(colF, collection);
|
||||
});
|
||||
colE.add(e);
|
||||
equal(e.collection, colE);
|
||||
colF.add(e);
|
||||
equal(e.collection, colE);
|
||||
});
|
||||
|
||||
test("add model with parse", 1, function() {
|
||||
var Model = Backbone.Model.extend({
|
||||
parse: function(obj) {
|
||||
obj.value += 1;
|
||||
return obj;
|
||||
}
|
||||
});
|
||||
|
||||
var Col = Backbone.Collection.extend({model: Model});
|
||||
var col = new Col;
|
||||
col.add({value: 1}, {parse: true});
|
||||
equal(col.at(0).get('value'), 2);
|
||||
});
|
||||
|
||||
test("add model to collection with sort()-style comparator", 3, function() {
|
||||
var col = new Backbone.Collection;
|
||||
col.comparator = function(a, b) {
|
||||
return a.get('name') < b.get('name') ? -1 : 1;
|
||||
};
|
||||
var tom = new Backbone.Model({name: 'Tom'});
|
||||
var rob = new Backbone.Model({name: 'Rob'});
|
||||
var tim = new Backbone.Model({name: 'Tim'});
|
||||
col.add(tom);
|
||||
col.add(rob);
|
||||
col.add(tim);
|
||||
equal(col.indexOf(rob), 0);
|
||||
equal(col.indexOf(tim), 1);
|
||||
equal(col.indexOf(tom), 2);
|
||||
});
|
||||
|
||||
test("comparator that depends on `this`", 2, function() {
|
||||
var col = new Backbone.Collection;
|
||||
col.negative = function(num) {
|
||||
return -num;
|
||||
};
|
||||
col.comparator = function(a) {
|
||||
return this.negative(a.id);
|
||||
};
|
||||
col.add([{id: 1}, {id: 2}, {id: 3}]);
|
||||
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("remove", 5, function() {
|
||||
var removed = null;
|
||||
var otherRemoved = null;
|
||||
col.on('remove', function(model, col, options) {
|
||||
removed = model.get('label');
|
||||
equal(options.index, 3);
|
||||
});
|
||||
otherCol.on('remove', function(model, col, options) {
|
||||
otherRemoved = true;
|
||||
});
|
||||
col.remove(d);
|
||||
equal(removed, 'd');
|
||||
equal(col.length, 3);
|
||||
equal(col.first(), a);
|
||||
equal(otherRemoved, null);
|
||||
});
|
||||
|
||||
test("shift and pop", 2, function() {
|
||||
var col = new Backbone.Collection([{a: 'a'}, {b: 'b'}, {c: 'c'}]);
|
||||
equal(col.shift().get('a'), 'a');
|
||||
equal(col.pop().get('c'), 'c');
|
||||
});
|
||||
|
||||
test("slice", 2, function() {
|
||||
var col = new Backbone.Collection([{a: 'a'}, {b: 'b'}, {c: 'c'}]);
|
||||
var array = col.slice(1, 3);
|
||||
equal(array.length, 2);
|
||||
equal(array[0].get('b'), 'b');
|
||||
});
|
||||
|
||||
test("events are unbound on remove", 3, function() {
|
||||
var counter = 0;
|
||||
var dj = new Backbone.Model();
|
||||
var emcees = new Backbone.Collection([dj]);
|
||||
emcees.on('change', function(){ counter++; });
|
||||
dj.set({name : 'Kool'});
|
||||
equal(counter, 1);
|
||||
emcees.reset([]);
|
||||
equal(dj.collection, undefined);
|
||||
dj.set({name : 'Shadow'});
|
||||
equal(counter, 1);
|
||||
});
|
||||
|
||||
test("remove in multiple collections", 7, function() {
|
||||
var modelData = {
|
||||
id : 5,
|
||||
title : 'Othello'
|
||||
};
|
||||
var passed = false;
|
||||
var e = new Backbone.Model(modelData);
|
||||
var f = new Backbone.Model(modelData);
|
||||
f.on('remove', function() {
|
||||
passed = true;
|
||||
});
|
||||
var colE = new Backbone.Collection([e]);
|
||||
var colF = new Backbone.Collection([f]);
|
||||
ok(e != f);
|
||||
ok(colE.length == 1);
|
||||
ok(colF.length == 1);
|
||||
colE.remove(e);
|
||||
equal(passed, false);
|
||||
ok(colE.length == 0);
|
||||
colF.remove(e);
|
||||
ok(colF.length == 0);
|
||||
equal(passed, true);
|
||||
});
|
||||
|
||||
test("remove same model in multiple collection", 16, function() {
|
||||
var counter = 0;
|
||||
var e = new Backbone.Model({id: 5, title: 'Othello'});
|
||||
e.on('remove', function(model, collection) {
|
||||
counter++;
|
||||
equal(e, model);
|
||||
if (counter > 1) {
|
||||
equal(collection, colE);
|
||||
} else {
|
||||
equal(collection, colF);
|
||||
}
|
||||
});
|
||||
var colE = new Backbone.Collection([e]);
|
||||
colE.on('remove', function(model, collection) {
|
||||
equal(e, model);
|
||||
equal(colE, collection);
|
||||
});
|
||||
var colF = new Backbone.Collection([e]);
|
||||
colF.on('remove', function(model, collection) {
|
||||
equal(e, model);
|
||||
equal(colF, collection);
|
||||
});
|
||||
equal(colE, e.collection);
|
||||
colF.remove(e);
|
||||
ok(colF.length == 0);
|
||||
ok(colE.length == 1);
|
||||
equal(counter, 1);
|
||||
equal(colE, e.collection);
|
||||
colE.remove(e);
|
||||
equal(null, e.collection);
|
||||
ok(colE.length == 0);
|
||||
equal(counter, 2);
|
||||
});
|
||||
|
||||
test("model destroy removes from all collections", 3, function() {
|
||||
var e = new Backbone.Model({id: 5, title: 'Othello'});
|
||||
e.sync = function(method, model, options) { options.success({}); };
|
||||
var colE = new Backbone.Collection([e]);
|
||||
var colF = new Backbone.Collection([e]);
|
||||
e.destroy();
|
||||
ok(colE.length == 0);
|
||||
ok(colF.length == 0);
|
||||
equal(undefined, e.collection);
|
||||
});
|
||||
|
||||
test("Colllection: non-persisted model destroy removes from all collections", 3, function() {
|
||||
var e = new Backbone.Model({title: 'Othello'});
|
||||
e.sync = function(method, model, options) { throw "should not be called"; };
|
||||
var colE = new Backbone.Collection([e]);
|
||||
var colF = new Backbone.Collection([e]);
|
||||
e.destroy();
|
||||
ok(colE.length == 0);
|
||||
ok(colF.length == 0);
|
||||
equal(undefined, e.collection);
|
||||
});
|
||||
|
||||
test("fetch", 4, function() {
|
||||
var collection = new Backbone.Collection;
|
||||
collection.url = '/test';
|
||||
collection.fetch();
|
||||
equal(this.syncArgs.method, 'read');
|
||||
equal(this.syncArgs.model, collection);
|
||||
equal(this.syncArgs.options.parse, true);
|
||||
|
||||
collection.fetch({parse: false});
|
||||
equal(this.syncArgs.options.parse, false);
|
||||
});
|
||||
|
||||
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.collection, collection);
|
||||
});
|
||||
|
||||
test("create enforces validation", 1, function() {
|
||||
var ValidatingModel = Backbone.Model.extend({
|
||||
validate: function(attrs) {
|
||||
return "fail";
|
||||
}
|
||||
});
|
||||
var ValidatingCollection = Backbone.Collection.extend({
|
||||
model: ValidatingModel
|
||||
});
|
||||
var col = new ValidatingCollection();
|
||||
equal(col.create({"foo":"bar"}), false);
|
||||
});
|
||||
|
||||
test("a failing create runs the error callback", 1, function() {
|
||||
var ValidatingModel = Backbone.Model.extend({
|
||||
validate: function(attrs) {
|
||||
return "fail";
|
||||
}
|
||||
});
|
||||
var ValidatingCollection = Backbone.Collection.extend({
|
||||
model: ValidatingModel
|
||||
});
|
||||
var flag = false;
|
||||
var callback = function(model, error) { flag = true; };
|
||||
var col = new ValidatingCollection();
|
||||
col.create({"foo":"bar"}, { error: callback });
|
||||
equal(flag, true);
|
||||
});
|
||||
|
||||
test("initialize", 1, function() {
|
||||
var Collection = Backbone.Collection.extend({
|
||||
initialize: function() {
|
||||
this.one = 1;
|
||||
}
|
||||
});
|
||||
var coll = new Collection;
|
||||
equal(coll.one, 1);
|
||||
});
|
||||
|
||||
test("toJSON", 1, function() {
|
||||
equal(JSON.stringify(col), '[{"id":3,"label":"a"},{"id":2,"label":"b"},{"id":1,"label":"c"},{"id":0,"label":"d"}]');
|
||||
});
|
||||
|
||||
test("where", 6, function() {
|
||||
var coll = new Backbone.Collection([
|
||||
{a: 1},
|
||||
{a: 1},
|
||||
{a: 1, b: 2},
|
||||
{a: 2, b: 2},
|
||||
{a: 3}
|
||||
]);
|
||||
equal(coll.where({a: 1}).length, 3);
|
||||
equal(coll.where({a: 2}).length, 1);
|
||||
equal(coll.where({a: 3}).length, 1);
|
||||
equal(coll.where({b: 1}).length, 0);
|
||||
equal(coll.where({b: 2}).length, 2);
|
||||
equal(coll.where({a: 1, b: 2}).length, 1);
|
||||
});
|
||||
|
||||
test("Underscore methods", 13, function() {
|
||||
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 === 0; }), true);
|
||||
equal(col.indexOf(b), 1);
|
||||
equal(col.size(), 4);
|
||||
equal(col.rest().length, 3);
|
||||
ok(!_.include(col.rest()), a);
|
||||
ok(!_.include(col.rest()), d);
|
||||
ok(!col.isEmpty());
|
||||
ok(!_.include(col.without(d)), d);
|
||||
equal(col.max(function(model){ return model.id; }).id, 3);
|
||||
equal(col.min(function(model){ return model.id; }).id, 0);
|
||||
deepEqual(col.chain()
|
||||
.filter(function(o){ return o.id % 2 === 0; })
|
||||
.map(function(o){ return o.id * 2; })
|
||||
.value(),
|
||||
[4, 0]);
|
||||
});
|
||||
|
||||
test("reset", 10, function() {
|
||||
var resetCount = 0;
|
||||
var models = col.models;
|
||||
col.on('reset', function() { resetCount += 1; });
|
||||
col.reset([]);
|
||||
equal(resetCount, 1);
|
||||
equal(col.length, 0);
|
||||
equal(col.last(), null);
|
||||
col.reset(models);
|
||||
equal(resetCount, 2);
|
||||
equal(col.length, 4);
|
||||
equal(col.last(), d);
|
||||
col.reset(_.map(models, function(m){ return m.attributes; }));
|
||||
equal(resetCount, 3);
|
||||
equal(col.length, 4);
|
||||
ok(col.last() !== d);
|
||||
ok(_.isEqual(col.last().attributes, d.attributes));
|
||||
});
|
||||
|
||||
test("reset passes caller options", 3, function() {
|
||||
var Model = Backbone.Model.extend({
|
||||
initialize: function(attrs, options) {
|
||||
this.model_parameter = options.model_parameter;
|
||||
}
|
||||
});
|
||||
var col = new (Backbone.Collection.extend({ model: Model }))();
|
||||
col.reset([{ astring: "green", anumber: 1 }, { astring: "blue", anumber: 2 }], { model_parameter: 'model parameter' });
|
||||
equal(col.length, 2);
|
||||
col.each(function(model) {
|
||||
equal(model.model_parameter, 'model parameter');
|
||||
});
|
||||
});
|
||||
|
||||
test("trigger custom events on models", 1, function() {
|
||||
var fired = null;
|
||||
a.on("custom", function() { fired = true; });
|
||||
a.trigger("custom");
|
||||
equal(fired, true);
|
||||
});
|
||||
|
||||
test("add does not alter arguments", 2, function(){
|
||||
var attrs = {};
|
||||
var models = [attrs];
|
||||
new Backbone.Collection().add(models);
|
||||
equal(models.length, 1);
|
||||
ok(attrs === models[0]);
|
||||
});
|
||||
|
||||
test("#714: access `model.collection` in a brand new model.", 2, function() {
|
||||
var collection = new Backbone.Collection;
|
||||
collection.url = '/test';
|
||||
var Model = Backbone.Model.extend({
|
||||
set: function(attrs) {
|
||||
equal(attrs.prop, 'value');
|
||||
equal(this.collection, collection);
|
||||
return this;
|
||||
}
|
||||
});
|
||||
collection.model = Model;
|
||||
collection.create({prop: 'value'});
|
||||
});
|
||||
|
||||
test("#574, remove its own reference to the .models array.", 2, function() {
|
||||
var col = new Backbone.Collection([
|
||||
{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}, {id: 6}
|
||||
]);
|
||||
equal(col.length, 6);
|
||||
col.remove(col.models);
|
||||
equal(col.length, 0);
|
||||
});
|
||||
|
||||
test("#861, adding models to a collection which do not pass validation", 1, function() {
|
||||
raises(function() {
|
||||
var Model = Backbone.Model.extend({
|
||||
validate: function(attrs) {
|
||||
if (attrs.id == 3) return "id can't be 3";
|
||||
}
|
||||
});
|
||||
|
||||
var Collection = Backbone.Collection.extend({
|
||||
model: Model
|
||||
});
|
||||
|
||||
var col = new Collection;
|
||||
|
||||
col.add([{id: 1}, {id: 2}, {id: 3}, {id: 4}, {id: 5}, {id: 6}]);
|
||||
}, function(e) {
|
||||
return e.message === "Can't add an invalid model to a collection";
|
||||
});
|
||||
});
|
||||
|
||||
test("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'; }
|
||||
});
|
||||
var model = new col.model({id: 1, valid: true});
|
||||
raises(function() { col.add([model, {id: 2}]); });
|
||||
model.trigger('test');
|
||||
ok(!col.getByCid(model.cid));
|
||||
ok(!col.get(1));
|
||||
equal(col.length, 0);
|
||||
});
|
||||
|
||||
test("multiple copies of the same model", 3, function() {
|
||||
var col = new Backbone.Collection();
|
||||
var model = new Backbone.Model();
|
||||
col.add([model, model]);
|
||||
equal(col.length, 1);
|
||||
col.add([{id: 1}, {id: 1}]);
|
||||
equal(col.length, 2);
|
||||
equal(col.last().id, 1);
|
||||
});
|
||||
|
||||
test("#964 - collection.get return inconsistent", 2, function() {
|
||||
var c = new Backbone.Collection();
|
||||
ok(c.get(null) === undefined);
|
||||
ok(c.get() === undefined);
|
||||
});
|
||||
|
||||
test("#1112 - passing options.model sets collection.model", 2, function() {
|
||||
var Model = Backbone.Model.extend({});
|
||||
var c = new Backbone.Collection([{id: 1}], {model: Model});
|
||||
ok(c.model === Model);
|
||||
ok(c.at(0) instanceof Model);
|
||||
});
|
||||
|
||||
test("null and undefined are invalid ids.", 2, function() {
|
||||
var model = new Backbone.Model({id: 1});
|
||||
var collection = new Backbone.Collection([model]);
|
||||
model.set({id: null});
|
||||
ok(!collection.get('null'));
|
||||
model.set({id: 1});
|
||||
model.set({id: undefined});
|
||||
ok(!collection.get('undefined'));
|
||||
});
|
||||
|
||||
test("falsy comparator", 4, function(){
|
||||
var Col = Backbone.Collection.extend({
|
||||
comparator: function(model){ return model.id; }
|
||||
});
|
||||
var col = new Col();
|
||||
var colFalse = new Col(null, {comparator: false});
|
||||
var colNull = new Col(null, {comparator: null});
|
||||
var colUndefined = new Col(null, {comparator: undefined});
|
||||
ok(col.comparator);
|
||||
ok(!colFalse.comparator);
|
||||
ok(!colNull.comparator);
|
||||
ok(colUndefined.comparator);
|
||||
});
|
||||
|
||||
test("#1355 - `options` is passed to success callbacks", 2, function(){
|
||||
var m = new Backbone.Model({x:1});
|
||||
var col = new Backbone.Collection();
|
||||
var opts = {
|
||||
success: function(collection, resp, options){
|
||||
ok(options);
|
||||
}
|
||||
};
|
||||
col.sync = m.sync = function( method, collection, options ){
|
||||
options.success();
|
||||
};
|
||||
col.fetch(opts);
|
||||
col.create(m, opts);
|
||||
});
|
||||
|
||||
test("#1412 - Trigger 'sync' event.", 2, function() {
|
||||
var collection = new Backbone.Collection;
|
||||
collection.url = '/test';
|
||||
collection.on('sync', function() { ok(true); });
|
||||
Backbone.ajax = function(settings){ settings.success(); };
|
||||
collection.fetch();
|
||||
collection.create({id: 1});
|
||||
});
|
||||
|
||||
test("#1447 - create with wait adds model.", 1, function() {
|
||||
var collection = new Backbone.Collection;
|
||||
var model = new Backbone.Model;
|
||||
model.sync = function(method, model, options){ options.success(); };
|
||||
collection.on('add', function(){ ok(true); });
|
||||
collection.create(model, {wait: true});
|
||||
});
|
||||
|
||||
test("#1448 - add sorts collection after merge.", 1, function() {
|
||||
var collection = new Backbone.Collection([
|
||||
{id: 1, x: 1},
|
||||
{id: 2, x: 2}
|
||||
]);
|
||||
collection.comparator = function(model){ return model.get('x'); };
|
||||
collection.add({id: 1, x: 3}, {merge: true});
|
||||
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]);
|
||||
});
|
||||
});
|
||||
39
vendor/backbone/test/environment.js
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
(function() {
|
||||
|
||||
var Environment = this.Environment = function(){};
|
||||
|
||||
_.extend(Environment.prototype, {
|
||||
|
||||
ajax: Backbone.ajax,
|
||||
|
||||
sync: Backbone.sync,
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
195
vendor/backbone/test/events.js
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
module("Backbone.Events");
|
||||
|
||||
test("on and trigger", 2, function() {
|
||||
var obj = { counter: 0 };
|
||||
_.extend(obj,Backbone.Events);
|
||||
obj.on('event', function() { obj.counter += 1; });
|
||||
obj.trigger('event');
|
||||
equal(obj.counter,1,'counter should be incremented.');
|
||||
obj.trigger('event');
|
||||
obj.trigger('event');
|
||||
obj.trigger('event');
|
||||
obj.trigger('event');
|
||||
equal(obj.counter, 5, 'counter should be incremented five times.');
|
||||
});
|
||||
|
||||
test("binding and triggering multiple events", 4, function() {
|
||||
var obj = { counter: 0 };
|
||||
_.extend(obj,Backbone.Events);
|
||||
|
||||
obj.on('a b c', function() { obj.counter += 1; });
|
||||
|
||||
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 c');
|
||||
obj.trigger('a b c');
|
||||
equal(obj.counter, 5);
|
||||
});
|
||||
|
||||
test("trigger all for each event", 3, function() {
|
||||
var a, b, obj = { counter: 0 };
|
||||
_.extend(obj, Backbone.Events);
|
||||
obj.on('all', function(event) {
|
||||
obj.counter++;
|
||||
if (event == 'a') a = true;
|
||||
if (event == 'b') b = true;
|
||||
})
|
||||
.trigger('a b');
|
||||
ok(a);
|
||||
ok(b);
|
||||
equal(obj.counter, 2);
|
||||
});
|
||||
|
||||
test("on, then unbind all functions", 1, function() {
|
||||
var obj = { counter: 0 };
|
||||
_.extend(obj,Backbone.Events);
|
||||
var callback = function() { obj.counter += 1; };
|
||||
obj.on('event', callback);
|
||||
obj.trigger('event');
|
||||
obj.off('event');
|
||||
obj.trigger('event');
|
||||
equal(obj.counter, 1, 'counter should have only been incremented once.');
|
||||
});
|
||||
|
||||
test("bind two callbacks, unbind only one", 2, function() {
|
||||
var obj = { counterA: 0, counterB: 0 };
|
||||
_.extend(obj,Backbone.Events);
|
||||
var callback = function() { obj.counterA += 1; };
|
||||
obj.on('event', callback);
|
||||
obj.on('event', function() { obj.counterB += 1; });
|
||||
obj.trigger('event');
|
||||
obj.off('event', callback);
|
||||
obj.trigger('event');
|
||||
equal(obj.counterA, 1, 'counterA should have only been incremented once.');
|
||||
equal(obj.counterB, 2, 'counterB should have been incremented twice.');
|
||||
});
|
||||
|
||||
test("unbind a callback in the midst of it firing", 1, function() {
|
||||
var obj = {counter: 0};
|
||||
_.extend(obj, Backbone.Events);
|
||||
var callback = function() {
|
||||
obj.counter += 1;
|
||||
obj.off('event', callback);
|
||||
};
|
||||
obj.on('event', callback);
|
||||
obj.trigger('event');
|
||||
obj.trigger('event');
|
||||
obj.trigger('event');
|
||||
equal(obj.counter, 1, 'the callback should have been unbound.');
|
||||
});
|
||||
|
||||
test("two binds that unbind themeselves", 2, function() {
|
||||
var obj = { counterA: 0, counterB: 0 };
|
||||
_.extend(obj,Backbone.Events);
|
||||
var incrA = function(){ obj.counterA += 1; obj.off('event', incrA); };
|
||||
var incrB = function(){ obj.counterB += 1; obj.off('event', incrB); };
|
||||
obj.on('event', incrA);
|
||||
obj.on('event', incrB);
|
||||
obj.trigger('event');
|
||||
obj.trigger('event');
|
||||
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("bind a callback with a supplied context", 1, function () {
|
||||
var TestClass = function () {
|
||||
return this;
|
||||
};
|
||||
TestClass.prototype.assertTrue = function () {
|
||||
ok(true, '`this` was bound to the callback');
|
||||
};
|
||||
|
||||
var obj = _.extend({},Backbone.Events);
|
||||
obj.on('event', function () { this.assertTrue(); }, (new TestClass));
|
||||
obj.trigger('event');
|
||||
});
|
||||
|
||||
test("nested trigger with unbind", 1, function () {
|
||||
var obj = { counter: 0 };
|
||||
_.extend(obj, Backbone.Events);
|
||||
var incr1 = function(){ obj.counter += 1; obj.off('event', incr1); obj.trigger('event'); };
|
||||
var incr2 = function(){ obj.counter += 1; };
|
||||
obj.on('event', incr1);
|
||||
obj.on('event', incr2);
|
||||
obj.trigger('event');
|
||||
equal(obj.counter, 3, 'counter should have been incremented three times');
|
||||
});
|
||||
|
||||
test("callback list is not altered during trigger", 2, function () {
|
||||
var counter = 0, obj = _.extend({}, Backbone.Events);
|
||||
var incr = function(){ counter++; };
|
||||
obj.on('event', function(){ obj.on('event', incr).on('all', incr); })
|
||||
.trigger('event');
|
||||
equal(counter, 0, 'bind does not alter callback list');
|
||||
obj.off()
|
||||
.on('event', function(){ obj.off('event', incr).off('all', incr); })
|
||||
.on('event', incr)
|
||||
.on('all', incr)
|
||||
.trigger('event');
|
||||
equal(counter, 2, 'unbind does not alter callback list');
|
||||
});
|
||||
|
||||
test("#1282 - 'all' callback list is retrieved after each event.", 1, function() {
|
||||
var counter = 0;
|
||||
var obj = _.extend({}, Backbone.Events);
|
||||
var incr = function(){ counter++; };
|
||||
obj.on('x', function() {
|
||||
obj.on('y', incr).on('all', incr);
|
||||
})
|
||||
.trigger('x y');
|
||||
strictEqual(counter, 2);
|
||||
});
|
||||
|
||||
test("if no callback is provided, `on` is a noop", 0, function() {
|
||||
_.extend({}, Backbone.Events).on('test').trigger('test');
|
||||
});
|
||||
|
||||
test("remove all events for a specific context", 4, function() {
|
||||
var obj = _.extend({}, Backbone.Events);
|
||||
obj.on('x y all', function() { ok(true); });
|
||||
obj.on('x y all', function() { ok(false); }, obj);
|
||||
obj.off(null, null, obj);
|
||||
obj.trigger('x y');
|
||||
});
|
||||
|
||||
test("remove all events for a specific callback", 4, function() {
|
||||
var obj = _.extend({}, Backbone.Events);
|
||||
var success = function() { ok(true); };
|
||||
var fail = function() { ok(false); };
|
||||
obj.on('x y all', success);
|
||||
obj.on('x y all', fail);
|
||||
obj.off(null, fail);
|
||||
obj.trigger('x y');
|
||||
});
|
||||
|
||||
test("off is chainable", 3, function() {
|
||||
var obj = _.extend({}, Backbone.Events);
|
||||
// With no events
|
||||
ok(obj.off() === obj);
|
||||
// When removing all events
|
||||
obj.on('event', function(){}, obj);
|
||||
ok(obj.off() === obj);
|
||||
// When removing some events
|
||||
obj.on('event', function(){}, obj);
|
||||
ok(obj.off('event') === obj);
|
||||
});
|
||||
|
||||
test("#1310 - off does not skip consecutive events", 0, function() {
|
||||
var obj = _.extend({}, Backbone.Events);
|
||||
obj.on('event', function() { ok(false); }, obj);
|
||||
obj.on('event', function() { ok(false); }, obj);
|
||||
obj.off(null, null, obj);
|
||||
obj.trigger('event');
|
||||
});
|
||||
|
||||
});
|
||||
881
vendor/backbone/test/model.js
vendored
Normal file
@@ -0,0 +1,881 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
var proxy = Backbone.Model.extend();
|
||||
var klass = Backbone.Collection.extend({
|
||||
url : function() { return '/collection'; }
|
||||
});
|
||||
var doc, collection;
|
||||
|
||||
module("Backbone.Model", _.extend(new Environment, {
|
||||
|
||||
setup: function() {
|
||||
Environment.prototype.setup.apply(this, arguments);
|
||||
doc = new proxy({
|
||||
id : '1-the-tempest',
|
||||
title : "The Tempest",
|
||||
author : "Bill Shakespeare",
|
||||
length : 123
|
||||
});
|
||||
collection = new klass();
|
||||
collection.add(doc);
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
test("initialize", 3, function() {
|
||||
var Model = Backbone.Model.extend({
|
||||
initialize: function() {
|
||||
this.one = 1;
|
||||
equal(this.collection, collection);
|
||||
}
|
||||
});
|
||||
var model = new Model({}, {collection: collection});
|
||||
equal(model.one, 1);
|
||||
equal(model.collection, collection);
|
||||
});
|
||||
|
||||
test("initialize with attributes and options", 1, function() {
|
||||
var Model = Backbone.Model.extend({
|
||||
initialize: function(attributes, options) {
|
||||
this.one = options.one;
|
||||
}
|
||||
});
|
||||
var model = new Model({}, {one: 1});
|
||||
equal(model.one, 1);
|
||||
});
|
||||
|
||||
test("initialize with parsed attributes", 1, function() {
|
||||
var Model = Backbone.Model.extend({
|
||||
parse: function(obj) {
|
||||
obj.value += 1;
|
||||
return obj;
|
||||
}
|
||||
});
|
||||
var model = new Model({value: 1}, {parse: true});
|
||||
equal(model.get('value'), 2);
|
||||
});
|
||||
|
||||
test("url", 3, function() {
|
||||
doc.urlRoot = null;
|
||||
equal(doc.url(), '/collection/1-the-tempest');
|
||||
doc.collection.url = '/collection/';
|
||||
equal(doc.url(), '/collection/1-the-tempest');
|
||||
doc.collection = null;
|
||||
raises(function() { doc.url(); });
|
||||
doc.collection = collection;
|
||||
});
|
||||
|
||||
test("url when using urlRoot, and uri encoding", 2, function() {
|
||||
var Model = Backbone.Model.extend({
|
||||
urlRoot: '/collection'
|
||||
});
|
||||
var model = new Model();
|
||||
equal(model.url(), '/collection');
|
||||
model.set({id: '+1+'});
|
||||
equal(model.url(), '/collection/%2B1%2B');
|
||||
});
|
||||
|
||||
test("url when using urlRoot as a function to determine urlRoot at runtime", 2, function() {
|
||||
var Model = Backbone.Model.extend({
|
||||
urlRoot: function() {
|
||||
return '/nested/' + this.get('parent_id') + '/collection';
|
||||
}
|
||||
});
|
||||
|
||||
var model = new Model({parent_id: 1});
|
||||
equal(model.url(), '/nested/1/collection');
|
||||
model.set({id: 2});
|
||||
equal(model.url(), '/nested/1/collection/2');
|
||||
});
|
||||
|
||||
test("clone", 8, function() {
|
||||
var a = new Backbone.Model({ 'foo': 1, 'bar': 2, 'baz': 3});
|
||||
var b = a.clone();
|
||||
equal(a.get('foo'), 1);
|
||||
equal(a.get('bar'), 2);
|
||||
equal(a.get('baz'), 3);
|
||||
equal(b.get('foo'), a.get('foo'), "Foo should be the same on the clone.");
|
||||
equal(b.get('bar'), a.get('bar'), "Bar should be the same on the clone.");
|
||||
equal(b.get('baz'), a.get('baz'), "Baz should be the same on the clone.");
|
||||
a.set({foo : 100});
|
||||
equal(a.get('foo'), 100);
|
||||
equal(b.get('foo'), 1, "Changing a parent attribute does not change the clone.");
|
||||
});
|
||||
|
||||
test("isNew", 6, function() {
|
||||
var a = new Backbone.Model({ 'foo': 1, 'bar': 2, 'baz': 3});
|
||||
ok(a.isNew(), "it should be new");
|
||||
a = new Backbone.Model({ 'foo': 1, 'bar': 2, 'baz': 3, 'id': -5 });
|
||||
ok(!a.isNew(), "any defined ID is legal, negative or positive");
|
||||
a = new Backbone.Model({ 'foo': 1, 'bar': 2, 'baz': 3, 'id': 0 });
|
||||
ok(!a.isNew(), "any defined ID is legal, including zero");
|
||||
ok( new Backbone.Model({ }).isNew(), "is true when there is no id");
|
||||
ok(!new Backbone.Model({ 'id': 2 }).isNew(), "is false for a positive integer");
|
||||
ok(!new Backbone.Model({ 'id': -5 }).isNew(), "is false for a negative integer");
|
||||
});
|
||||
|
||||
test("get", 2, function() {
|
||||
equal(doc.get('title'), 'The Tempest');
|
||||
equal(doc.get('author'), 'Bill Shakespeare');
|
||||
});
|
||||
|
||||
test("escape", 5, function() {
|
||||
equal(doc.escape('title'), 'The Tempest');
|
||||
doc.set({audience: 'Bill & Bob'});
|
||||
equal(doc.escape('audience'), 'Bill & Bob');
|
||||
doc.set({audience: 'Tim > Joan'});
|
||||
equal(doc.escape('audience'), 'Tim > Joan');
|
||||
doc.set({audience: 10101});
|
||||
equal(doc.escape('audience'), '10101');
|
||||
doc.unset('audience');
|
||||
equal(doc.escape('audience'), '');
|
||||
});
|
||||
|
||||
test("has", 10, function() {
|
||||
var model = new Backbone.Model();
|
||||
|
||||
strictEqual(model.has('name'), false);
|
||||
|
||||
model.set({
|
||||
'0': 0,
|
||||
'1': 1,
|
||||
'true': true,
|
||||
'false': false,
|
||||
'empty': '',
|
||||
'name': 'name',
|
||||
'null': null,
|
||||
'undefined': undefined
|
||||
});
|
||||
|
||||
strictEqual(model.has('0'), true);
|
||||
strictEqual(model.has('1'), true);
|
||||
strictEqual(model.has('true'), true);
|
||||
strictEqual(model.has('false'), true);
|
||||
strictEqual(model.has('empty'), true);
|
||||
strictEqual(model.has('name'), true);
|
||||
|
||||
model.unset('name');
|
||||
|
||||
strictEqual(model.has('name'), false);
|
||||
strictEqual(model.has('null'), false);
|
||||
strictEqual(model.has('undefined'), false);
|
||||
});
|
||||
|
||||
test("set and unset", 8, function() {
|
||||
var a = new Backbone.Model({id: 'id', foo: 1, bar: 2, baz: 3});
|
||||
var changeCount = 0;
|
||||
a.on("change:foo", function() { changeCount += 1; });
|
||||
a.set({'foo': 2});
|
||||
ok(a.get('foo') == 2, "Foo should have changed.");
|
||||
ok(changeCount == 1, "Change count should have incremented.");
|
||||
a.set({'foo': 2}); // set with value that is not new shouldn't fire change event
|
||||
ok(a.get('foo') == 2, "Foo should NOT have changed, still 2");
|
||||
ok(changeCount == 1, "Change count should NOT have incremented.");
|
||||
|
||||
a.validate = function(attrs) {
|
||||
equal(attrs.foo, void 0, "don't ignore values when unsetting");
|
||||
};
|
||||
a.unset('foo');
|
||||
equal(a.get('foo'), void 0, "Foo should have changed");
|
||||
delete a.validate;
|
||||
ok(changeCount == 2, "Change count should have incremented for unset.");
|
||||
|
||||
a.unset('id');
|
||||
equal(a.id, undefined, "Unsetting the id should remove the id property.");
|
||||
});
|
||||
|
||||
test("multiple unsets", 1, function() {
|
||||
var i = 0;
|
||||
var counter = function(){ i++; };
|
||||
var model = new Backbone.Model({a: 1});
|
||||
model.on("change:a", counter);
|
||||
model.set({a: 2});
|
||||
model.unset('a');
|
||||
model.unset('a');
|
||||
equal(i, 2, 'Unset does not fire an event for missing attributes.');
|
||||
});
|
||||
|
||||
test("unset and changedAttributes", 2, function() {
|
||||
var model = new Backbone.Model({a: 1});
|
||||
model.unset('a', {silent: true});
|
||||
var changedAttributes = model.changedAttributes();
|
||||
ok('a' in changedAttributes, 'changedAttributes should contain unset properties');
|
||||
|
||||
changedAttributes = model.changedAttributes();
|
||||
ok('a' in changedAttributes, 'changedAttributes should contain unset properties when running changedAttributes again after an unset.');
|
||||
});
|
||||
|
||||
test("using a non-default id attribute.", 5, function() {
|
||||
var MongoModel = Backbone.Model.extend({idAttribute : '_id'});
|
||||
var model = new MongoModel({id: 'eye-dee', _id: 25, title: 'Model'});
|
||||
equal(model.get('id'), 'eye-dee');
|
||||
equal(model.id, 25);
|
||||
equal(model.isNew(), false);
|
||||
model.unset('_id');
|
||||
equal(model.id, undefined);
|
||||
equal(model.isNew(), true);
|
||||
});
|
||||
|
||||
test("set an empty string", 1, function() {
|
||||
var model = new Backbone.Model({name : "Model"});
|
||||
model.set({name : ''});
|
||||
equal(model.get('name'), '');
|
||||
});
|
||||
|
||||
test("clear", 3, function() {
|
||||
var changed;
|
||||
var model = new Backbone.Model({id: 1, name : "Model"});
|
||||
model.on("change:name", function(){ changed = true; });
|
||||
model.on("change", function() {
|
||||
var changedAttrs = model.changedAttributes();
|
||||
ok('name' in changedAttrs);
|
||||
});
|
||||
model.clear();
|
||||
equal(changed, true);
|
||||
equal(model.get('name'), undefined);
|
||||
});
|
||||
|
||||
test("defaults", 4, function() {
|
||||
var Defaulted = Backbone.Model.extend({
|
||||
defaults: {
|
||||
"one": 1,
|
||||
"two": 2
|
||||
}
|
||||
});
|
||||
var model = new Defaulted({two: null});
|
||||
equal(model.get('one'), 1);
|
||||
equal(model.get('two'), null);
|
||||
Defaulted = Backbone.Model.extend({
|
||||
defaults: function() {
|
||||
return {
|
||||
"one": 3,
|
||||
"two": 4
|
||||
};
|
||||
}
|
||||
});
|
||||
var model = new Defaulted({two: null});
|
||||
equal(model.get('one'), 3);
|
||||
equal(model.get('two'), null);
|
||||
});
|
||||
|
||||
test("change, hasChanged, changedAttributes, previous, previousAttributes", 12, function() {
|
||||
var model = new Backbone.Model({name : "Tim", age : 10});
|
||||
equal(model.changedAttributes(), false);
|
||||
model.on('change', function() {
|
||||
ok(model.hasChanged('name'), 'name changed');
|
||||
ok(!model.hasChanged('age'), 'age did not');
|
||||
ok(_.isEqual(model.changedAttributes(), {name : 'Rob'}), 'changedAttributes returns the changed attrs');
|
||||
equal(model.previous('name'), 'Tim');
|
||||
ok(_.isEqual(model.previousAttributes(), {name : "Tim", age : 10}), 'previousAttributes is correct');
|
||||
});
|
||||
equal(model.hasChanged(), false);
|
||||
equal(model.hasChanged(undefined), false);
|
||||
model.set({name : 'Rob'}, {silent : true});
|
||||
equal(model.hasChanged(), true);
|
||||
equal(model.hasChanged(undefined), true);
|
||||
equal(model.hasChanged('name'), true);
|
||||
model.change();
|
||||
equal(model.get('name'), 'Rob');
|
||||
|
||||
});
|
||||
|
||||
test("changedAttributes", 3, function() {
|
||||
var model = new Backbone.Model({a: 'a', b: 'b'});
|
||||
equal(model.changedAttributes(), false);
|
||||
equal(model.changedAttributes({a: 'a'}), false);
|
||||
equal(model.changedAttributes({a: 'b'}).a, 'b');
|
||||
});
|
||||
|
||||
test("change with options", 2, function() {
|
||||
var value;
|
||||
var model = new Backbone.Model({name: 'Rob'});
|
||||
model.on('change', function(model, options) {
|
||||
value = options.prefix + model.get('name');
|
||||
});
|
||||
model.set({name: 'Bob'}, {silent: true});
|
||||
model.change({prefix: 'Mr. '});
|
||||
equal(value, 'Mr. Bob');
|
||||
model.set({name: 'Sue'}, {prefix: 'Ms. '});
|
||||
equal(value, 'Ms. Sue');
|
||||
});
|
||||
|
||||
test("change after initialize", 1, function () {
|
||||
var changed = 0;
|
||||
var attrs = {id: 1, label: 'c'};
|
||||
var obj = new Backbone.Model(attrs);
|
||||
obj.on('change', function() { changed += 1; });
|
||||
obj.set(attrs);
|
||||
equal(changed, 0);
|
||||
});
|
||||
|
||||
test("save within change event", 1, function () {
|
||||
var env = this;
|
||||
var model = new Backbone.Model({firstName : "Taylor", lastName: "Swift"});
|
||||
model.url = '/test';
|
||||
model.on('change', function () {
|
||||
model.save();
|
||||
ok(_.isEqual(env.syncArgs.model, model));
|
||||
});
|
||||
model.set({lastName: 'Hicks'});
|
||||
});
|
||||
|
||||
test("validate after save", 1, function() {
|
||||
var lastError, model = new Backbone.Model();
|
||||
model.validate = function(attrs) {
|
||||
if (attrs.admin) return "Can't change admin status.";
|
||||
};
|
||||
model.sync = function(method, model, options) {
|
||||
options.success.call(this, {admin: true});
|
||||
};
|
||||
model.save(null, {error: function(model, error) {
|
||||
lastError = error;
|
||||
}});
|
||||
|
||||
equal(lastError, "Can't change admin status.");
|
||||
});
|
||||
|
||||
test("isValid", 5, function() {
|
||||
var model = new Backbone.Model({valid: true});
|
||||
model.validate = function(attrs) {
|
||||
if (!attrs.valid) return "invalid";
|
||||
};
|
||||
equal(model.isValid(), true);
|
||||
equal(model.set({valid: false}), false);
|
||||
equal(model.isValid(), true);
|
||||
ok(model.set('valid', false, {silent: true}));
|
||||
equal(model.isValid(), false);
|
||||
});
|
||||
|
||||
test("save", 2, function() {
|
||||
doc.save({title : "Henry V"});
|
||||
equal(this.syncArgs.method, 'update');
|
||||
ok(_.isEqual(this.syncArgs.model, doc));
|
||||
});
|
||||
|
||||
test("save in positional style", 1, function() {
|
||||
var model = new Backbone.Model();
|
||||
model.sync = function(method, model, options) {
|
||||
options.success();
|
||||
};
|
||||
model.save('title', 'Twelfth Night');
|
||||
equal(model.get('title'), 'Twelfth Night');
|
||||
});
|
||||
|
||||
|
||||
|
||||
test("fetch", 2, function() {
|
||||
doc.fetch();
|
||||
equal(this.syncArgs.method, 'read');
|
||||
ok(_.isEqual(this.syncArgs.model, doc));
|
||||
});
|
||||
|
||||
test("destroy", 3, function() {
|
||||
doc.destroy();
|
||||
equal(this.syncArgs.method, 'delete');
|
||||
ok(_.isEqual(this.syncArgs.model, doc));
|
||||
|
||||
var newModel = new Backbone.Model;
|
||||
equal(newModel.destroy(), false);
|
||||
});
|
||||
|
||||
test("non-persisted destroy", 1, function() {
|
||||
var a = new Backbone.Model({ 'foo': 1, 'bar': 2, 'baz': 3});
|
||||
a.sync = function() { throw "should not be called"; };
|
||||
a.destroy();
|
||||
ok(true, "non-persisted model should not call sync");
|
||||
});
|
||||
|
||||
test("validate", 7, function() {
|
||||
var lastError;
|
||||
var model = new Backbone.Model();
|
||||
model.validate = function(attrs) {
|
||||
if (attrs.admin != this.get('admin')) return "Can't change admin status.";
|
||||
};
|
||||
model.on('error', function(model, error) {
|
||||
lastError = error;
|
||||
});
|
||||
var result = model.set({a: 100});
|
||||
equal(result, model);
|
||||
equal(model.get('a'), 100);
|
||||
equal(lastError, undefined);
|
||||
result = model.set({admin: true}, {silent: true});
|
||||
equal(model.get('admin'), true);
|
||||
result = model.set({a: 200, admin: false});
|
||||
equal(lastError, "Can't change admin status.");
|
||||
equal(result, false);
|
||||
equal(model.get('a'), 100);
|
||||
});
|
||||
|
||||
test("validate on unset and clear", 6, function() {
|
||||
var error;
|
||||
var model = new Backbone.Model({name: "One"});
|
||||
model.validate = function(attrs) {
|
||||
if (!attrs.name) {
|
||||
error = true;
|
||||
return "No thanks.";
|
||||
}
|
||||
};
|
||||
model.set({name: "Two"});
|
||||
equal(model.get('name'), 'Two');
|
||||
equal(error, undefined);
|
||||
model.unset('name');
|
||||
equal(error, true);
|
||||
equal(model.get('name'), 'Two');
|
||||
model.clear();
|
||||
equal(model.get('name'), 'Two');
|
||||
delete model.validate;
|
||||
model.clear();
|
||||
equal(model.get('name'), undefined);
|
||||
});
|
||||
|
||||
test("validate with error callback", 8, function() {
|
||||
var lastError, boundError;
|
||||
var model = new Backbone.Model();
|
||||
model.validate = function(attrs) {
|
||||
if (attrs.admin) return "Can't change admin status.";
|
||||
};
|
||||
var callback = function(model, error) {
|
||||
lastError = error;
|
||||
};
|
||||
model.on('error', function(model, error) {
|
||||
boundError = true;
|
||||
});
|
||||
var result = model.set({a: 100}, {error: callback});
|
||||
equal(result, model);
|
||||
equal(model.get('a'), 100);
|
||||
equal(lastError, undefined);
|
||||
equal(boundError, undefined);
|
||||
result = model.set({a: 200, admin: true}, {error: callback});
|
||||
equal(result, false);
|
||||
equal(model.get('a'), 100);
|
||||
equal(lastError, "Can't change admin status.");
|
||||
equal(boundError, true);
|
||||
});
|
||||
|
||||
test("defaults always extend attrs (#459)", 2, function() {
|
||||
var Defaulted = Backbone.Model.extend({
|
||||
defaults: {one: 1},
|
||||
initialize : function(attrs, opts) {
|
||||
equal(this.attributes.one, 1);
|
||||
}
|
||||
});
|
||||
var providedattrs = new Defaulted({});
|
||||
var emptyattrs = new Defaulted();
|
||||
});
|
||||
|
||||
test("Inherit class properties", 6, function() {
|
||||
var Parent = Backbone.Model.extend({
|
||||
instancePropSame: function() {},
|
||||
instancePropDiff: function() {}
|
||||
}, {
|
||||
classProp: function() {}
|
||||
});
|
||||
var Child = Parent.extend({
|
||||
instancePropDiff: function() {}
|
||||
});
|
||||
|
||||
var adult = new Parent;
|
||||
var kid = new Child;
|
||||
|
||||
equal(Child.classProp, Parent.classProp);
|
||||
notEqual(Child.classProp, undefined);
|
||||
|
||||
equal(kid.instancePropSame, adult.instancePropSame);
|
||||
notEqual(kid.instancePropSame, undefined);
|
||||
|
||||
notEqual(Child.prototype.instancePropDiff, Parent.prototype.instancePropDiff);
|
||||
notEqual(Child.prototype.instancePropDiff, undefined);
|
||||
});
|
||||
|
||||
test("Nested change events don't clobber previous attributes", 4, function() {
|
||||
new Backbone.Model()
|
||||
.on('change:state', function(model, newState) {
|
||||
equal(model.previous('state'), undefined);
|
||||
equal(newState, 'hello');
|
||||
// Fire a nested change event.
|
||||
model.set({other: 'whatever'});
|
||||
})
|
||||
.on('change:state', function(model, newState) {
|
||||
equal(model.previous('state'), undefined);
|
||||
equal(newState, 'hello');
|
||||
})
|
||||
.set({state: 'hello'});
|
||||
});
|
||||
|
||||
test("hasChanged/set should use same comparison", 2, function() {
|
||||
var changed = 0, model = new Backbone.Model({a: null});
|
||||
model.on('change', function() {
|
||||
ok(this.hasChanged('a'));
|
||||
})
|
||||
.on('change:a', function() {
|
||||
changed++;
|
||||
})
|
||||
.set({a: undefined});
|
||||
equal(changed, 1);
|
||||
});
|
||||
|
||||
test("#582, #425, change:attribute callbacks should fire after all changes have occurred", 9, function() {
|
||||
var model = new Backbone.Model;
|
||||
|
||||
var assertion = function() {
|
||||
equal(model.get('a'), 'a');
|
||||
equal(model.get('b'), 'b');
|
||||
equal(model.get('c'), 'c');
|
||||
};
|
||||
|
||||
model.on('change:a', assertion);
|
||||
model.on('change:b', assertion);
|
||||
model.on('change:c', assertion);
|
||||
|
||||
model.set({a: 'a', b: 'b', c: 'c'});
|
||||
});
|
||||
|
||||
test("#871, set with attributes property", 1, function() {
|
||||
var model = new Backbone.Model();
|
||||
model.set({attributes: true});
|
||||
ok(model.has('attributes'));
|
||||
});
|
||||
|
||||
test("set value regardless of equality/change", 1, function() {
|
||||
var model = new Backbone.Model({x: []});
|
||||
var a = [];
|
||||
model.set({x: a});
|
||||
ok(model.get('x') === a);
|
||||
});
|
||||
|
||||
test("unset fires change for undefined attributes", 1, function() {
|
||||
var model = new Backbone.Model({x: undefined});
|
||||
model.on('change:x', function(){ ok(true); });
|
||||
model.unset('x');
|
||||
});
|
||||
|
||||
test("set: undefined values", 1, function() {
|
||||
var model = new Backbone.Model({x: undefined});
|
||||
ok('x' in model.attributes);
|
||||
});
|
||||
|
||||
test("change fires change:attr", 1, function() {
|
||||
var model = new Backbone.Model({x: 1});
|
||||
model.set({x: 2}, {silent: true});
|
||||
model.on('change:x', function(){ ok(true); });
|
||||
model.change();
|
||||
});
|
||||
|
||||
test("hasChanged is false after original values are set", 2, function() {
|
||||
var model = new Backbone.Model({x: 1});
|
||||
model.on('change:x', function(){ ok(false); });
|
||||
model.set({x: 2}, {silent: true});
|
||||
ok(model.hasChanged());
|
||||
model.set({x: 1}, {silent: true});
|
||||
ok(!model.hasChanged());
|
||||
});
|
||||
|
||||
test("save with `wait` succeeds without `validate`", 1, function() {
|
||||
var model = new Backbone.Model();
|
||||
model.url = '/test';
|
||||
model.save({x: 1}, {wait: true});
|
||||
ok(this.syncArgs.model === model);
|
||||
});
|
||||
|
||||
test("`hasChanged` for falsey keys", 2, function() {
|
||||
var model = new Backbone.Model();
|
||||
model.set({x: true}, {silent: true});
|
||||
ok(!model.hasChanged(0));
|
||||
ok(!model.hasChanged(''));
|
||||
});
|
||||
|
||||
test("`previous` for falsey keys", 2, function() {
|
||||
var model = new Backbone.Model({0: true, '': true});
|
||||
model.set({0: false, '': false}, {silent: true});
|
||||
equal(model.previous(0), true);
|
||||
equal(model.previous(''), true);
|
||||
});
|
||||
|
||||
test("`save` with `wait` sends correct attributes", 5, function() {
|
||||
var changed = 0;
|
||||
var model = new Backbone.Model({x: 1, y: 2});
|
||||
model.url = '/test';
|
||||
model.on('change:x', function() { changed++; });
|
||||
model.save({x: 3}, {wait: true});
|
||||
deepEqual(JSON.parse(this.ajaxSettings.data), {x: 3, y: 2});
|
||||
equal(model.get('x'), 1);
|
||||
equal(changed, 0);
|
||||
this.syncArgs.options.success({});
|
||||
equal(model.get('x'), 3);
|
||||
equal(changed, 1);
|
||||
});
|
||||
|
||||
test("a failed `save` with `wait` doesn't leave attributes behind", 1, function() {
|
||||
var model = new Backbone.Model;
|
||||
model.url = '/test';
|
||||
model.save({x: 1}, {wait: true});
|
||||
equal(model.get('x'), void 0);
|
||||
});
|
||||
|
||||
test("#1030 - `save` with `wait` results in correct attributes if success is called during sync", 2, function() {
|
||||
var model = new Backbone.Model({x: 1, y: 2});
|
||||
model.sync = function(method, model, options) {
|
||||
options.success();
|
||||
};
|
||||
model.on("change:x", function() { ok(true); });
|
||||
model.save({x: 3}, {wait: true});
|
||||
equal(model.get('x'), 3);
|
||||
});
|
||||
|
||||
test("save with wait validates attributes", 1, function() {
|
||||
var model = new Backbone.Model();
|
||||
model.url = '/test';
|
||||
model.validate = function() { ok(true); };
|
||||
model.save({x: 1}, {wait: true});
|
||||
});
|
||||
|
||||
test("nested `set` during `'change:attr'`", 2, function() {
|
||||
var events = [];
|
||||
var model = new Backbone.Model();
|
||||
model.on('all', function(event) { events.push(event); });
|
||||
model.on('change', function() {
|
||||
model.set({z: true}, {silent:true});
|
||||
});
|
||||
model.on('change:x', function() {
|
||||
model.set({y: true});
|
||||
});
|
||||
model.set({x: true});
|
||||
deepEqual(events, ['change:y', 'change:x', 'change']);
|
||||
events = [];
|
||||
model.change();
|
||||
deepEqual(events, ['change:z', 'change']);
|
||||
});
|
||||
|
||||
test("nested `change` only fires once", 1, function() {
|
||||
var model = new Backbone.Model();
|
||||
model.on('change', function() {
|
||||
ok(true);
|
||||
model.change();
|
||||
});
|
||||
model.set({x: true});
|
||||
});
|
||||
|
||||
test("no `'change'` event if no changes", 0, function() {
|
||||
var model = new Backbone.Model();
|
||||
model.on('change', function() { ok(false); });
|
||||
model.change();
|
||||
});
|
||||
|
||||
test("nested `set` during `'change'`", 6, function() {
|
||||
var count = 0;
|
||||
var model = new Backbone.Model();
|
||||
model.on('change', function() {
|
||||
switch(count++) {
|
||||
case 0:
|
||||
deepEqual(this.changedAttributes(), {x: true});
|
||||
equal(model.previous('x'), undefined);
|
||||
model.set({y: true});
|
||||
break;
|
||||
case 1:
|
||||
deepEqual(this.changedAttributes(), {y: true});
|
||||
equal(model.previous('x'), true);
|
||||
model.set({z: true});
|
||||
break;
|
||||
case 2:
|
||||
deepEqual(this.changedAttributes(), {z: true});
|
||||
equal(model.previous('y'), true);
|
||||
break;
|
||||
default:
|
||||
ok(false);
|
||||
}
|
||||
});
|
||||
model.set({x: true});
|
||||
});
|
||||
|
||||
test("nested `'change'` with silent", 3, function() {
|
||||
var count = 0;
|
||||
var model = new Backbone.Model();
|
||||
model.on('change:y', function() { ok(true); });
|
||||
model.on('change', function() {
|
||||
switch(count++) {
|
||||
case 0:
|
||||
deepEqual(this.changedAttributes(), {x: true});
|
||||
model.set({y: true}, {silent: true});
|
||||
break;
|
||||
case 1:
|
||||
deepEqual(this.changedAttributes(), {y: true, z: true});
|
||||
break;
|
||||
default:
|
||||
ok(false);
|
||||
}
|
||||
});
|
||||
model.set({x: true});
|
||||
model.set({z: true});
|
||||
});
|
||||
|
||||
test("nested `'change:attr'` with silent", 1, function() {
|
||||
var model = new Backbone.Model();
|
||||
model.on('change:y', function(){ ok(true); });
|
||||
model.on('change', function() {
|
||||
model.set({y: true}, {silent: true});
|
||||
model.set({z: true});
|
||||
});
|
||||
model.set({x: true});
|
||||
});
|
||||
|
||||
test("multiple nested changes with silent", 1, function() {
|
||||
var model = new Backbone.Model();
|
||||
model.on('change:x', function() {
|
||||
model.set({y: 1}, {silent: true});
|
||||
model.set({y: 2});
|
||||
});
|
||||
model.on('change:y', function(model, val) {
|
||||
equal(val, 2);
|
||||
});
|
||||
model.set({x: true});
|
||||
model.change();
|
||||
});
|
||||
|
||||
test("multiple nested changes with silent", 2, function() {
|
||||
var changes = [];
|
||||
var model = new Backbone.Model();
|
||||
model.on('change:b', function(model, val) { changes.push(val); });
|
||||
model.on('change', function() {
|
||||
model.set({b: 1});
|
||||
model.set({b: 2}, {silent: true});
|
||||
});
|
||||
model.set({b: 0});
|
||||
deepEqual(changes, [0, 1]);
|
||||
model.change();
|
||||
deepEqual(changes, [0, 1, 2, 1]);
|
||||
});
|
||||
|
||||
test("nested set multiple times", 1, function() {
|
||||
var model = new Backbone.Model();
|
||||
model.on('change:b', function() {
|
||||
ok(true);
|
||||
});
|
||||
model.on('change:a', function() {
|
||||
model.set({b: true});
|
||||
model.set({b: true});
|
||||
});
|
||||
model.set({a: true});
|
||||
});
|
||||
|
||||
test("#1179 - isValid returns true in the absence of validate.", 1, function() {
|
||||
var model = new Backbone.Model();
|
||||
model.validate = null;
|
||||
ok(model.isValid());
|
||||
});
|
||||
|
||||
test("#1122 - clear does not alter options.", 1, function() {
|
||||
var model = new Backbone.Model();
|
||||
var options = {};
|
||||
model.clear(options);
|
||||
ok(!options.unset);
|
||||
});
|
||||
|
||||
test("#1122 - unset does not alter options.", 1, function() {
|
||||
var model = new Backbone.Model();
|
||||
var options = {};
|
||||
model.unset('x', options);
|
||||
ok(!options.unset);
|
||||
});
|
||||
|
||||
test("#1355 - `options` is passed to success callbacks", 3, function() {
|
||||
var model = new Backbone.Model();
|
||||
var opts = {
|
||||
success: function( model, resp, options ) {
|
||||
ok(options);
|
||||
}
|
||||
};
|
||||
model.sync = function(method, model, options) {
|
||||
options.success();
|
||||
};
|
||||
model.save({id: 1}, opts);
|
||||
model.fetch(opts);
|
||||
model.destroy(opts);
|
||||
});
|
||||
|
||||
test("#1412 - Trigger 'sync' event.", 3, function() {
|
||||
var model = new Backbone.Model({id: 1});
|
||||
model.url = '/test';
|
||||
model.on('sync', function(){ ok(true); });
|
||||
Backbone.ajax = function(settings){ settings.success(); };
|
||||
model.fetch();
|
||||
model.save();
|
||||
model.destroy();
|
||||
});
|
||||
|
||||
test("#1365 - Destroy: New models execute success callback.", 2, function() {
|
||||
new Backbone.Model()
|
||||
.on('sync', function() { ok(false); })
|
||||
.on('destroy', function(){ ok(true); })
|
||||
.destroy({ success: function(){ ok(true); }});
|
||||
});
|
||||
|
||||
test("#1433 - Save: An invalid model cannot be persisted.", 1, function() {
|
||||
var model = new Backbone.Model;
|
||||
model.validate = function(){ return 'invalid'; };
|
||||
model.sync = function(){ ok(false); };
|
||||
strictEqual(model.save(), false);
|
||||
});
|
||||
|
||||
test("#1377 - Save without attrs triggers 'error'.", 1, function() {
|
||||
var Model = Backbone.Model.extend({
|
||||
url: '/test/',
|
||||
sync: function(method, model, options){ options.success(); },
|
||||
validate: function(){ return 'invalid'; }
|
||||
});
|
||||
var model = new Model({id: 1});
|
||||
model.on('error', function(){ ok(true); });
|
||||
model.save();
|
||||
});
|
||||
|
||||
test("#1545 - `undefined` can be passed to a model constructor without coersion", function() {
|
||||
var Model = Backbone.Model.extend({
|
||||
defaults: { one: 1 },
|
||||
initialize : function(attrs, opts) {
|
||||
equal(attrs, undefined);
|
||||
}
|
||||
});
|
||||
var emptyattrs = new Model();
|
||||
var undefinedattrs = new Model(undefined);
|
||||
});
|
||||
|
||||
asyncTest("#1478 - Model `save` does not trigger change on unchanged attributes", 0, function() {
|
||||
var Model = Backbone.Model.extend({
|
||||
sync: function(method, model, options) {
|
||||
setTimeout(function(){
|
||||
options.success();
|
||||
start();
|
||||
}, 0);
|
||||
}
|
||||
});
|
||||
new Model({x: true})
|
||||
.on('change:x', function(){ ok(false); })
|
||||
.save(null, {wait: true});
|
||||
});
|
||||
|
||||
test("#1664 - Changing from one value, silently to another, back to original does not trigger change.", 0, function() {
|
||||
var model = new Backbone.Model({x:1});
|
||||
model.on('change:x', function() { ok(false); });
|
||||
model.set({x:2},{silent:true});
|
||||
model.set({x:3},{silent:true});
|
||||
model.set({x:1});
|
||||
});
|
||||
|
||||
test("#1664 - multiple silent changes nested inside a change event", 2, function() {
|
||||
var changes = [];
|
||||
var model = new Backbone.Model();
|
||||
model.on('change', function() {
|
||||
model.set({a:'c'}, {silent:true});
|
||||
model.set({b:2}, {silent:true});
|
||||
model.unset('c', {silent:true});
|
||||
model.set({a:'a'}, {silent:true});
|
||||
model.set({b:1}, {silent:true});
|
||||
model.set({c:'item'}, {silent:true});
|
||||
});
|
||||
model.on('change:a change:b change:c', function(model, val) { changes.push(val); });
|
||||
model.set({a:'a', b:1, c:'item'});
|
||||
deepEqual(changes, ['a',1,'item']);
|
||||
model.change();
|
||||
deepEqual(changes, ['a',1,'item']);
|
||||
});
|
||||
|
||||
});
|
||||
12
vendor/backbone/test/noconflict.js
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
module("Backbone.noConflict");
|
||||
|
||||
test('noConflict', 2, function() {
|
||||
var noconflictBackbone = Backbone.noConflict();
|
||||
equal(window.Backbone, undefined, 'Returned window.Backbone');
|
||||
window.Backbone = noconflictBackbone;
|
||||
equal(window.Backbone, noconflictBackbone, 'Backbone is still pointing to the original Backbone');
|
||||
});
|
||||
|
||||
});
|
||||
484
vendor/backbone/test/router.js
vendored
Normal file
@@ -0,0 +1,484 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
var router = null;
|
||||
var location = null;
|
||||
var lastRoute = null;
|
||||
var lastArgs = [];
|
||||
|
||||
function onRoute(router, route, args) {
|
||||
lastRoute = route;
|
||||
lastArgs = args;
|
||||
}
|
||||
|
||||
var Location = function(href) {
|
||||
this.replace(href);
|
||||
};
|
||||
|
||||
_.extend(Location.prototype, {
|
||||
|
||||
replace: function(href) {
|
||||
_.extend(this, _.pick($('<a></a>', {href: href})[0],
|
||||
'href',
|
||||
'hash',
|
||||
'host',
|
||||
'search',
|
||||
'fragment',
|
||||
'pathname',
|
||||
'protocol'
|
||||
));
|
||||
// In IE, anchor.pathname does not contain a leading slash though
|
||||
// window.location.pathname does.
|
||||
if (!/^\//.test(this.pathname)) this.pathname = '/' + this.pathname;
|
||||
},
|
||||
|
||||
toString: function() {
|
||||
return this.href;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
module("Backbone.Router", {
|
||||
|
||||
setup: function() {
|
||||
location = new Location('http://example.com');
|
||||
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||
router = new Router({testing: 101});
|
||||
Backbone.history.interval = 9;
|
||||
Backbone.history.start({pushState: false});
|
||||
lastRoute = null;
|
||||
lastArgs = [];
|
||||
Backbone.history.on('route', onRoute);
|
||||
},
|
||||
|
||||
teardown: function() {
|
||||
Backbone.history.stop();
|
||||
Backbone.history.off('route', onRoute);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var Router = Backbone.Router.extend({
|
||||
|
||||
count: 0,
|
||||
|
||||
routes: {
|
||||
"noCallback": "noCallback",
|
||||
"counter": "counter",
|
||||
"search/:query": "search",
|
||||
"search/:query/p:page": "search",
|
||||
"contacts": "contacts",
|
||||
"contacts/new": "newContact",
|
||||
"contacts/:id": "loadContact",
|
||||
"optional(/:item)": "optionalItem",
|
||||
"splat/*args/end": "splat",
|
||||
"*first/complex-:part/*rest": "complex",
|
||||
":entity?*args": "query",
|
||||
"*anything": "anything"
|
||||
},
|
||||
|
||||
initialize : function(options) {
|
||||
this.testing = options.testing;
|
||||
this.route('implicit', 'implicit');
|
||||
},
|
||||
|
||||
counter: function() {
|
||||
this.count++;
|
||||
},
|
||||
|
||||
implicit: function() {
|
||||
this.count++;
|
||||
},
|
||||
|
||||
search : function(query, page) {
|
||||
this.query = query;
|
||||
this.page = page;
|
||||
},
|
||||
|
||||
contacts: function(){
|
||||
this.contact = 'index';
|
||||
},
|
||||
|
||||
newContact: function(){
|
||||
this.contact = 'new';
|
||||
},
|
||||
|
||||
loadContact: function(){
|
||||
this.contact = 'load';
|
||||
},
|
||||
|
||||
optionalItem: function(arg){
|
||||
this.arg = arg !== undefined ? arg : null;
|
||||
},
|
||||
|
||||
splat : function(args) {
|
||||
this.args = args;
|
||||
},
|
||||
|
||||
complex : function(first, part, rest) {
|
||||
this.first = first;
|
||||
this.part = part;
|
||||
this.rest = rest;
|
||||
},
|
||||
|
||||
query : function(entity, args) {
|
||||
this.entity = entity;
|
||||
this.queryArgs = args;
|
||||
},
|
||||
|
||||
anything : function(whatever) {
|
||||
this.anything = whatever;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
test("initialize", 1, function() {
|
||||
equal(router.testing, 101);
|
||||
});
|
||||
|
||||
test("routes (simple)", 4, function() {
|
||||
location.replace('http://example.com#search/news');
|
||||
Backbone.history.checkUrl();
|
||||
equal(router.query, 'news');
|
||||
equal(router.page, undefined);
|
||||
equal(lastRoute, 'search');
|
||||
equal(lastArgs[0], 'news');
|
||||
});
|
||||
|
||||
test("routes (two part)", 2, function() {
|
||||
location.replace('http://example.com#search/nyc/p10');
|
||||
Backbone.history.checkUrl();
|
||||
equal(router.query, 'nyc');
|
||||
equal(router.page, '10');
|
||||
});
|
||||
|
||||
test("routes via navigate", 2, function() {
|
||||
Backbone.history.navigate('search/manhattan/p20', {trigger: true});
|
||||
equal(router.query, 'manhattan');
|
||||
equal(router.page, '20');
|
||||
});
|
||||
|
||||
test("routes via navigate for backwards-compatibility", 2, function() {
|
||||
Backbone.history.navigate('search/manhattan/p20', true);
|
||||
equal(router.query, 'manhattan');
|
||||
equal(router.page, '20');
|
||||
});
|
||||
|
||||
test("route precedence via navigate", 6, function(){
|
||||
// check both 0.9.x and backwards-compatibility options
|
||||
_.each([ { trigger: true }, true ], function( options ){
|
||||
Backbone.history.navigate('contacts', options);
|
||||
equal(router.contact, 'index');
|
||||
Backbone.history.navigate('contacts/new', options);
|
||||
equal(router.contact, 'new');
|
||||
Backbone.history.navigate('contacts/foo', options);
|
||||
equal(router.contact, 'load');
|
||||
});
|
||||
});
|
||||
|
||||
test("loadUrl is not called for identical routes.", 0, function() {
|
||||
Backbone.history.loadUrl = function(){ ok(false); };
|
||||
location.replace('http://example.com#route');
|
||||
Backbone.history.navigate('route');
|
||||
Backbone.history.navigate('/route');
|
||||
Backbone.history.navigate('/route');
|
||||
});
|
||||
|
||||
test("use implicit callback if none provided", 1, function() {
|
||||
router.count = 0;
|
||||
router.navigate('implicit', {trigger: true});
|
||||
equal(router.count, 1);
|
||||
});
|
||||
|
||||
test("routes via navigate with {replace: true}", 1, function() {
|
||||
location.replace('http://example.com#start_here');
|
||||
Backbone.history.checkUrl();
|
||||
location.replace = function(href) {
|
||||
strictEqual(href, new Location('http://example.com#end_here').href);
|
||||
};
|
||||
Backbone.history.navigate('end_here', {replace: true});
|
||||
});
|
||||
|
||||
test("routes (splats)", 1, function() {
|
||||
location.replace('http://example.com#splat/long-list/of/splatted_99args/end');
|
||||
Backbone.history.checkUrl();
|
||||
equal(router.args, 'long-list/of/splatted_99args');
|
||||
});
|
||||
|
||||
test("routes (optional)", 2, function() {
|
||||
location.replace('http://example.com#optional');
|
||||
Backbone.history.checkUrl();
|
||||
equal(router.arg, null);
|
||||
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');
|
||||
Backbone.history.checkUrl();
|
||||
equal(router.first, 'one/two/three');
|
||||
equal(router.part, 'part');
|
||||
equal(router.rest, 'four/five/six/seven');
|
||||
});
|
||||
|
||||
test("routes (query)", 5, function() {
|
||||
location.replace('http://example.com#mandel?a=b&c=d');
|
||||
Backbone.history.checkUrl();
|
||||
equal(router.entity, 'mandel');
|
||||
equal(router.queryArgs, 'a=b&c=d');
|
||||
equal(lastRoute, 'query');
|
||||
equal(lastArgs[0], 'mandel');
|
||||
equal(lastArgs[1], 'a=b&c=d');
|
||||
});
|
||||
|
||||
test("routes (anything)", 1, function() {
|
||||
location.replace('http://example.com#doesnt-match-a-route');
|
||||
Backbone.history.checkUrl();
|
||||
equal(router.anything, 'doesnt-match-a-route');
|
||||
});
|
||||
|
||||
test("fires event when router doesn't have callback on it", 1, function() {
|
||||
router.on("route:noCallback", function(){ ok(true); });
|
||||
location.replace('http://example.com#noCallback');
|
||||
Backbone.history.checkUrl();
|
||||
});
|
||||
|
||||
test("#933, #908 - leading slash", 2, function() {
|
||||
location.replace('http://example.com/root/foo');
|
||||
|
||||
Backbone.history.stop();
|
||||
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||
Backbone.history.start({root: '/root', hashChange: false, silent: true});
|
||||
strictEqual(Backbone.history.getFragment(), 'foo');
|
||||
|
||||
Backbone.history.stop();
|
||||
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||
Backbone.history.start({root: '/root/', hashChange: false, silent: true});
|
||||
strictEqual(Backbone.history.getFragment(), 'foo');
|
||||
});
|
||||
|
||||
test("#1003 - History is started before navigate is called", 1, function() {
|
||||
Backbone.history.stop();
|
||||
Backbone.history.navigate = function(){ ok(Backbone.History.started); };
|
||||
Backbone.history.start();
|
||||
// If this is not an old IE navigate will not be called.
|
||||
if (!Backbone.history.iframe) ok(true);
|
||||
});
|
||||
|
||||
test("route callback gets passed decoded values", 3, function() {
|
||||
var route = 'has%2Fslash/complex-has%23hash/has%20space';
|
||||
Backbone.history.navigate(route, {trigger: true});
|
||||
equal(router.first, 'has/slash');
|
||||
equal(router.part, 'has#hash');
|
||||
equal(router.rest, 'has space');
|
||||
});
|
||||
|
||||
test("correctly handles URLs with % (#868)", 3, function() {
|
||||
location.replace('http://example.com#search/fat%3A1.5%25');
|
||||
Backbone.history.checkUrl();
|
||||
location.replace('http://example.com#search/fat');
|
||||
Backbone.history.checkUrl();
|
||||
equal(router.query, 'fat');
|
||||
equal(router.page, undefined);
|
||||
equal(lastRoute, 'search');
|
||||
});
|
||||
|
||||
test("#1185 - Use pathname when hashChange is not wanted.", 1, function() {
|
||||
Backbone.history.stop();
|
||||
location.replace('http://example.com/path/name#hash');
|
||||
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||
Backbone.history.start({hashChange: false});
|
||||
var fragment = Backbone.history.getFragment();
|
||||
strictEqual(fragment, location.pathname.replace(/^\//, ''));
|
||||
});
|
||||
|
||||
test("#1206 - Strip leading slash before location.assign.", 1, function() {
|
||||
Backbone.history.stop();
|
||||
location.replace('http://example.com/root/');
|
||||
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||
Backbone.history.start({hashChange: false, root: '/root/'});
|
||||
location.assign = function(pathname) {
|
||||
strictEqual(pathname, '/root/fragment');
|
||||
};
|
||||
Backbone.history.navigate('/fragment');
|
||||
});
|
||||
|
||||
test("#1387 - Root fragment without trailing slash.", 1, function() {
|
||||
Backbone.history.stop();
|
||||
location.replace('http://example.com/root');
|
||||
Backbone.history = _.extend(new Backbone.History, {location: location});
|
||||
Backbone.history.start({hashChange: false, root: '/root/', silent: true});
|
||||
strictEqual(Backbone.history.getFragment(), '');
|
||||
});
|
||||
|
||||
test("#1366 - History does not prepend root to fragment.", 2, 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/x');
|
||||
}
|
||||
}
|
||||
});
|
||||
Backbone.history.start({
|
||||
root: '/root/',
|
||||
pushState: true,
|
||||
hashChange: false
|
||||
});
|
||||
Backbone.history.navigate('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
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
160
vendor/backbone/test/sync.js
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
var Library = Backbone.Collection.extend({
|
||||
url : function() { return '/library'; }
|
||||
});
|
||||
var library;
|
||||
|
||||
var attrs = {
|
||||
title : "The Tempest",
|
||||
author : "Bill Shakespeare",
|
||||
length : 123
|
||||
};
|
||||
|
||||
module("Backbone.sync", _.extend(new Environment, {
|
||||
|
||||
setup : function() {
|
||||
Environment.prototype.setup.apply(this, arguments);
|
||||
library = new Library;
|
||||
library.create(attrs, {wait: false});
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
test("read", 4, function() {
|
||||
library.fetch();
|
||||
equal(this.ajaxSettings.url, '/library');
|
||||
equal(this.ajaxSettings.type, 'GET');
|
||||
equal(this.ajaxSettings.dataType, 'json');
|
||||
ok(_.isEmpty(this.ajaxSettings.data));
|
||||
});
|
||||
|
||||
test("passing data", 3, function() {
|
||||
library.fetch({data: {a: 'a', one: 1}});
|
||||
equal(this.ajaxSettings.url, '/library');
|
||||
equal(this.ajaxSettings.data.a, 'a');
|
||||
equal(this.ajaxSettings.data.one, 1);
|
||||
});
|
||||
|
||||
test("create", 6, function() {
|
||||
equal(this.ajaxSettings.url, '/library');
|
||||
equal(this.ajaxSettings.type, 'POST');
|
||||
equal(this.ajaxSettings.dataType, 'json');
|
||||
var data = JSON.parse(this.ajaxSettings.data);
|
||||
equal(data.title, 'The Tempest');
|
||||
equal(data.author, 'Bill Shakespeare');
|
||||
equal(data.length, 123);
|
||||
});
|
||||
|
||||
test("update", 7, function() {
|
||||
library.first().save({id: '1-the-tempest', author: 'William Shakespeare'});
|
||||
equal(this.ajaxSettings.url, '/library/1-the-tempest');
|
||||
equal(this.ajaxSettings.type, 'PUT');
|
||||
equal(this.ajaxSettings.dataType, 'json');
|
||||
var data = JSON.parse(this.ajaxSettings.data);
|
||||
equal(data.id, '1-the-tempest');
|
||||
equal(data.title, 'The Tempest');
|
||||
equal(data.author, 'William Shakespeare');
|
||||
equal(data.length, 123);
|
||||
});
|
||||
|
||||
test("update with emulateHTTP and emulateJSON", 7, function() {
|
||||
Backbone.emulateHTTP = Backbone.emulateJSON = true;
|
||||
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
||||
equal(this.ajaxSettings.url, '/library/2-the-tempest');
|
||||
equal(this.ajaxSettings.type, 'POST');
|
||||
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.author, 'Tim Shakespeare');
|
||||
equal(data.length, 123);
|
||||
Backbone.emulateHTTP = Backbone.emulateJSON = false;
|
||||
});
|
||||
|
||||
test("update with just emulateHTTP", 6, function() {
|
||||
Backbone.emulateHTTP = true;
|
||||
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
||||
equal(this.ajaxSettings.url, '/library/2-the-tempest');
|
||||
equal(this.ajaxSettings.type, 'POST');
|
||||
equal(this.ajaxSettings.contentType, 'application/json');
|
||||
var data = JSON.parse(this.ajaxSettings.data);
|
||||
equal(data.id, '2-the-tempest');
|
||||
equal(data.author, 'Tim Shakespeare');
|
||||
equal(data.length, 123);
|
||||
Backbone.emulateHTTP = false;
|
||||
});
|
||||
|
||||
test("update with just emulateJSON", 6, function() {
|
||||
Backbone.emulateJSON = true;
|
||||
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
||||
equal(this.ajaxSettings.url, '/library/2-the-tempest');
|
||||
equal(this.ajaxSettings.type, 'PUT');
|
||||
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.author, 'Tim Shakespeare');
|
||||
equal(data.length, 123);
|
||||
Backbone.emulateJSON = false;
|
||||
});
|
||||
|
||||
test("read model", 3, function() {
|
||||
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
||||
library.first().fetch();
|
||||
equal(this.ajaxSettings.url, '/library/2-the-tempest');
|
||||
equal(this.ajaxSettings.type, 'GET');
|
||||
ok(_.isEmpty(this.ajaxSettings.data));
|
||||
});
|
||||
|
||||
test("destroy", 3, function() {
|
||||
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
||||
library.first().destroy({wait: true});
|
||||
equal(this.ajaxSettings.url, '/library/2-the-tempest');
|
||||
equal(this.ajaxSettings.type, 'DELETE');
|
||||
equal(this.ajaxSettings.data, null);
|
||||
});
|
||||
|
||||
test("destroy with emulateHTTP", 3, function() {
|
||||
library.first().save({id: '2-the-tempest', author: 'Tim Shakespeare'});
|
||||
Backbone.emulateHTTP = Backbone.emulateJSON = true;
|
||||
library.first().destroy();
|
||||
equal(this.ajaxSettings.url, '/library/2-the-tempest');
|
||||
equal(this.ajaxSettings.type, 'POST');
|
||||
equal(JSON.stringify(this.ajaxSettings.data), '{"_method":"DELETE"}');
|
||||
Backbone.emulateHTTP = Backbone.emulateJSON = false;
|
||||
});
|
||||
|
||||
test("urlError", 2, function() {
|
||||
var model = new Backbone.Model();
|
||||
raises(function() {
|
||||
model.fetch();
|
||||
});
|
||||
model.fetch({url: '/one/two'});
|
||||
equal(this.ajaxSettings.url, '/one/two');
|
||||
});
|
||||
|
||||
test("#1052 - `options` is optional.", 0, function() {
|
||||
var model = new Backbone.Model();
|
||||
model.url = '/test';
|
||||
Backbone.sync('create', model);
|
||||
});
|
||||
|
||||
test("Backbone.ajax", 1, function() {
|
||||
Backbone.ajax = function(settings){
|
||||
strictEqual(settings.url, '/test');
|
||||
};
|
||||
var model = new Backbone.Model();
|
||||
model.url = '/test';
|
||||
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();
|
||||
});
|
||||
|
||||
});
|
||||
9266
vendor/backbone/test/vendor/jquery-1.7.1.js
vendored
Normal file
649
vendor/backbone/test/vendor/jslitmus.js
vendored
Normal file
@@ -0,0 +1,649 @@
|
||||
// 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
Normal file
@@ -0,0 +1,481 @@
|
||||
/*
|
||||
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');
|
||||
};
|
||||
}
|
||||
}());
|
||||
235
vendor/backbone/test/vendor/qunit.css
vendored
Executable file
@@ -0,0 +1,235 @@
|
||||
/**
|
||||
* QUnit v1.10.0 - A JavaScript Unit Testing Framework
|
||||
*
|
||||
* http://qunitjs.com
|
||||
*
|
||||
* Copyright 2012 jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*/
|
||||
|
||||
/** 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, #qunit-modulefilter {
|
||||
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: 5px 5px 0 0;
|
||||
-moz-border-radius: 5px 5px 0 0;
|
||||
-webkit-border-top-right-radius: 5px;
|
||||
-webkit-border-top-left-radius: 5px;
|
||||
}
|
||||
|
||||
#qunit-header a {
|
||||
text-decoration: none;
|
||||
color: #c2ccd1;
|
||||
}
|
||||
|
||||
#qunit-header a:hover,
|
||||
#qunit-header a:focus {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar label {
|
||||
display: inline-block;
|
||||
padding: 0 .5em 0 .1em;
|
||||
}
|
||||
|
||||
#qunit-banner {
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar {
|
||||
padding: 0.5em 0 0.5em 2em;
|
||||
color: #5E740B;
|
||||
background-color: #eee;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-container {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/** 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: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
}
|
||||
|
||||
#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 {
|
||||
padding: 5px;
|
||||
background-color: #fff;
|
||||
border-bottom: none;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
/*** Passing Styles */
|
||||
|
||||
#qunit-tests li li.pass {
|
||||
color: #3c510c;
|
||||
background-color: #fff;
|
||||
border-left: 10px 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: 10px solid #EE5757;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
#qunit-tests > li:last-child {
|
||||
border-radius: 0 0 5px 5px;
|
||||
-moz-border-radius: 0 0 5px 5px;
|
||||
-webkit-border-bottom-right-radius: 5px;
|
||||
-webkit-border-bottom-left-radius: 5px;
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
1977
vendor/backbone/test/vendor/qunit.js
vendored
Executable file
331
vendor/backbone/test/view.js
vendored
Normal file
@@ -0,0 +1,331 @@
|
||||
$(document).ready(function() {
|
||||
|
||||
var view;
|
||||
|
||||
module("Backbone.View", {
|
||||
|
||||
setup: function() {
|
||||
view = new Backbone.View({
|
||||
id : 'test-view',
|
||||
className : 'test-view'
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
test("constructor", 4, function() {
|
||||
equal(view.el.id, 'test-view');
|
||||
equal(view.el.className, 'test-view');
|
||||
equal(view.options.id, 'test-view');
|
||||
equal(view.options.className, 'test-view');
|
||||
});
|
||||
|
||||
test("jQuery", 1, function() {
|
||||
var view = new Backbone.View;
|
||||
view.setElement('<p><a><b>test</b></a></p>');
|
||||
strictEqual(view.$('a b').html(), 'test');
|
||||
});
|
||||
|
||||
test("make", 3, 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("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("initialize", 1, function() {
|
||||
var View = Backbone.View.extend({
|
||||
initialize: function() {
|
||||
this.one = 1;
|
||||
}
|
||||
});
|
||||
|
||||
strictEqual(new View().one, 1);
|
||||
});
|
||||
|
||||
test("delegateEvents", 6, function() {
|
||||
var counter1 = 0, counter2 = 0;
|
||||
|
||||
var view = new Backbone.View({el: '<p><a id="test"></a></p>'});
|
||||
view.increment = function(){ counter1++; };
|
||||
view.$el.on('click', function(){ counter2++; });
|
||||
|
||||
var events = {'click #test': 'increment'};
|
||||
|
||||
view.delegateEvents(events);
|
||||
view.$('#test').trigger('click');
|
||||
equal(counter1, 1);
|
||||
equal(counter2, 1);
|
||||
|
||||
view.$('#test').trigger('click');
|
||||
equal(counter1, 2);
|
||||
equal(counter2, 2);
|
||||
|
||||
view.delegateEvents(events);
|
||||
view.$('#test').trigger('click');
|
||||
equal(counter1, 3);
|
||||
equal(counter2, 3);
|
||||
});
|
||||
|
||||
test("delegateEvents allows functions for callbacks", 3, function() {
|
||||
var view = new Backbone.View({el: '<p></p>'});
|
||||
view.counter = 0;
|
||||
|
||||
var events = {
|
||||
click: function() {
|
||||
this.counter++;
|
||||
}
|
||||
};
|
||||
|
||||
view.delegateEvents(events);
|
||||
view.$el.trigger('click');
|
||||
equal(view.counter, 1);
|
||||
|
||||
view.$el.trigger('click');
|
||||
equal(view.counter, 2);
|
||||
|
||||
view.delegateEvents(events);
|
||||
view.$el.trigger('click');
|
||||
equal(view.counter, 3);
|
||||
});
|
||||
|
||||
test("undelegateEvents", 6, function() {
|
||||
var counter1 = 0, counter2 = 0;
|
||||
|
||||
var view = new Backbone.View({el: '<p><a id="test"></a></p>'});
|
||||
view.increment = function(){ counter1++; };
|
||||
view.$el.on('click', function(){ counter2++; });
|
||||
|
||||
var events = {'click #test': 'increment'};
|
||||
|
||||
view.delegateEvents(events);
|
||||
view.$('#test').trigger('click');
|
||||
equal(counter1, 1);
|
||||
equal(counter2, 1);
|
||||
|
||||
view.undelegateEvents();
|
||||
view.$('#test').trigger('click');
|
||||
equal(counter1, 1);
|
||||
equal(counter2, 2);
|
||||
|
||||
view.delegateEvents(events);
|
||||
view.$('#test').trigger('click');
|
||||
equal(counter1, 2);
|
||||
equal(counter2, 3);
|
||||
});
|
||||
|
||||
test("_ensureElement with DOM node el", 1, function() {
|
||||
var View = Backbone.View.extend({
|
||||
el: document.body
|
||||
});
|
||||
|
||||
equal(new View().el, document.body);
|
||||
});
|
||||
|
||||
test("_ensureElement with string el", 3, function() {
|
||||
var View = Backbone.View.extend({
|
||||
el: "body"
|
||||
});
|
||||
strictEqual(new View().el, document.body);
|
||||
|
||||
View = Backbone.View.extend({
|
||||
el: "#testElement > h1"
|
||||
});
|
||||
strictEqual(new View().el, $("#testElement > h1").get(0));
|
||||
|
||||
View = Backbone.View.extend({
|
||||
el: "#nonexistent"
|
||||
});
|
||||
ok(!new View().el);
|
||||
});
|
||||
|
||||
test("with className and id functions", 2, function() {
|
||||
var View = Backbone.View.extend({
|
||||
className: function() {
|
||||
return 'className';
|
||||
},
|
||||
id: function() {
|
||||
return 'id';
|
||||
}
|
||||
});
|
||||
|
||||
strictEqual(new View().el.className, 'className');
|
||||
strictEqual(new View().el.id, 'id');
|
||||
});
|
||||
|
||||
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() {
|
||||
return {'class': 'dynamic'};
|
||||
}
|
||||
});
|
||||
|
||||
strictEqual(new View().el.className, 'dynamic');
|
||||
});
|
||||
|
||||
test("multiple views per element", 3, function() {
|
||||
var count = 0;
|
||||
var $el = $('<p></p>');
|
||||
|
||||
var View = Backbone.View.extend({
|
||||
el: $el,
|
||||
events: {
|
||||
click: function() {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var view1 = new View;
|
||||
$el.trigger("click");
|
||||
equal(1, count);
|
||||
|
||||
var view2 = new View;
|
||||
$el.trigger("click");
|
||||
equal(3, count);
|
||||
|
||||
view1.delegateEvents();
|
||||
$el.trigger("click");
|
||||
equal(5, count);
|
||||
});
|
||||
|
||||
test("custom events, with namespaces", 2, function() {
|
||||
var count = 0;
|
||||
|
||||
var View = Backbone.View.extend({
|
||||
el: $('body'),
|
||||
events: function() {
|
||||
return {"fake$event.namespaced": "run"};
|
||||
},
|
||||
run: function() {
|
||||
count++;
|
||||
}
|
||||
});
|
||||
|
||||
var view = new View;
|
||||
$('body').trigger('fake$event').trigger('fake$event');
|
||||
equal(count, 2);
|
||||
|
||||
$('body').unbind('.namespaced');
|
||||
$('body').trigger('fake$event');
|
||||
equal(count, 2);
|
||||
});
|
||||
|
||||
test("#1048 - setElement uses provided object.", 2, function() {
|
||||
var $el = $('body');
|
||||
|
||||
var view = new Backbone.View({el: $el});
|
||||
ok(view.$el === $el);
|
||||
|
||||
view.setElement($el = $($el));
|
||||
ok(view.$el === $el);
|
||||
});
|
||||
|
||||
test("#986 - Undelegate before changing element.", 1, function() {
|
||||
var button1 = $('<button></button>');
|
||||
var button2 = $('<button></button>');
|
||||
|
||||
var View = Backbone.View.extend({
|
||||
events: {
|
||||
click: function(e) {
|
||||
ok(view.el === e.target);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var view = new View({el: button1});
|
||||
view.setElement(button2);
|
||||
|
||||
button1.trigger('click');
|
||||
button2.trigger('click');
|
||||
});
|
||||
|
||||
test("#1172 - Clone attributes object", 2, function() {
|
||||
var View = Backbone.View.extend({
|
||||
attributes: {foo: 'bar'}
|
||||
});
|
||||
|
||||
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() {
|
||||
var View = Backbone.View.extend({
|
||||
tagName: function() {
|
||||
return 'p';
|
||||
}
|
||||
});
|
||||
|
||||
ok(new View().$el.is('p'));
|
||||
});
|
||||
|
||||
test("dispose", 0, function() {
|
||||
var View = Backbone.View.extend({
|
||||
events: {
|
||||
click: function() { ok(false); }
|
||||
},
|
||||
initialize: function() {
|
||||
this.model.on('all x', function(){ ok(false); }, this);
|
||||
this.collection.on('all x', function(){ ok(false); }, this);
|
||||
}
|
||||
});
|
||||
|
||||
var view = new View({
|
||||
model: new Backbone.Model,
|
||||
collection: new Backbone.Collection
|
||||
});
|
||||
|
||||
view.dispose();
|
||||
view.model.trigger('x');
|
||||
view.collection.trigger('x');
|
||||
view.$el.click();
|
||||
});
|
||||
|
||||
test("dispose with non Backbone objects", 0, function() {
|
||||
var view = new Backbone.View({model: {}, collection: {}});
|
||||
view.dispose();
|
||||
});
|
||||
|
||||
test("view#remove calls dispose.", 1, function() {
|
||||
var view = new Backbone.View();
|
||||
|
||||
view.dispose = function() { ok(true); };
|
||||
view.remove();
|
||||
});
|
||||
|
||||
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)'));
|
||||
});
|
||||
|
||||
});
|
||||
1
vendor/benchmark.js
vendored
22
vendor/benchmark.js/LICENSE.txt
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
Copyright 2010-2012 Mathias Bynens <http://mathiasbynens.be/>
|
||||
Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
|
||||
Modified by John-David Dalton <http://allyoucanleet.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.
|
||||
136
vendor/benchmark.js/README.md
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
# 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/).
|
||||
|
||||
## Download
|
||||
|
||||
* [Development source](https://raw.github.com/bestiejs/benchmark.js/v1.0.0/benchmark.js)
|
||||
|
||||
## Dive in
|
||||
|
||||
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).
|
||||
|
||||
## 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
|
||||
|
||||
In a browser or Adobe AIR:
|
||||
|
||||
```html
|
||||
<script src="benchmark.js"></script>
|
||||
```
|
||||
|
||||
Optionally, expose Java’s nanosecond timer by adding the `nano` applet to the `<body>`:
|
||||
|
||||
```html
|
||||
<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):
|
||||
|
||||
--enable-benchmarking
|
||||
|
||||
Via [npm](http://npmjs.org/):
|
||||
|
||||
```bash
|
||||
npm install benchmark
|
||||
```
|
||||
|
||||
In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):
|
||||
|
||||
```js
|
||||
var Benchmark = require('benchmark');
|
||||
```
|
||||
|
||||
Optionally, use the [microtime module](https://github.com/wadey/node-microtime) by Wade Simmons:
|
||||
|
||||
```bash
|
||||
npm install microtime
|
||||
```
|
||||
|
||||
In [RingoJS v0.7.0-](http://ringojs.org/):
|
||||
|
||||
```js
|
||||
var Benchmark = require('benchmark').Benchmark;
|
||||
```
|
||||
|
||||
In [Rhino](http://www.mozilla.org/rhino/):
|
||||
|
||||
```js
|
||||
load('benchmark.js');
|
||||
```
|
||||
|
||||
In an AMD loader like [RequireJS](http://requirejs.org/):
|
||||
|
||||
```js
|
||||
require({
|
||||
'paths': {
|
||||
'benchmark': 'path/to/benchmark'
|
||||
}
|
||||
},
|
||||
['benchmark'], function(Benchmark) {
|
||||
console.log(Benchmark.version);
|
||||
});
|
||||
|
||||
// or with platform.js
|
||||
// https://github.com/bestiejs/platform.js
|
||||
require({
|
||||
'paths': {
|
||||
'benchmark': 'path/to/benchmark',
|
||||
'platform': 'path/to/platform'
|
||||
}
|
||||
},
|
||||
['benchmark', 'platform'], function(Benchmark, platform) {
|
||||
Benchmark.platform = platform;
|
||||
console.log(Benchmark.platform.name);
|
||||
});
|
||||
```
|
||||
|
||||
Usage example:
|
||||
|
||||
```js
|
||||
var suite = new Benchmark.Suite;
|
||||
|
||||
// add tests
|
||||
suite.add('RegExp#test', function() {
|
||||
/o/.test('Hello World!');
|
||||
})
|
||||
.add('String#indexOf', function() {
|
||||
'Hello World!'.indexOf('o') > -1;
|
||||
})
|
||||
// add listeners
|
||||
.on('cycle', function(event) {
|
||||
console.log(String(event.target));
|
||||
})
|
||||
.on('complete', function() {
|
||||
console.log('Fastest is ' + this.filter('fastest').pluck('name'));
|
||||
})
|
||||
// run async
|
||||
.run({ 'async': true });
|
||||
|
||||
// logs:
|
||||
// > RegExp#test x 4,161,532 +-0.99% (59 cycles)
|
||||
// > String#indexOf x 6,139,623 +-1.00% (131 cycles)
|
||||
// > Fastest is String#indexOf
|
||||
```
|
||||
|
||||
## BestieJS
|
||||
|
||||
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.
|
||||
|
||||
## Authors
|
||||
|
||||
* [Mathias Bynens](http://mathiasbynens.be/)
|
||||
[](https://twitter.com/mathias "Follow @mathias on Twitter")
|
||||
* [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")
|
||||
3919
vendor/benchmark.js/benchmark.js
vendored
Normal file
BIN
vendor/benchmark.js/nano.jar
vendored
Normal file
1
vendor/docdown
vendored
20
vendor/docdown/LICENSE.txt
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
Copyright 2011-2012 John-David Dalton <http://allyoucanleet.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.
|
||||
33
vendor/docdown/README.md
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
# Docdown <sup>v1.0.0</sup>
|
||||
|
||||
A simple JSDoc to Markdown documentation generator.
|
||||
|
||||
## Documentation
|
||||
|
||||
The documentation for Docdown can be viewed here: [/doc/README.md](https://github.com/jdalton/docdown/blob/master/doc/README.md#readme)
|
||||
|
||||
For a list of upcoming features, check out our [roadmap](https://github.com/jdalton/docdown/wiki/Roadmap).
|
||||
|
||||
## Installation and usage
|
||||
|
||||
Usage example:
|
||||
|
||||
```php
|
||||
require("docdown.php");
|
||||
|
||||
// generate Markdown
|
||||
$markdown = docdown(array(
|
||||
"path" => $filepath,
|
||||
"url" => "https://github.com/username/project/blob/master/my.js"
|
||||
));
|
||||
```
|
||||
|
||||
## Author
|
||||
|
||||
* [John-David Dalton](http://allyoucanleet.com/)
|
||||
[](https://twitter.com/jdalton "Follow @jdalton on Twitter")
|
||||
|
||||
## Contributors
|
||||
|
||||
* [Mathias Bynens](http://mathiasbynens.be/)
|
||||
[](https://twitter.com/mathias "Follow @mathias on Twitter")
|
||||
38
vendor/docdown/docdown.php
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/*!
|
||||
* Docdown v1.0.0-pre
|
||||
* Copyright 2011-2012 John-David Dalton <http://allyoucanleet.com/>
|
||||
* Available under MIT license <http://mths.be/mit>
|
||||
*/
|
||||
require(dirname(__FILE__) . '/src/DocDown/Generator.php');
|
||||
|
||||
/**
|
||||
* Generates Markdown from JSDoc entries in a given file.
|
||||
*
|
||||
* @param {Array} [$options=array()] The options array.
|
||||
* @returns {String} The generated Markdown.
|
||||
* @example
|
||||
*
|
||||
* // specify a file path
|
||||
* $markdown = docdown(array(
|
||||
* // path to js file
|
||||
* 'path' => $filepath,
|
||||
* // url used to reference line numbers in code
|
||||
* 'url' => 'https://github.com/username/project/blob/master/my.js'
|
||||
* ));
|
||||
*
|
||||
* // or pass raw js
|
||||
* $markdown = docdown(array(
|
||||
* // raw JavaScript source
|
||||
* 'source' => $rawJS,
|
||||
* // documentation title
|
||||
* 'title' => 'My API Documentation',
|
||||
* // url used to reference line numbers in code
|
||||
* 'url' => 'https://github.com/username/project/blob/master/my.js'
|
||||
* ));
|
||||
*/
|
||||
function docdown( $options = array() ) {
|
||||
$gen = new Generator($options);
|
||||
return $gen->generate();
|
||||
}
|
||||
?>
|
||||
215
vendor/docdown/src/DocDown/Alias.php
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
<?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->_lineNumber = $owner->getLineNumber();
|
||||
$this->_members = $owner->getMembers();
|
||||
$this->_params = $owner->getParams();
|
||||
$this->_returns = $owner->getReturns();
|
||||
$this->_type = $owner->getType();
|
||||
$this->_isCtor = $owner->isCtor();
|
||||
$this->_isPlugin = $owner->isPlugin();
|
||||
$this->_isPrivate = $owner->isPrivate();
|
||||
$this->_isStatic = $owner->isStatic();
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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* 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;
|
||||
}
|
||||
}
|
||||
?>
|
||||
426
vendor/docdown/src/DocDown/Entry.php
vendored
Normal file
@@ -0,0 +1,426 @@
|
||||
<?php
|
||||
|
||||
require(dirname(__FILE__) . "/Alias.php");
|
||||
|
||||
/**
|
||||
* A class to simplify parsing a single JSDoc entry.
|
||||
*/
|
||||
class Entry {
|
||||
|
||||
/**
|
||||
* The documentation entry.
|
||||
*
|
||||
* @memberOf Entry
|
||||
* @type String
|
||||
*/
|
||||
public $entry = '';
|
||||
|
||||
/**
|
||||
* The language highlighter used for code examples.
|
||||
*
|
||||
* @memberOf Entry
|
||||
* @type String
|
||||
*/
|
||||
public $lang = '';
|
||||
|
||||
/**
|
||||
* The source code.
|
||||
*
|
||||
* @memberOf Entry
|
||||
* @type String
|
||||
*/
|
||||
public $source = '';
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* The Entry constructor.
|
||||
*
|
||||
* @constructor
|
||||
* @param {String} $entry The documentation entry to analyse.
|
||||
* @param {String} $source The source code.
|
||||
* @param {String} [$lang ='js'] The language highlighter used for code examples.
|
||||
*/
|
||||
public function __construct( $entry, $source, $lang = 'js' ) {
|
||||
$this->entry = $entry;
|
||||
$this->lang = $lang;
|
||||
$this->source = str_replace(PHP_EOL, "\n", $source);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Extracts the documentation entries from source code.
|
||||
*
|
||||
* @static
|
||||
* @memberOf Entry
|
||||
* @param {String} $source The source code.
|
||||
* @returns {Array} The array of entries.
|
||||
*/
|
||||
public static function getEntries( $source ) {
|
||||
preg_match_all('#/\*\*(?![-!])[\s\S]*?\*/\s*[^\n]+#', $source, $result);
|
||||
return array_pop($result);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Checks if the entry is a function reference.
|
||||
*
|
||||
* @private
|
||||
* @memberOf Entry
|
||||
* @returns {Boolean} Returns `true` if the entry is a function reference, else `false`.
|
||||
*/
|
||||
private function isFunction() {
|
||||
if (!isset($this->_isFunction)) {
|
||||
$this->_isFunction = !!(
|
||||
$this->isCtor() ||
|
||||
count($this->getParams()) ||
|
||||
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.
|
||||
*
|
||||
* @memberOf Entry
|
||||
* @returns {String} The function call.
|
||||
*/
|
||||
public function getCall() {
|
||||
if (isset($this->_call)) {
|
||||
return $this->_call;
|
||||
}
|
||||
|
||||
preg_match('#\*/\s*(?:function ([^(]*)|(.*?)(?=[:=,]|return\b))#', $this->entry, $result);
|
||||
if ($result = array_pop($result)) {
|
||||
$result = array_pop(explode('var ', trim(trim(array_pop(explode('.', $result))), "'")));
|
||||
}
|
||||
// resolve name
|
||||
// avoid $this->getName() because it calls $this->getCall()
|
||||
preg_match('#\* *@name\s+([^\n]+)#', $this->entry, $name);
|
||||
if (count($name)) {
|
||||
$name = trim($name[1]);
|
||||
} else {
|
||||
$name = $result;
|
||||
}
|
||||
// compile function call syntax
|
||||
if ($this->isFunction()) {
|
||||
// compose parts
|
||||
$result = array($result);
|
||||
$params = $this->getParams();
|
||||
foreach ($params as $param) {
|
||||
$result[] = $param[1];
|
||||
}
|
||||
// format
|
||||
$result = $name .'('. implode(array_slice($result, 1), ', ') .')';
|
||||
$result = str_replace(', [', ' [, ', str_replace('], [', ', ', $result));
|
||||
}
|
||||
|
||||
$this->_call = $result ? $result : $name;
|
||||
return $this->_call;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the entry's `category` data.
|
||||
*
|
||||
* @memberOf Entry
|
||||
* @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() {
|
||||
if (isset($this->_desc)) {
|
||||
return $this->_desc;
|
||||
}
|
||||
|
||||
preg_match('#/\*\*(?:\s*\*)?([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result);
|
||||
if (count($result)) {
|
||||
$type = $this->getType();
|
||||
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', ' ', $result[1]));
|
||||
$result = ($type == 'Function' ? '' : '(' . str_replace('|', ', ', trim($type, '{}')) . '): ') . $result;
|
||||
}
|
||||
$this->_desc = $result;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the entry's `example` data.
|
||||
*
|
||||
* @memberOf Entry
|
||||
* @returns {String} The entry's `example` data.
|
||||
*/
|
||||
public function getExample() {
|
||||
if (isset($this->_example)) {
|
||||
return $this->_example;
|
||||
}
|
||||
|
||||
preg_match('#\* *@example\s+([\s\S]*?)(?=\*\s\@[a-z]|\*/)#', $this->entry, $result);
|
||||
if (count($result)) {
|
||||
$result = trim(preg_replace('/(?:^|\n)\s*\* ?/', "\n", $result[1]));
|
||||
$result = '```' . $this->lang . "\n" . $result . "\n```";
|
||||
}
|
||||
$this->_example = $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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the entry is an alias.
|
||||
*
|
||||
* @memberOf Entry
|
||||
* @returns {Boolean} Returns `false`.
|
||||
*/
|
||||
public function isAlias() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the entry is a constructor.
|
||||
*
|
||||
* @memberOf Entry
|
||||
* @returns {Boolean} Returns `true` if a constructor, else `false`.
|
||||
*/
|
||||
public function isCtor() {
|
||||
if (!isset($this->_isCtor)) {
|
||||
$this->_isCtor = !!preg_match('/\* *@constructor\b/', $this->entry);
|
||||
}
|
||||
return $this->_isCtor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
if (!isset($this->_isPlugin)) {
|
||||
$this->_isPlugin = !$this->isCtor() && !$this->isPrivate() && !$this->isStatic();
|
||||
}
|
||||
return $this->_isPlugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the entry is private.
|
||||
*
|
||||
* @memberOf Entry
|
||||
* @returns {Boolean} Returns `true` if private, else `false`.
|
||||
*/
|
||||
public function isPrivate() {
|
||||
if (!isset($this->_isPrivate)) {
|
||||
$this->_isPrivate = !!preg_match('/\* *@private\b/', $this->entry) || !preg_match('/\* *@[a-z]+\b/', $this->entry);
|
||||
}
|
||||
return $this->_isPrivate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the entry is *not* assigned to a prototype.
|
||||
*
|
||||
* @memberOf Entry
|
||||
* @returns {Boolean} Returns `true` if not assigned to a prototype, else `false`.
|
||||
*/
|
||||
public function isStatic() {
|
||||
if (isset($this->_isStatic)) {
|
||||
return $this->_isStatic;
|
||||
}
|
||||
|
||||
$public = !$this->isPrivate();
|
||||
$result = $public && !!preg_match('/\* *@static\b/', $this->entry);
|
||||
|
||||
// set in cases where it isn't explicitly stated
|
||||
if ($public && !$result) {
|
||||
if ($parent = array_pop(preg_split('/[#.]/', $this->getMembers(0)))) {
|
||||
foreach (Entry::getEntries($this->source) as $entry) {
|
||||
$entry = new Entry($entry, $this->source);
|
||||
if ($entry->getName() == $parent) {
|
||||
$result = !$entry->isCtor();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result = true;
|
||||
}
|
||||
}
|
||||
$this->_isStatic = $result;
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
?>
|
||||
565
vendor/docdown/src/DocDown/Generator.php
vendored
Normal file
@@ -0,0 +1,565 @@
|
||||
<?php
|
||||
|
||||
require(dirname(__FILE__) . "/Entry.php");
|
||||
|
||||
/**
|
||||
* Generates Markdown from JSDoc entries.
|
||||
*/
|
||||
class Generator {
|
||||
|
||||
/**
|
||||
* The HTML for the close tag.
|
||||
*
|
||||
* @static
|
||||
* @memberOf Generator
|
||||
* @type String
|
||||
*/
|
||||
public $closeTag = "\n<!-- /div -->\n";
|
||||
|
||||
/**
|
||||
* An array of JSDoc entries.
|
||||
*
|
||||
* @memberOf Generator
|
||||
* @type 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.
|
||||
*
|
||||
* @memberOf Generator
|
||||
* @type Array
|
||||
*/
|
||||
public $options = array();
|
||||
|
||||
/**
|
||||
* The file's source code.
|
||||
*
|
||||
* @memberOf Generator
|
||||
* @type String
|
||||
*/
|
||||
public $source = '';
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* The Generator constructor.
|
||||
*
|
||||
* @constructor
|
||||
* @param {String} $source The source code to parse.
|
||||
* @param {Array} $options The options array.
|
||||
*/
|
||||
public function __construct( $source, $options = array() ) {
|
||||
// juggle arguments
|
||||
if (is_array($source)) {
|
||||
$options = $source;
|
||||
} else {
|
||||
$options['source'] = $source;
|
||||
}
|
||||
if (isset($options['source']) && realpath($options['source'])) {
|
||||
$options['path'] = $options['source'];
|
||||
}
|
||||
if (isset($options['path'])) {
|
||||
preg_match('/(?<=\.)[a-z]+$/', $options['path'], $ext);
|
||||
$options['source'] = file_get_contents($options['path']);
|
||||
$ext = array_pop($ext);
|
||||
|
||||
if (!isset($options['lang']) && $ext) {
|
||||
$options['lang'] = $ext;
|
||||
}
|
||||
if (!isset($options['title'])) {
|
||||
$options['title'] = ucfirst(basename($options['path'])) . ' API documentation';
|
||||
}
|
||||
}
|
||||
if (!isset($options['lang'])) {
|
||||
$options['lang'] = 'js';
|
||||
}
|
||||
if (!isset($options['toc'])) {
|
||||
$options['toc'] = 'properties';
|
||||
}
|
||||
|
||||
$this->options = $options;
|
||||
$this->source = str_replace(PHP_EOL, "\n", $options['source']);
|
||||
$this->entries = Entry::getEntries($this->source);
|
||||
|
||||
foreach ($this->entries as $index => $value) {
|
||||
$this->entries[$index] = new Entry($value, $this->source, $options['lang']);
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Performs common string formatting operations.
|
||||
*
|
||||
* @private
|
||||
* @static
|
||||
* @memberOf Generator
|
||||
* @param {String} $string The string to format.
|
||||
* @returns {String} The formatted string.
|
||||
*/
|
||||
private static function format( $string ) {
|
||||
$counter = 0;
|
||||
|
||||
// tokenize inline code snippets
|
||||
preg_match_all('/`[^`]+`/', $string, $tokenized);
|
||||
$tokenized = $tokenized[0];
|
||||
foreach ($tokenized as $snippet) {
|
||||
$string = str_replace($snippet, '__token' . ($counter++) .'__', $string);
|
||||
}
|
||||
|
||||
// italicize parentheses
|
||||
$string = preg_replace('/(^|\s)(\([^)]+\))/', '$1*$2*', $string);
|
||||
|
||||
// mark numbers as inline code
|
||||
$string = preg_replace('/ (-?\d+(?:.\d+)?)(?!\.[^\n])/', ' `$1`', $string);
|
||||
|
||||
// detokenize inline code snippets
|
||||
$counter = 0;
|
||||
foreach ($tokenized as $snippet) {
|
||||
$string = str_replace('__token' . ($counter++) . '__', $snippet, $string);
|
||||
}
|
||||
|
||||
return trim($string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify a string by replacing named tokens with matching assoc. array values.
|
||||
*
|
||||
* @private
|
||||
* @static
|
||||
* @memberOf Generator
|
||||
* @param {String} $string The string to modify.
|
||||
* @param {Array|Object} $object The template object.
|
||||
* @returns {String} The modified string.
|
||||
*/
|
||||
private static function interpolate( $string, $object ) {
|
||||
preg_match_all('/#\{([^}]+)\}/', $string, $tokens);
|
||||
$tokens = array_unique(array_pop($tokens));
|
||||
|
||||
foreach ($tokens as $token) {
|
||||
$pattern = '/#\{' . $token . '\}/';
|
||||
$replacement = '';
|
||||
|
||||
if (is_object($object)) {
|
||||
preg_match('/\(([^)]+?)\)$/', $token, $args);
|
||||
$args = preg_split('/,\s*/', array_pop($args));
|
||||
$method = 'get' . ucfirst(str_replace('/\([^)]+?\)$/', '', $token));
|
||||
|
||||
if (method_exists($object, $method)) {
|
||||
$replacement = (string) call_user_func_array(array($object, $method), $args);
|
||||
} else if (isset($object->{$token})) {
|
||||
$replacement = (string) $object->{$token};
|
||||
}
|
||||
} else if (isset($object[$token])) {
|
||||
$replacement = (string) $object[$token];
|
||||
}
|
||||
$string = preg_replace($pattern, trim($replacement), $string);
|
||||
}
|
||||
return Generator::format($string);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @private
|
||||
* @memberOf Generator
|
||||
* @param {Number|Object} $entry The entry object.
|
||||
* @param {String} $member The name of the member.
|
||||
* @returns {String} The url hash.
|
||||
*/
|
||||
private function getHash( $entry, $member = '' ) {
|
||||
$entry = is_numeric($entry) ? $this->entries[$entry] : $entry;
|
||||
$member = !$member ? $entry->getMembers(0) : $member;
|
||||
$result = ($member ? $member . ($entry->isPlugin() ? 'prototype' : '') : '') . $entry->getCall();
|
||||
$result = preg_replace('/\(\[|\[\]/', '', $result);
|
||||
$result = preg_replace('/[ =|\'"{}.()\]]/', '', $result);
|
||||
$result = preg_replace('/[[#,]/', '-', $result);
|
||||
return strtolower($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the entry's url for the specific line number.
|
||||
*
|
||||
* @private
|
||||
* @memberOf Generator
|
||||
* @param {Number|Object} $entry The entry object.
|
||||
* @returns {String} The url.
|
||||
*/
|
||||
private function getLineUrl( $entry ) {
|
||||
$entry = is_numeric($entry) ? $this->entries($entry) : $entry;
|
||||
return $this->options['url'] . '#L' . $entry->getLineNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the character used to separate the entry's name from its member.
|
||||
*
|
||||
* @private
|
||||
* @memberOf Generator
|
||||
* @param {Number|Object} $entry The entry object.
|
||||
* @returns {String} The separator.
|
||||
*/
|
||||
private function getSeparator( $entry ) {
|
||||
$entry = is_numeric($entry) ? $this->entries($entry) : $entry;
|
||||
return $entry->isPlugin() ? '.prototype.' : '.';
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Generates Markdown from JSDoc entries.
|
||||
*
|
||||
* @memberOf Generator
|
||||
* @returns {String} The rendered Markdown.
|
||||
*/
|
||||
public function generate() {
|
||||
$api = array();
|
||||
$byCategory = $this->options['toc'] == 'categories';
|
||||
$categories = array();
|
||||
$closeTag = $this->closeTag;
|
||||
$compiling = false;
|
||||
$openTag = $this->openTag;
|
||||
$result = array('# ' . $this->options['title']);
|
||||
$toc = 'toc';
|
||||
|
||||
// initialize $api array
|
||||
foreach ($this->entries as $entry) {
|
||||
// skip invalid or private entries
|
||||
$name = $entry->getName();
|
||||
if (!$name || $entry->isPrivate()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$members = $entry->getMembers();
|
||||
$members = count($members) ? $members : array('');
|
||||
|
||||
foreach ($members as $member) {
|
||||
// create api category arrays
|
||||
if ($member && !isset($api[$member])) {
|
||||
// create temporary entry to be replaced later
|
||||
$api[$member] = new stdClass;
|
||||
$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();
|
||||
}
|
||||
}
|
||||
else if ($entry->isStatic()) {
|
||||
$api[$member]->static[] = $entry;
|
||||
foreach ($entry->getAliases() as $alias) {
|
||||
$api[$member]->static[] = $alias;
|
||||
}
|
||||
}
|
||||
else if (!$entry->isCtor()) {
|
||||
$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
|
||||
// TODO: see how well it handles deeper namespace traversal
|
||||
function sortCompare($a, $b) {
|
||||
$score = array( 'a' => 0, 'b' => 0);
|
||||
foreach (array( 'a' => $a, 'b' => $b) as $key => $value) {
|
||||
// capitalized properties are last
|
||||
if (preg_match('/[#.][A-Z]/', $value)) {
|
||||
$score[$key] = 0;
|
||||
}
|
||||
// lowercase prototype properties are next to last
|
||||
else if (preg_match('/#[a-z]/', $value)) {
|
||||
$score[$key] = 1;
|
||||
}
|
||||
// lowercase static properties next to first
|
||||
else if (preg_match('/\.[a-z]/', $value)) {
|
||||
$score[$key] = 2;
|
||||
}
|
||||
// root properties are first
|
||||
else if (preg_match('/^[^#.]+$/', $value)) {
|
||||
$score[$key] = 3;
|
||||
}
|
||||
}
|
||||
$score = $score['b'] - $score['a'];
|
||||
return $score ? $score : strcasecmp($a, $b);
|
||||
}
|
||||
|
||||
uksort($api, 'sortCompare');
|
||||
|
||||
// sort static and plugin sub-entries
|
||||
foreach ($api as $entry) {
|
||||
foreach (array('static', 'plugin') as $kind) {
|
||||
$sortBy = array( 'a' => array(), 'b' => array(), 'c' => array() );
|
||||
foreach ($entry->{$kind} as $subentry) {
|
||||
$name = $subentry->getName();
|
||||
// functions w/o ALL-CAPs names are last
|
||||
$sortBy['a'][] = $subentry->getType() == 'Function' && !preg_match('/^[A-Z_]+$/', $name);
|
||||
// ALL-CAPs properties first
|
||||
$sortBy['b'][] = preg_match('/^[A-Z_]+$/', $name);
|
||||
// lowercase alphanumeric sort
|
||||
$sortBy['c'][] = strtolower($name);
|
||||
}
|
||||
array_multisort($sortBy['a'], SORT_ASC, $sortBy['b'], SORT_DESC, $sortBy['c'], SORT_ASC, $entry->{$kind});
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
// 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
|
||||
$result[] = $openTag;
|
||||
|
||||
// compile TOC by categories
|
||||
if ($byCategory) {
|
||||
foreach ($categories as $category => $entries) {
|
||||
if ($compiling) {
|
||||
$result[] = $closeTag;
|
||||
} else {
|
||||
$compiling = true;
|
||||
}
|
||||
// assign TOC hash
|
||||
if (count($result) == 2) {
|
||||
$toc = $category;
|
||||
}
|
||||
// add category
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
array_push($result, $closeTag, $closeTag);
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
// compile content
|
||||
$compiling = false;
|
||||
$result[] = $openTag;
|
||||
|
||||
if ($byCategory) {
|
||||
foreach ($categories as $category => $entries) {
|
||||
if ($compiling) {
|
||||
$result[] = $closeTag;
|
||||
} else {
|
||||
$compiling = true;
|
||||
}
|
||||
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 . '`');
|
||||
|
||||
foreach (array($entry, 'static', 'plugin') as $kind) {
|
||||
$subentries = is_string($kind) ? $entry->{$kind} : array($kind);
|
||||
|
||||
// add sub-entry name
|
||||
if ($kind != 'static' && $entry->getType() != 'Object' &&
|
||||
count($subentries) && $subentries[0] != $kind) {
|
||||
if ($kind == 'plugin') {
|
||||
$result[] = $closeTag;
|
||||
}
|
||||
array_push(
|
||||
$result,
|
||||
$openTag,
|
||||
'## `' . $member . ($kind == 'plugin' ? '.prototype`' : '`')
|
||||
);
|
||||
}
|
||||
$this->addEntries($result, $subentries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// close tags add TOC link reference
|
||||
array_push($result, $closeTag, $closeTag, '', ' [1]: #' . $toc . ' "Jump back to the TOC."');
|
||||
|
||||
// cleanup whitespace
|
||||
return trim(preg_replace('/ +\n/', "\n", join($result, "\n")));
|
||||
}
|
||||
}
|
||||
?>
|
||||
1049
vendor/firebug-lite/changelog.txt
vendored
Normal file
30
vendor/firebug-lite/license.txt
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2007, Parakey Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use of this software in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the
|
||||
following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
* Neither the name of Parakey Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior
|
||||
written permission of Parakey Inc.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
BIN
vendor/firebug-lite/skin/xp/blank.gif
vendored
Normal file
|
After Width: | Height: | Size: 43 B |
BIN
vendor/firebug-lite/skin/xp/buttonBg.png
vendored
Normal file
|
After Width: | Height: | Size: 167 B |
BIN
vendor/firebug-lite/skin/xp/buttonBgHover.png
vendored
Normal file
|
After Width: | Height: | Size: 171 B |
331
vendor/firebug-lite/skin/xp/debugger.css
vendored
Normal file
@@ -0,0 +1,331 @@
|
||||
/* See license.txt for terms of usage */
|
||||
|
||||
.panelNode-script {
|
||||
overflow: hidden;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
|
||||
.scriptTooltip {
|
||||
position: fixed;
|
||||
z-index: 2147483647;
|
||||
padding: 2px 3px;
|
||||
border: 1px solid #CBE087;
|
||||
background: LightYellow;
|
||||
font-family: monospace;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
|
||||
.sourceBox {
|
||||
/* TODO: xxxpedro problem with sourceBox and scrolling elements */
|
||||
/*overflow: scroll; /* see issue 1479 */
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.sourceRow {
|
||||
white-space: nowrap;
|
||||
-moz-user-select: text;
|
||||
}
|
||||
|
||||
.sourceRow.hovered {
|
||||
background-color: #EEEEEE;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
|
||||
.sourceLine {
|
||||
-moz-user-select: none;
|
||||
margin-right: 10px;
|
||||
border-right: 1px solid #CCCCCC;
|
||||
padding: 0px 4px 0 20px;
|
||||
background: #EEEEEE no-repeat 2px 0px;
|
||||
color: #888888;
|
||||
white-space: pre;
|
||||
font-family: monospace; /* see issue 2953 */
|
||||
}
|
||||
|
||||
.noteInToolTip { /* below sourceLine, so it overrides it */
|
||||
background-color: #FFD472;
|
||||
}
|
||||
|
||||
.useA11y .sourceBox .sourceViewport:focus .sourceLine {
|
||||
background-color: #FFFFC0;
|
||||
color: navy;
|
||||
border-right: 1px solid black;
|
||||
}
|
||||
|
||||
.useA11y .sourceBox .sourceViewport:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.a11y1emSize {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.useA11y .panelStatusLabel:focus {
|
||||
outline-offset: -2px !important;
|
||||
}
|
||||
|
||||
.sourceBox > .sourceRow > .sourceLine {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sourceLine:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.sourceRowText {
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.sourceRow[exe_line="true"] {
|
||||
outline: 1px solid #D9D9B6;
|
||||
margin-right: 1px;
|
||||
background-color: lightgoldenrodyellow;
|
||||
}
|
||||
|
||||
.sourceRow[executable="true"] > .sourceLine {
|
||||
content: "-";
|
||||
color: #4AA02C; /* Spring Green */
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sourceRow[exe_line="true"] > .sourceLine {
|
||||
background-image: url(chrome://firebug/skin/exe.png);
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.sourceRow[breakpoint="true"] > .sourceLine {
|
||||
background-image: url(chrome://firebug/skin/breakpoint.png);
|
||||
}
|
||||
|
||||
.sourceRow[breakpoint="true"][condition="true"] > .sourceLine {
|
||||
background-image: url(chrome://firebug/skin/breakpointCondition.png);
|
||||
}
|
||||
|
||||
.sourceRow[breakpoint="true"][disabledBreakpoint="true"] > .sourceLine {
|
||||
background-image: url(chrome://firebug/skin/breakpointDisabled.png);
|
||||
}
|
||||
|
||||
.sourceRow[breakpoint="true"][exe_line="true"] > .sourceLine {
|
||||
background-image: url(chrome://firebug/skin/breakpointExe.png);
|
||||
}
|
||||
|
||||
.sourceRow[breakpoint="true"][exe_line="true"][disabledBreakpoint="true"] > .sourceLine {
|
||||
background-image: url(chrome://firebug/skin/breakpointDisabledExe.png);
|
||||
}
|
||||
|
||||
.sourceLine.editing {
|
||||
background-image: url(chrome://firebug/skin/breakpoint.png);
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
|
||||
.conditionEditor {
|
||||
z-index: 2147483647;
|
||||
position: absolute;
|
||||
margin-top: 0;
|
||||
left: 2px;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
.conditionEditorInner {
|
||||
position: relative;
|
||||
top: -26px;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.conditionCaption {
|
||||
margin-bottom: 2px;
|
||||
font-family: Lucida Grande, sans-serif;
|
||||
font-weight: bold;
|
||||
font-size: 11px;
|
||||
color: #226679;
|
||||
}
|
||||
|
||||
.conditionInput {
|
||||
width: 100%;
|
||||
border: 1px solid #0096C0;
|
||||
font-family: monospace;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.conditionEditorInner1 {
|
||||
padding-left: 37px;
|
||||
background: url(condBorders.png) repeat-y;
|
||||
}
|
||||
|
||||
.conditionEditorInner2 {
|
||||
padding-right: 25px;
|
||||
background: url(condBorders.png) repeat-y 100% 0;
|
||||
}
|
||||
|
||||
.conditionEditorTop1 {
|
||||
background: url(condCorners.png) no-repeat 100% 0;
|
||||
margin-left: 37px;
|
||||
height: 35px;
|
||||
}
|
||||
|
||||
.conditionEditorTop2 {
|
||||
position: relative;
|
||||
left: -37px;
|
||||
width: 37px;
|
||||
height: 35px;
|
||||
background: url(condCorners.png) no-repeat;
|
||||
}
|
||||
|
||||
.conditionEditorBottom1 {
|
||||
background: url(condCorners.png) no-repeat 100% 100%;
|
||||
margin-left: 37px;
|
||||
height: 33px;
|
||||
}
|
||||
|
||||
.conditionEditorBottom2 {
|
||||
position: relative; left: -37px;
|
||||
width: 37px;
|
||||
height: 33px;
|
||||
background: url(condCorners.png) no-repeat 0 100%;
|
||||
}
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
.upsideDown {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.upsideDown .conditionEditorInner {
|
||||
top: -8px;
|
||||
}
|
||||
|
||||
.upsideDown .conditionEditorInner1 {
|
||||
padding-left: 33px;
|
||||
background: url(condBordersUps.png) repeat-y;
|
||||
}
|
||||
|
||||
.upsideDown .conditionEditorInner2 {
|
||||
padding-right: 25px;
|
||||
background: url(condBordersUps.png) repeat-y 100% 0;
|
||||
}
|
||||
|
||||
.upsideDown .conditionEditorTop1 {
|
||||
background: url(condCornersUps.png) no-repeat 100% 0;
|
||||
margin-left: 33px;
|
||||
height: 25px;
|
||||
}
|
||||
|
||||
.upsideDown .conditionEditorTop2 {
|
||||
position: relative;
|
||||
left: -33px;
|
||||
width: 33px;
|
||||
height: 25px;
|
||||
background: url(condCornersUps.png) no-repeat;
|
||||
}
|
||||
|
||||
.upsideDown .conditionEditorBottom1 {
|
||||
background: url(condCornersUps.png) no-repeat 100% 100%;
|
||||
margin-left: 33px;
|
||||
height: 43px;
|
||||
}
|
||||
|
||||
.upsideDown .conditionEditorBottom2 {
|
||||
position: relative;
|
||||
left: -33px;
|
||||
width: 33px;
|
||||
height: 43px;
|
||||
background: url(condCornersUps.png) no-repeat 0 100%;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
|
||||
.breakpointsGroupListBox {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.breakpointBlockHead {
|
||||
position: relative;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.breakpointBlockHead > .checkbox {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.breakpointBlockHead > .objectLink-sourceLink {
|
||||
top: 4px;
|
||||
right: 20px;
|
||||
background-color: #FFFFFF; /* issue 3308 */
|
||||
}
|
||||
|
||||
.breakpointBlockHead > .closeButton {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
}
|
||||
|
||||
.breakpointCheckbox {
|
||||
margin-top: 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.breakpointName {
|
||||
margin-left: 4px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.breakpointRow[aria-checked="false"] > .breakpointBlockHead > *,
|
||||
.breakpointRow[aria-checked="false"] > .breakpointCode {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.breakpointRow[aria-checked="false"] .breakpointCheckbox,
|
||||
.breakpointRow[aria-checked="false"] .objectLink-sourceLink,
|
||||
.breakpointRow[aria-checked="false"] .closeButton,
|
||||
.breakpointRow[aria-checked="false"] .breakpointMutationType {
|
||||
opacity: 1.0 !important;
|
||||
}
|
||||
|
||||
.breakpointCode {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
padding-left: 24px;
|
||||
padding-bottom: 2px;
|
||||
border-bottom: 1px solid #D7D7D7;
|
||||
font-family: monospace;
|
||||
color: DarkGreen;
|
||||
}
|
||||
|
||||
.breakpointCondition {
|
||||
white-space: nowrap;
|
||||
padding-left: 24px;
|
||||
padding-bottom: 2px;
|
||||
border-bottom: 1px solid #D7D7D7;
|
||||
font-family: monospace;
|
||||
color: Gray;
|
||||
}
|
||||
|
||||
.breakpointBlock-breakpoints > .groupHeader {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.breakpointBlock-monitors > .breakpointCode {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.breakpointBlock-errorBreakpoints .breakpointCheckbox,
|
||||
.breakpointBlock-monitors .breakpointCheckbox {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.breakpointHeader {
|
||||
margin: 0 !important;
|
||||
border-top: none !important;
|
||||
}
|
||||
BIN
vendor/firebug-lite/skin/xp/detach.png
vendored
Normal file
|
After Width: | Height: | Size: 655 B |
BIN
vendor/firebug-lite/skin/xp/detachHover.png
vendored
Normal file
|
After Width: | Height: | Size: 586 B |
BIN
vendor/firebug-lite/skin/xp/disable.gif
vendored
Normal file
|
After Width: | Height: | Size: 340 B |
BIN
vendor/firebug-lite/skin/xp/disable.png
vendored
Normal file
|
After Width: | Height: | Size: 543 B |
BIN
vendor/firebug-lite/skin/xp/disableHover.gif
vendored
Normal file
|
After Width: | Height: | Size: 344 B |
BIN
vendor/firebug-lite/skin/xp/disableHover.png
vendored
Normal file
|
After Width: | Height: | Size: 512 B |
BIN
vendor/firebug-lite/skin/xp/down.png
vendored
Normal file
|
After Width: | Height: | Size: 637 B |
BIN
vendor/firebug-lite/skin/xp/downActive.png
vendored
Normal file
|
After Width: | Height: | Size: 543 B |
BIN
vendor/firebug-lite/skin/xp/downHover.png
vendored
Normal file
|
After Width: | Height: | Size: 526 B |
BIN
vendor/firebug-lite/skin/xp/errorIcon-sm.png
vendored
Normal file
|
After Width: | Height: | Size: 447 B |
BIN
vendor/firebug-lite/skin/xp/errorIcon.gif
vendored
Normal file
|
After Width: | Height: | Size: 365 B |
BIN
vendor/firebug-lite/skin/xp/errorIcon.png
vendored
Normal file
|
After Width: | Height: | Size: 457 B |
817
vendor/firebug-lite/skin/xp/firebug-1.3a2.css
vendored
Normal file
@@ -0,0 +1,817 @@
|
||||
.fbBtnPressed {
|
||||
background: #ECEBE3;
|
||||
padding: 3px 6px 2px 7px !important;
|
||||
margin: 1px 0 0 1px;
|
||||
_margin: 1px -1px 0 1px;
|
||||
border: 1px solid #ACA899 !important;
|
||||
border-color: #ACA899 #ECEBE3 #ECEBE3 #ACA899 !important;
|
||||
}
|
||||
|
||||
.fbToolbarButtons {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#fbStatusBarBox {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/************************************************************************************************
|
||||
Error Popup
|
||||
*************************************************************************************************/
|
||||
#fbErrorPopup {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 19px;
|
||||
width: 75px;
|
||||
background: url(sprite.png) #f1f2ee 0 0;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
#fbErrorPopupContent {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 1px;
|
||||
height: 18px;
|
||||
width: 75px;
|
||||
_width: 74px;
|
||||
border-left: 1px solid #aca899;
|
||||
}
|
||||
|
||||
#fbErrorIndicator {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.fbBtnInspectActive {
|
||||
background: #aaa;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
/************************************************************************************************
|
||||
General
|
||||
*************************************************************************************************/
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Lucida Grande, Tahoma, sans-serif;
|
||||
font-size: 11px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/************************************************************************************************
|
||||
Mini Chrome
|
||||
*************************************************************************************************/
|
||||
#fbMiniChrome {
|
||||
display: none;
|
||||
right: 0;
|
||||
height: 27px;
|
||||
background: url(sprite.png) #f1f2ee 0 0;
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
#fbMiniContent {
|
||||
display: block;
|
||||
position: relative;
|
||||
left: -1px;
|
||||
right: 0;
|
||||
top: 1px;
|
||||
height: 25px;
|
||||
border-left: 1px solid #aca899;
|
||||
}
|
||||
|
||||
#fbToolbarSearch {
|
||||
float: right;
|
||||
border: 1px solid #ccc;
|
||||
margin: 0 5px 0 0;
|
||||
background: #fff url(search.png) no-repeat 4px 2px;
|
||||
padding-left: 20px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
#fbToolbarErrors {
|
||||
float: right;
|
||||
margin: 1px 4px 0 0;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
#fbLeftToolbarErrors {
|
||||
float: left;
|
||||
margin: 7px 0px 0 5px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.fbErrors {
|
||||
padding-left: 20px;
|
||||
height: 14px;
|
||||
background: url(errorIcon.png) no-repeat;
|
||||
color: #f00;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#fbMiniErrors {
|
||||
display: inline;
|
||||
display: none;
|
||||
float: right;
|
||||
margin: 5px 2px 0 5px;
|
||||
}
|
||||
|
||||
#fbMiniIcon {
|
||||
float: right;
|
||||
margin: 3px 4px 0;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
float: right;
|
||||
background: url(sprite.png) 0 -135px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************************************
|
||||
Master Layout
|
||||
*************************************************************************************************/
|
||||
#fbChrome {
|
||||
position: fixed;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
#fbTop {
|
||||
height: 49px;
|
||||
}
|
||||
|
||||
#fbToolbar {
|
||||
position: absolute;
|
||||
z-index: 5;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
background: url(sprite.png) #f1f2ee 0 0;
|
||||
height: 27px;
|
||||
font-size: 11px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#fbPanelBarBox {
|
||||
top: 27px;
|
||||
position: absolute;
|
||||
z-index: 8;
|
||||
width: 100%;
|
||||
background: url(sprite.png) #dbd9c9 0 -27px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
#fbContent {
|
||||
height: 100%;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#fbBottom {
|
||||
height: 18px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
/************************************************************************************************
|
||||
Sub-Layout
|
||||
*************************************************************************************************/
|
||||
|
||||
/* fbToolbar
|
||||
*************************************************************************************************/
|
||||
#fbToolbarIcon {
|
||||
float: left;
|
||||
padding: 4px 5px 0;
|
||||
}
|
||||
|
||||
#fbToolbarIcon a {
|
||||
display: block;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
background: url(sprite.png) 0 -135px;
|
||||
text-decoration: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#fbToolbarButtons {
|
||||
float: left;
|
||||
padding: 4px 2px 0 5px;
|
||||
}
|
||||
|
||||
#fbToolbarButtons a {
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
float: left;
|
||||
color: #000;
|
||||
padding: 4px 8px 4px;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#fbToolbarButtons a:hover {
|
||||
color: #333;
|
||||
padding: 3px 7px 3px;
|
||||
border: 1px solid #fff;
|
||||
border-bottom: 1px solid #bbb;
|
||||
border-right: 1px solid #bbb;
|
||||
}
|
||||
|
||||
#fbStatusBarBox {
|
||||
position: relative;
|
||||
top: 5px;
|
||||
line-height: 19px;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.fbToolbarSeparator{
|
||||
overflow: hidden;
|
||||
border: 1px solid;
|
||||
border-color: transparent #fff transparent #777;
|
||||
_border-color: #eee #fff #eee #777;
|
||||
height: 7px;
|
||||
margin: 10px 6px 0 0;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.fbStatusBar span {
|
||||
color: #808080;
|
||||
padding: 0 4px 0 0;
|
||||
}
|
||||
|
||||
.fbStatusBar span a {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.fbStatusBar span a:hover {
|
||||
color: blue;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
#fbWindowButtons {
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 17px;
|
||||
_width: 50px;
|
||||
padding: 5px 0 5px 5px;
|
||||
z-index: 6;
|
||||
background: url(sprite.png) #f1f2ee 0 0;
|
||||
}
|
||||
|
||||
/* fbPanelBarBox
|
||||
*************************************************************************************************/
|
||||
|
||||
#fbPanelBar1 {
|
||||
width: 255px; /* fixed width to avoid tabs breaking line */
|
||||
z-index: 8;
|
||||
left: 0;
|
||||
white-space: nowrap;
|
||||
background: url(sprite.png) #dbd9c9 0 -27px;
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
}
|
||||
|
||||
#fbPanelBar2Box {
|
||||
background: url(sprite.png) #dbd9c9 0 -27px;
|
||||
position: absolute;
|
||||
height: 22px;
|
||||
width: 300px; /* fixed width to avoid tabs breaking line */
|
||||
z-index: 9;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#fbPanelBar2 {
|
||||
position: absolute;
|
||||
width: 290px; /* fixed width to avoid tabs breaking line */
|
||||
height: 22px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
/* body
|
||||
*************************************************************************************************/
|
||||
.fbPanel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#fbPanelBox1, #fbPanelBox2 {
|
||||
max-height: inherit;
|
||||
height: 100%;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
#fbPanelBox2 {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
#fbPanelBox2 {
|
||||
width: 300px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
#fbPanel2 {
|
||||
padding-left: 6px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.hide {
|
||||
overflow: hidden !important;
|
||||
position: fixed !important;
|
||||
display: none !important;
|
||||
visibility: hidden !important;
|
||||
}
|
||||
|
||||
/* fbBottom
|
||||
*************************************************************************************************/
|
||||
|
||||
#fbCommand {
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
#fbCommandBox {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 18px;
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
z-index: 9;
|
||||
background: #fff;
|
||||
border: 0;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
|
||||
#fbCommandIcon {
|
||||
position: absolute;
|
||||
color: #00f;
|
||||
top: 2px;
|
||||
left: 7px;
|
||||
display: inline;
|
||||
font: 11px Monaco, monospace;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
#fbCommandLine {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 2px 0 2px 32px;
|
||||
font: 11px Monaco, monospace;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
div.fbFitHeight {
|
||||
overflow: auto;
|
||||
_position: absolute;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************************************
|
||||
Layout Controls
|
||||
*************************************************************************************************/
|
||||
|
||||
/* fbToolbar buttons
|
||||
*************************************************************************************************/
|
||||
#fbWindowButtons a {
|
||||
font-size: 1px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: block;
|
||||
float: right;
|
||||
margin-right: 4px;
|
||||
text-decoration: none;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
#fbWindow_btClose {
|
||||
background: url(sprite.png) 0 -119px;
|
||||
}
|
||||
|
||||
#fbWindow_btClose:hover {
|
||||
background: url(sprite.png) -16px -119px;
|
||||
}
|
||||
|
||||
#fbWindow_btDetach {
|
||||
background: url(sprite.png) -32px -119px;
|
||||
}
|
||||
|
||||
#fbWindow_btDetach:hover {
|
||||
background: url(sprite.png) -48px -119px;
|
||||
}
|
||||
|
||||
/* fbPanelBarBox tabs
|
||||
*************************************************************************************************/
|
||||
.fbTab {
|
||||
text-decoration: none;
|
||||
display: none;
|
||||
float: left;
|
||||
width: auto;
|
||||
float: left;
|
||||
cursor: default;
|
||||
font-family: Lucida Grande, Tahoma, sans-serif;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
height: 22px;
|
||||
color: #565656;
|
||||
}
|
||||
|
||||
.fbPanelBar span {
|
||||
display: block;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.fbPanelBar .fbTabL,.fbPanelBar .fbTabR {
|
||||
height: 22px;
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.fbPanelBar .fbTabText {
|
||||
padding: 4px 1px 0;
|
||||
}
|
||||
|
||||
a.fbTab:hover {
|
||||
background: url(sprite.png) 0 -73px;
|
||||
}
|
||||
|
||||
a.fbTab:hover .fbTabL {
|
||||
background: url(sprite.png) -16px -96px;
|
||||
}
|
||||
|
||||
a.fbTab:hover .fbTabR {
|
||||
background: url(sprite.png) -24px -96px;
|
||||
}
|
||||
|
||||
.fbSelectedTab {
|
||||
background: url(sprite.png) #f1f2ee 0 -50px !important;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.fbSelectedTab .fbTabL {
|
||||
background: url(sprite.png) 0 -96px !important;
|
||||
}
|
||||
|
||||
.fbSelectedTab .fbTabR {
|
||||
background: url(sprite.png) -8px -96px !important;
|
||||
}
|
||||
|
||||
/* splitters
|
||||
*************************************************************************************************/
|
||||
#fbHSplitter {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
overflow: hidden;
|
||||
cursor: n-resize !important;
|
||||
background: url(pixel_transparent.gif);
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
#fbHSplitter.fbOnMovingHSplitter {
|
||||
height: 100%;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.fbVSplitter {
|
||||
background: #ece9d8;
|
||||
color: #000;
|
||||
border: 1px solid #716f64;
|
||||
border-width: 0 1px;
|
||||
border-left-color: #aca899;
|
||||
width: 4px;
|
||||
cursor: e-resize;
|
||||
overflow: hidden;
|
||||
right: 294px;
|
||||
text-decoration: none;
|
||||
z-index: 9;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
top: 27px;
|
||||
_width: 6px;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
div.lineNo {
|
||||
font: 11px Monaco, monospace;
|
||||
float: left;
|
||||
display: inline;
|
||||
position: relative;
|
||||
margin: 0;
|
||||
padding: 0 5px 0 20px;
|
||||
background: #eee;
|
||||
color: #888;
|
||||
border-right: 1px solid #ccc;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
pre.nodeCode {
|
||||
font: 11px Monaco, monospace;
|
||||
margin: 0;
|
||||
padding-left: 10px;
|
||||
overflow: hidden;
|
||||
/*
|
||||
_width: 100%;
|
||||
/**/
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
.nodeControl {
|
||||
margin-top: 3px;
|
||||
margin-left: -14px;
|
||||
float: left;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
overflow: hidden;
|
||||
cursor: default;
|
||||
background: url(tree_open.gif);
|
||||
_float: none;
|
||||
_display: inline;
|
||||
_position: absolute;
|
||||
}
|
||||
|
||||
div.nodeMaximized {
|
||||
background: url(tree_close.gif);
|
||||
}
|
||||
|
||||
div.objectBox-element {
|
||||
padding: 1px 3px;
|
||||
}
|
||||
.objectBox-selector{
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.selectedElement{
|
||||
background: highlight;
|
||||
/* background: url(roundCorner.svg); Opera */
|
||||
color: #fff !important;
|
||||
}
|
||||
.selectedElement span{
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
/* Webkit CSS Hack - bug in "highlight" named color */
|
||||
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||
.selectedElement{
|
||||
background: #316AC5;
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
/************************************************************************************************/
|
||||
.logRow * {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.logRow {
|
||||
position: relative;
|
||||
border-bottom: 1px solid #D7D7D7;
|
||||
padding: 2px 4px 1px 6px;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.logRow-command {
|
||||
font-family: Monaco, monospace;
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.objectBox-string,
|
||||
.objectBox-text,
|
||||
.objectBox-number,
|
||||
.objectBox-function,
|
||||
.objectLink-element,
|
||||
.objectLink-textNode,
|
||||
.objectLink-function,
|
||||
.objectBox-stackTrace,
|
||||
.objectLink-profile {
|
||||
font-family: Monaco, monospace;
|
||||
}
|
||||
|
||||
.objectBox-null {
|
||||
padding: 0 2px;
|
||||
border: 1px solid #666666;
|
||||
background-color: #888888;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.objectBox-string {
|
||||
color: red;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.objectBox-number {
|
||||
color: #000088;
|
||||
}
|
||||
|
||||
.objectBox-function {
|
||||
color: DarkGreen;
|
||||
}
|
||||
|
||||
.objectBox-object {
|
||||
color: DarkGreen;
|
||||
font-weight: bold;
|
||||
font-family: Lucida Grande, sans-serif;
|
||||
}
|
||||
|
||||
.objectBox-array {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
.logRow-info,.logRow-error,.logRow-warning {
|
||||
background: #fff no-repeat 2px 2px;
|
||||
padding-left: 20px;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
.logRow-info {
|
||||
background-image: url(infoIcon.png);
|
||||
}
|
||||
|
||||
.logRow-warning {
|
||||
background-color: cyan;
|
||||
background-image: url(warningIcon.png);
|
||||
}
|
||||
|
||||
.logRow-error {
|
||||
background-color: LightYellow;
|
||||
background-image: url(errorIcon.png);
|
||||
color: #f00;
|
||||
}
|
||||
|
||||
.errorMessage {
|
||||
vertical-align: top;
|
||||
color: #f00;
|
||||
}
|
||||
|
||||
.objectBox-sourceLink {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
top: 2px;
|
||||
padding-left: 8px;
|
||||
font-family: Lucida Grande, sans-serif;
|
||||
font-weight: bold;
|
||||
color: #0000FF;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
.logRow-group {
|
||||
background: #EEEEEE;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.logGroup {
|
||||
background: #EEEEEE;
|
||||
}
|
||||
|
||||
.logGroupBox {
|
||||
margin-left: 24px;
|
||||
border-top: 1px solid #D7D7D7;
|
||||
border-left: 1px solid #D7D7D7;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
.selectorTag,.selectorId,.selectorClass {
|
||||
font-family: Monaco, monospace;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.selectorTag {
|
||||
color: #0000FF;
|
||||
}
|
||||
|
||||
.selectorId {
|
||||
color: DarkBlue;
|
||||
}
|
||||
|
||||
.selectorClass {
|
||||
color: red;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
.objectBox-element {
|
||||
font-family: Monaco, monospace;
|
||||
color: #000088;
|
||||
}
|
||||
|
||||
.nodeChildren {
|
||||
padding-left: 26px;
|
||||
}
|
||||
|
||||
.nodeTag {
|
||||
color: blue;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.nodeValue {
|
||||
color: #FF0000;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.nodeText,.nodeComment {
|
||||
margin: 0 2px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.nodeText {
|
||||
color: #333333;
|
||||
font-family: Monaco, monospace;
|
||||
}
|
||||
|
||||
.nodeComment {
|
||||
color: DarkGreen;
|
||||
}
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
.nodeHidden, .nodeHidden * {
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
.nodeHidden .nodeTag {
|
||||
color: #5F82D9;
|
||||
}
|
||||
|
||||
.nodeHidden .nodeValue {
|
||||
color: #D86060;
|
||||
}
|
||||
|
||||
.selectedElement .nodeHidden, .selectedElement .nodeHidden * {
|
||||
color: SkyBlue !important;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************************************/
|
||||
.log-object {
|
||||
/*
|
||||
_position: relative;
|
||||
_height: 100%;
|
||||
/**/
|
||||
}
|
||||
|
||||
.property {
|
||||
position: relative;
|
||||
clear: both;
|
||||
height: 15px;
|
||||
}
|
||||
|
||||
.propertyNameCell {
|
||||
vertical-align: top;
|
||||
float: left;
|
||||
width: 28%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.propertyValueCell {
|
||||
float: right;
|
||||
width: 68%;
|
||||
background: #fff;
|
||||
position: absolute;
|
||||
padding-left: 5px;
|
||||
display: table-cell;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
/*
|
||||
_position: relative;
|
||||
/**/
|
||||
}
|
||||
|
||||
.propertyName {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.FirebugPopup {
|
||||
height: 100% !important;
|
||||
}
|
||||
|
||||
.FirebugPopup #fbWindowButtons {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.FirebugPopup #fbHSplitter {
|
||||
display: none !important;
|
||||
}
|
||||
20
vendor/firebug-lite/skin/xp/firebug.IE6.css
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/************************************************************************************************/
|
||||
#fbToolbarSearch {
|
||||
background-image: url(search.gif) !important;
|
||||
}
|
||||
/************************************************************************************************/
|
||||
.fbErrors {
|
||||
background-image: url(errorIcon.gif) !important;
|
||||
}
|
||||
/************************************************************************************************/
|
||||
.logRow-info {
|
||||
background-image: url(infoIcon.gif) !important;
|
||||
}
|
||||
|
||||
.logRow-warning {
|
||||
background-image: url(warningIcon.gif) !important;
|
||||
}
|
||||
|
||||
.logRow-error {
|
||||
background-image: url(errorIcon.gif) !important;
|
||||
}
|
||||
3147
vendor/firebug-lite/skin/xp/firebug.css
vendored
Normal file
215
vendor/firebug-lite/skin/xp/firebug.html
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/DTD/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
||||
<title>Firebug Lite</title>
|
||||
<!-- An empty script to avoid FOUC when loading the stylesheet -->
|
||||
<script type="text/javascript"></script>
|
||||
<style type="text/css" media="screen">@import "firebug.css";</style>
|
||||
<style>html,body{margin:0;padding:0;overflow:hidden;}</style>
|
||||
</head>
|
||||
<body class="fbBody">
|
||||
<table id="fbChrome" cellpadding="0" cellspacing="0" border="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<!-- Interface - Top Area -->
|
||||
<td id="fbTop" colspan="2">
|
||||
|
||||
<!--
|
||||
<div>
|
||||
--><!-- <span id="fbToolbarErrors" class="fbErrors">2 errors</span> --><!--
|
||||
<input type="text" id="fbToolbarSearch" />
|
||||
</div>
|
||||
-->
|
||||
|
||||
<!-- Window Buttons -->
|
||||
<div id="fbWindowButtons">
|
||||
<a id="fbWindow_btDeactivate" class="fbSmallButton fbHover" title="Deactivate Firebug for this web page"> </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>
|
||||
</div>
|
||||
|
||||
<!-- Toolbar buttons and Status Bar -->
|
||||
<div id="fbToolbar">
|
||||
<div id="fbToolbarContent">
|
||||
|
||||
<!-- Firebug Button -->
|
||||
<span id="fbToolbarIcon">
|
||||
<a id="fbFirebugButton" class="fbIconButton" class="fbHover" target="_blank"> </a>
|
||||
</span>
|
||||
|
||||
<!--
|
||||
<span id="fbLeftToolbarErrors" class="fbErrors">2 errors</span>
|
||||
-->
|
||||
|
||||
<!-- Toolbar Buttons -->
|
||||
<span id="fbToolbarButtons">
|
||||
<!-- Fixed Toolbar Buttons -->
|
||||
<span id="fbFixedButtons">
|
||||
<a id="fbChrome_btInspect" class="fbButton fbHover" title="Click an element in the page to inspect">Inspect</a>
|
||||
</span>
|
||||
|
||||
<!-- Console Panel Toolbar Buttons -->
|
||||
<span id="fbConsoleButtons" class="fbToolbarButtons">
|
||||
<a id="fbConsole_btClear" class="fbButton fbHover" title="Clear the console">Clear</a>
|
||||
</span>
|
||||
|
||||
<!-- HTML Panel Toolbar Buttons -->
|
||||
<!--
|
||||
<span id="fbHTMLButtons" class="fbToolbarButtons">
|
||||
<a id="fbHTML_btEdit" class="fbHover" title="Edit this HTML">Edit</a>
|
||||
</span>
|
||||
-->
|
||||
</span>
|
||||
|
||||
<!-- Status Bar -->
|
||||
<span id="fbStatusBarBox">
|
||||
<span class="fbToolbarSeparator"></span>
|
||||
<!-- HTML Panel Status Bar -->
|
||||
<!--
|
||||
<span id="fbHTMLStatusBar" class="fbStatusBar fbToolbarButtons">
|
||||
</span>
|
||||
-->
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- PanelBars -->
|
||||
<div id="fbPanelBarBox">
|
||||
|
||||
<!-- Main PanelBar -->
|
||||
<div id="fbPanelBar1" class="fbPanelBar">
|
||||
<a id="fbConsoleTab" class="fbTab fbHover">
|
||||
<span class="fbTabL"></span>
|
||||
<span class="fbTabText">Console</span>
|
||||
<span class="fbTabMenuTarget"></span>
|
||||
<span class="fbTabR"></span>
|
||||
</a>
|
||||
<a id="fbHTMLTab" class="fbTab fbHover">
|
||||
<span class="fbTabL"></span>
|
||||
<span class="fbTabText">HTML</span>
|
||||
<span class="fbTabR"></span>
|
||||
</a>
|
||||
<a class="fbTab fbHover">
|
||||
<span class="fbTabL"></span>
|
||||
<span class="fbTabText">CSS</span>
|
||||
<span class="fbTabR"></span>
|
||||
</a>
|
||||
<a class="fbTab fbHover">
|
||||
<span class="fbTabL"></span>
|
||||
<span class="fbTabText">Script</span>
|
||||
<span class="fbTabR"></span>
|
||||
</a>
|
||||
<a class="fbTab fbHover">
|
||||
<span class="fbTabL"></span>
|
||||
<span class="fbTabText">DOM</span>
|
||||
<span class="fbTabR"></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Side PanelBars -->
|
||||
<div id="fbPanelBar2Box" class="hide">
|
||||
<div id="fbPanelBar2" class="fbPanelBar">
|
||||
<!--
|
||||
<a class="fbTab fbHover">
|
||||
<span class="fbTabL"></span>
|
||||
<span class="fbTabText">Style</span>
|
||||
<span class="fbTabR"></span>
|
||||
</a>
|
||||
<a class="fbTab fbHover">
|
||||
<span class="fbTabL"></span>
|
||||
<span class="fbTabText">Layout</span>
|
||||
<span class="fbTabR"></span>
|
||||
</a>
|
||||
<a class="fbTab fbHover">
|
||||
<span class="fbTabL"></span>
|
||||
<span class="fbTabText">DOM</span>
|
||||
<span class="fbTabR"></span>
|
||||
</a>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Horizontal Splitter -->
|
||||
<div id="fbHSplitter"> </div>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Interface - Main Area -->
|
||||
<tr id="fbContent">
|
||||
|
||||
<!-- Panels -->
|
||||
<td id="fbPanelBox1">
|
||||
<div id="fbPanel1" class="fbFitHeight">
|
||||
<div id="fbConsole" class="fbPanel"></div>
|
||||
<div id="fbHTML" class="fbPanel"></div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<!-- Side Panel Box -->
|
||||
<td id="fbPanelBox2" class="hide">
|
||||
|
||||
<!-- VerticalSplitter -->
|
||||
<div id="fbVSplitter" class="fbVSplitter"> </div>
|
||||
|
||||
<!-- Side Panels -->
|
||||
<div id="fbPanel2" class="fbFitHeight">
|
||||
|
||||
<!-- HTML Side Panels -->
|
||||
<div id="fbHTML_Style" class="fbPanel"></div>
|
||||
<div id="fbHTML_Layout" class="fbPanel"></div>
|
||||
<div id="fbHTML_DOM" class="fbPanel"></div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Large Command Line -->
|
||||
<textarea id="fbLargeCommandLine" class="fbFitHeight"></textarea>
|
||||
|
||||
<!-- Large Command Line Buttons -->
|
||||
<div id="fbLargeCommandButtons">
|
||||
<a id="fbCommand_btRun" class="fbButton fbHover">Run</a>
|
||||
<a id="fbCommand_btClear" class="fbButton fbHover">Clear</a>
|
||||
|
||||
<a id="fbSmallCommandLineIcon" class="fbSmallButton fbHover"></a>
|
||||
</div>
|
||||
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<!-- Interface - Bottom Area -->
|
||||
<tr id="fbBottom" class="hide">
|
||||
|
||||
<!-- Command Line -->
|
||||
<td id="fbCommand" colspan="2">
|
||||
<div id="fbCommandBox">
|
||||
<div id="fbCommandIcon">>>></div>
|
||||
<input id="fbCommandLine" name="fbCommandLine" type="text" />
|
||||
<a id="fbLargeCommandLineIcon" class="fbSmallButton fbHover"></a>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<span id="fbMiniChrome">
|
||||
<span id="fbMiniContent">
|
||||
<span id="fbMiniIcon" title="Open Firebug Lite"></span>
|
||||
<span id="fbMiniErrors" class="fbErrors"><!-- 2 errors --></span>
|
||||
</span>
|
||||
</span>
|
||||
<!--
|
||||
<div id="fbErrorPopup">
|
||||
<div id="fbErrorPopupContent">
|
||||
<div id="fbErrorIndicator" class="fbErrors">2 errors</div>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
BIN
vendor/firebug-lite/skin/xp/firebug.png
vendored
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
vendor/firebug-lite/skin/xp/group.gif
vendored
Normal file
|
After Width: | Height: | Size: 158 B |
272
vendor/firebug-lite/skin/xp/html.css
vendored
Normal file
@@ -0,0 +1,272 @@
|
||||
/* See license.txt for terms of usage */
|
||||
|
||||
.panelNode-html {
|
||||
-moz-box-sizing: padding-box;
|
||||
padding: 4px 0 0 2px;
|
||||
}
|
||||
|
||||
.nodeBox {
|
||||
position: relative;
|
||||
font-family: Monaco, monospace;
|
||||
padding-left: 13px;
|
||||
-moz-user-select: -moz-none;
|
||||
}
|
||||
.nodeBox.search-selection {
|
||||
-moz-user-select: text;
|
||||
}
|
||||
.twisty {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.nodeChildBox {
|
||||
margin-left: 12px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nodeLabel,
|
||||
.nodeCloseLabel {
|
||||
margin: -2px 2px 0 2px;
|
||||
border: 2px solid transparent;
|
||||
-moz-border-radius: 3px;
|
||||
padding: 0 2px;
|
||||
color: #000088;
|
||||
}
|
||||
|
||||
.nodeCloseLabel {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nodeTag {
|
||||
cursor: pointer;
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.nodeValue {
|
||||
color: #FF0000;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.nodeText,
|
||||
.nodeComment {
|
||||
margin: 0 2px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.nodeText {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.nodeWhiteSpace {
|
||||
border: 1px solid LightGray;
|
||||
white-space: pre; /* otherwise the border will be collapsed around zero pixels */
|
||||
margin-left: 1px;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
|
||||
.nodeWhiteSpace_Space {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.nodeTextEntity {
|
||||
border: 1px solid gray;
|
||||
white-space: pre; /* otherwise the border will be collapsed around zero pixels */
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
.nodeComment {
|
||||
color: DarkGreen;
|
||||
}
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
.nodeBox.highlightOpen > .nodeLabel {
|
||||
background-color: #EEEEEE;
|
||||
}
|
||||
|
||||
.nodeBox.highlightOpen > .nodeCloseLabel,
|
||||
.nodeBox.highlightOpen > .nodeChildBox,
|
||||
.nodeBox.open > .nodeCloseLabel,
|
||||
.nodeBox.open > .nodeChildBox {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.selected > .nodeLabel {
|
||||
border-color: Highlight;
|
||||
background-color: Highlight;
|
||||
color: HighlightText !important;
|
||||
}
|
||||
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText {
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
.nodeBox.highlighted > .nodeLabel {
|
||||
border-color: Highlight !important;
|
||||
background-color: cyan !important;
|
||||
color: #000000 !important;
|
||||
}
|
||||
|
||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
||||
.nodeBox.highlighted > .nodeLabel > .nodeLabelBox > .nodeText {
|
||||
color: #000000 !important;
|
||||
}
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.nodeHidden .nodeCloseLabel,
|
||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeText,
|
||||
.nodeBox.nodeHidden .nodeText {
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||
.nodeBox.nodeHidden .nodeCloseLabel > .nodeCloseLabelBox > .nodeTag {
|
||||
color: #5F82D9;
|
||||
}
|
||||
|
||||
.nodeBox.nodeHidden .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue {
|
||||
color: #D86060;
|
||||
}
|
||||
|
||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeTag,
|
||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue,
|
||||
.nodeBox.nodeHidden.selected > .nodeLabel > .nodeLabelBox > .nodeText {
|
||||
color: SkyBlue !important;
|
||||
}
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
.nodeBox.mutated > .nodeLabel,
|
||||
.nodeAttr.mutated,
|
||||
.nodeValue.mutated,
|
||||
.nodeText.mutated,
|
||||
.nodeBox.mutated > .nodeText {
|
||||
background-color: #EFFF79;
|
||||
color: #FF0000 !important;
|
||||
}
|
||||
|
||||
.nodeBox.selected.mutated > .nodeLabel,
|
||||
.nodeBox.selected.mutated > .nodeLabel > .nodeLabelBox,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr.mutated > .nodeValue,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeAttr > .nodeValue.mutated,
|
||||
.nodeBox.selected > .nodeLabel > .nodeLabelBox > .nodeText.mutated {
|
||||
background-color: #EFFF79;
|
||||
border-color: #EFFF79;
|
||||
color: #FF0000 !important;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
|
||||
.logRow-dirxml {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.soloElement > .nodeBox {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.useA11y .nodeLabel.focused {
|
||||
outline: 2px solid #FF9933;
|
||||
-moz-outline-radius: 3px;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.useA11y .nodeLabelBox:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/************************************************************************************************/
|
||||
|
||||
.breakpointCode .twisty {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.breakpointCode .nodeBox.containerNodeBox,
|
||||
.breakpointCode .nodeLabel {
|
||||
padding-left: 0px;
|
||||
margin-left: 0px;
|
||||
font-family: Monaco, monospace !important;
|
||||
}
|
||||
|
||||
.breakpointCode .nodeTag,
|
||||
.breakpointCode .nodeAttr,
|
||||
.breakpointCode .nodeText,
|
||||
.breakpointCode .nodeValue,
|
||||
.breakpointCode .nodeLabel {
|
||||
color: DarkGreen !important;
|
||||
}
|
||||
|
||||
.breakpointMutationType {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 20px;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/************************************************************************************************/
|
||||
/************************************************************************************************/
|
||||
/************************************************************************************************/
|
||||
/************************************************************************************************/
|
||||
/************************************************************************************************/
|
||||
/************************************************************************************************/
|
||||
/************************************************************************************************/
|
||||
/************************************************************************************************/
|
||||
/************************************************************************************************/
|
||||
/************************************************************************************************/
|
||||
|
||||
|
||||
|
||||
/************************************************************************************************/
|
||||
/* Twisties */
|
||||
|
||||
.twisty,
|
||||
.logRow-errorMessage > .hasTwisty > .errorTitle,
|
||||
.logRow-log > .objectBox-array.hasTwisty,
|
||||
.logRow-spy .spyHead .spyTitle,
|
||||
.logGroup > .logRow,
|
||||
.memberRow.hasChildren > .memberLabelCell > .memberLabel,
|
||||
.hasHeaders .netHrefLabel,
|
||||
.netPageRow > .netCol > .netPageTitle {
|
||||
background-image: url(twistyClosed.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 2px 2px;
|
||||
min-height: 12px;
|
||||
}
|
||||
|
||||
.logRow-errorMessage > .hasTwisty.opened > .errorTitle,
|
||||
.logRow-log > .objectBox-array.hasTwisty.opened,
|
||||
.logRow-spy.opened .spyHead .spyTitle,
|
||||
.logGroup.opened > .logRow,
|
||||
.memberRow.hasChildren.opened > .memberLabelCell > .memberLabel,
|
||||
.nodeBox.highlightOpen > .nodeLabel > .twisty,
|
||||
.nodeBox.open > .nodeLabel > .twisty,
|
||||
.netRow.opened > .netCol > .netHrefLabel,
|
||||
.netPageRow.opened > .netCol > .netPageTitle {
|
||||
background-image: url(twistyOpen.png);
|
||||
}
|
||||
|
||||
.twisty {
|
||||
background-position: 4px 4px;
|
||||
}
|
||||
BIN
vendor/firebug-lite/skin/xp/infoIcon.gif
vendored
Normal file
|
After Width: | Height: | Size: 359 B |
BIN
vendor/firebug-lite/skin/xp/infoIcon.png
vendored
Normal file
|
After Width: | Height: | Size: 524 B |
BIN
vendor/firebug-lite/skin/xp/loading_16.gif
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
vendor/firebug-lite/skin/xp/min.png
vendored
Normal file
|
After Width: | Height: | Size: 552 B |
BIN
vendor/firebug-lite/skin/xp/minHover.png
vendored
Normal file
|
After Width: | Height: | Size: 485 B |
BIN
vendor/firebug-lite/skin/xp/off.png
vendored
Normal file
|
After Width: | Height: | Size: 742 B |
BIN
vendor/firebug-lite/skin/xp/offHover.png
vendored
Normal file
|
After Width: | Height: | Size: 680 B |
BIN
vendor/firebug-lite/skin/xp/pixel_transparent.gif
vendored
Normal file
|
After Width: | Height: | Size: 43 B |
6
vendor/firebug-lite/skin/xp/roundCorner.svg
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<rect fill="white" x="0" y="0" width="100%" height="100%" />
|
||||
<rect fill="highlight" x="0" y="0" width="100%" height="100%" rx="2px"/>
|
||||
</svg>
|
||||
|
||||
|
After Width: | Height: | Size: 234 B |
BIN
vendor/firebug-lite/skin/xp/search.gif
vendored
Normal file
|
After Width: | Height: | Size: 550 B |
BIN
vendor/firebug-lite/skin/xp/search.png
vendored
Normal file
|
After Width: | Height: | Size: 685 B |
BIN
vendor/firebug-lite/skin/xp/shadow.gif
vendored
Normal file
|
After Width: | Height: | Size: 4.3 KiB |
BIN
vendor/firebug-lite/skin/xp/shadow2.gif
vendored
Normal file
|
After Width: | Height: | Size: 3.0 KiB |