diff --git a/.Gruntfile.js.swp b/.Gruntfile.js.swp new file mode 100644 index 0000000..badf973 Binary files /dev/null and b/.Gruntfile.js.swp differ diff --git a/Gruntfile.js b/Gruntfile.js index 25d9d83..34bb635 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,6 +1,7 @@ module.exports = function(grunt) { grunt.loadNpmTasks('grunt-contrib-less'); + grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-contrib'); grunt.initConfig({ @@ -22,7 +23,9 @@ module.exports = function(grunt) { "build/metro-vibes/metro-vibes.css": "themes/metro-vibes/metro-vibes.less", "build/metro-vibes-dark/metro-vibes-dark.css": "themes/metro-vibes-dark/metro-vibes-dark.less", "build/wood/wood.css": "themes/wood/wood.less", - "build/wood-ri/wood-ri.css": "themes/wood-ri/wood-ri.less" + "build/wood-ri/wood-ri.css": "themes/wood-ri/wood-ri.less", + "build/imazine/magazine.css": "themes/imazine/magazine.less", + "build/imazine/water-color.css": "themes/imazine/water-color.less" } } }, @@ -44,9 +47,20 @@ module.exports = function(grunt) { { src: 'themes/wood-ri/wood.jpg', dest: 'build/wood-ri/wood.jpg' } ] } + }, + + watch: { + options: { + files: ['themes/**'], + tasks: ['less'], + options:{ + livereload: true, + } + } } + }); grunt.registerTask('default', [ 'less:development', 'copy:resources', 'copy:preview' ]); grunt.registerTask('build', [ 'less:development', 'copy' ]); -} \ No newline at end of file +} diff --git a/assets/css/imazine/.magazine.css.swo b/assets/css/imazine/.magazine.css.swo new file mode 100644 index 0000000..d20d84d Binary files /dev/null and b/assets/css/imazine/.magazine.css.swo differ diff --git a/assets/css/imazine/magazine.css b/assets/css/imazine/magazine.css new file mode 100644 index 0000000..1291af6 --- /dev/null +++ b/assets/css/imazine/magazine.css @@ -0,0 +1,104 @@ +@import url(http://fonts.googleapis.com/css?family=Quicksand:300,400,700); + +.magazine{ + font: 1em 'Quicksand', sans-serif, 'Apple SD Gothic Neo', '맑은 고딕','Malgun Gothic', 'Nanum Gothic', '나눔고딕','Driod Sans Fallback', 'Driod Sans', Helvetica, 'Gulim'; + padding: 50px; + color: #222; + line-height: 1.5em; + letter-spacing: -0.03em; + word-spacing: 0.24em; + font-weight: 300; + /*text-shadow: inset 1px 1px 1px black;*/ +} + +.magazine h1, +.magazine h2, +.magazine h3, +.magazine h4, +.magazine h5, +.magazine h6{ + letter-spacing: -0.1em; + font-weight: 400; + padding-top: 30px; + color: #000; + margin: 30px 0; +} + +.magazine a{ + color: #e74b3b; + font-weight: 400; + text-decoration: underline; +} + +.magazine h1{ + padding: 40px 0 20px; + font-size: 3em; + line-height: 1em; +} + +.magazine h2{ + border-bottom: 1px solid; + padding: 14px 0; +} + +.magazine img{ + -webkit-transition: scale 0.4s ease; +} + +.magazine strong.highlight{ + background-color: #d91303; + padding: 4px 8px; + border-radius: 10px; + color: white; +} + +.magazine thead{ + background-color: #e74b3b; + color: white; +} + +.magazine tbody tr td{ + border-color: white; + padding: 10px 14px; +} + +.magazine tbody tr{ + background-color: #f2f2f2; +} + +.magazine tbody tr:nth-child(2n){ + background-color: #e3dad9; +} + +.magazine pre{ + border: none; + background: #f2f2f2; + color: #a70b00; + border-radius: 10px; + padding: 30px; +} + +.magazine pre code{ + border: none; + font-weight: 300; +} + +.magazine blockquote{ + padding: 30px; + font-style: italic; + font-size: 1.2em; + font-weight: bold; + color: black; + background-color: #f2f2f2; + border-radius: 10px; + margin: 0 auto; + width: 84%; +} + +.magazine blockquote p:before, +.magazine blockquote p:after{ + position: relative; + top: 0.05em; + color: black; + content: ' " '; +} \ No newline at end of file diff --git a/assets/css/imazine/water-color.css b/assets/css/imazine/water-color.css new file mode 100644 index 0000000..5e9ff98 --- /dev/null +++ b/assets/css/imazine/water-color.css @@ -0,0 +1,87 @@ +.water-color{ + background: url(data:image/jpg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAA8AAD/4QMbaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjMtYzAxMSA2Ni4xNDU2NjEsIDIwMTIvMDIvMDYtMTQ6NTY6MjcgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjNERkQ4QkZFNDQzQzExRTNCOEE4OEI1ODQ1QjBBM0EwIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjNERkQ4QkZENDQzQzExRTNCOEE4OEI1ODQ1QjBBM0EwIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzYgTWFjaW50b3NoIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9IjRCM0IzRTc1RUI0QjA4RDM1QzY4MEI3QTBFQUMwRERGIiBzdFJlZjpkb2N1bWVudElEPSI0QjNCM0U3NUVCNEIwOEQzNUM2ODBCN0EwRUFDMERERiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pv/uAA5BZG9iZQBkwAAAAAH/2wCEAAYEBAQFBAYFBQYJBgUGCQsIBgYICwwKCgsKCgwQDAwMDAwMEAwODxAPDgwTExQUExMcGxsbHB8fHx8fHx8fHx8BBwcHDQwNGBAQGBoVERUaHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fH//AABEIAMgAyAMBEQACEQEDEQH/xABvAAEBAQEBAQAAAAAAAAAAAAACAQADBAgBAQAAAAAAAAAAAAAAAAAAAAAQAAIBAwMCBAUDBAIDAQAAAAECEQASAyExQVEiYTITBHGBkUJSobEjwdEzFOFi8PFyQxEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8A+mWuYi4a8+HyoIMeJSR551JoMyu4tUFJ2Kjigo9sFgwPEbzQM5QBYh20t03oODj3mQwotA09TpQNMPu1EXz1I3oOtzpoGuNATkzkHSByTvQDH7fIWZjkJU6quwHwoER6YJBLDnk0AdlcD1HKLwooEMeNvM1x+09KC3FV0kg6QKAIMawDcW6zMTQdguAgmCsb+NAVbCQbQWA2FB5n95/LorrwNN6D0jOw1Yd5+7/3QDJlwsQHJ+W80AbIQe24xtNBCysArqwncrrNB1t9sE2KqODvQAPgthFnWSxoGhyEeoBap2WglqgSduvNAlGpBPz5igjK0HuKsuxGtBC4LwMgtPTf4UB9D2+Ms9xVzrceKDoVuSbzoND1oOT+6QqF9S2e3UazQbFjwqZyMzZaDsq42aGYq/HwoC2TGWKqSXG80GVo8q3Ggt6lrrfnQQnLsqgA8HegtrgaAXHg8UCVXIhAB1ag5Zfbe7LXqwkbjigy47AFs824Oomg6rYk3C2OvFACJYGQ5P3eHwoEvs01mCTqDQYLYQJmgJ90gYrj7mHmEUG9PKzX43sB3Xmgq4spk3CBweaCmcerNN32UFtcmSvZHlO9AI1nyHod6BEZDrsP6UE9RQDI02JigAxAi4rdGo+HjQIe6xDdY6LG1BUz+3chog/awFA2OPJBUiBuaAZ8eVhKEQd56eFAQxVQpAZd5jWgQbXVSAOBQY3HURrsKCSyzGp60FXK2t47TrPIoNlGN4BYwPt2oIoxBoVmNu29An906oGAid9KAYw2YC7JcDt4UHS1VHaBdwf6UHMr7kAsrSOQODQVD7gKWyC6ftoKiljDgKfCgjJLRJ7fvmgdyArPm2H96CHJBKxcOooC2RkHbDRtNBF9xlKyccfKgi5mLfyggeH6UD9TGGAYQTsBQYM91xELweaCNiV2ktoaDo64UFpGh5FBx9LHjWUQuR9o2oIMuff0zb+PPyoOlzKO1Wu/E0GdMkggwYoCb9AWCxvQJHxqu9BbnfVABrz4UBOhIVCY3bxoLcoi8QeFoGGxSNdekb0AyJrpjgHkGgCe2ebgQT0mgxz5ka3T9v3oOozuVAiG68UEtzlTDAHxoAvqAk5mUKBpaaCzhygCYYbUCGC1YBBH1NAYCRoJn9aC+oxa2yQeZ5oHbC2gju0oD6LDuGv2/AUBdWGjuQg6a0EBS3Rxr5RQBcOU6er/APQ30oH6pxkIoLNsARB+M0DbMFIDPB/Eb0ACe4OSfUlTt4CgYFpm4tO1AC2S+CgAPzNBbcI30PANAiVXvv0Aig54/cI6SZDAwFH70DVBkBbI027KRQTRWuVrjyu5FBzfLkZhGNo2k7TQdLgxiLVA7qDE+ztBYkkbTv8ACggzEABce5/SgbPMgjeg3o4lW99+JoIUJW4BSTs3Sg5BfdjV4M8LQd/TbUkhiRoKA2JrMg9Bt8qAsrBYQGaChSElpJ5igQbCFvsLRuKDnfibuGOByJn9KDAtb2KAD8qBQ1hDkjk0GHptpAt8B3fWgrBLTaYb40BGJgASZPAoEDaOnXighZW8w+BoKLTpZdQHIcHaGlTOkb0HRvbswAUgHcUBXFlWYAn8h0HWgXqtBDaiNOtBr7hAIIG9BxGDAXlm7jsOhoOrY8io0RPLc0B/gCyvO5Y6TQZMSFvVZrlP2nX6CgtmJ3uAYACI8o+lBC2QG3GCOpNBDkzDTGZbgAUGv9yFBIA8JoIjZBqwmeeJoGM5BsI156UB9L+UOckaarxQdBixxowk6fKgB9PDpxxQRXRnNwuFB0GLDabVg0HP0FV7gPE0FYsdgSeKDTgkLkkseKBH0gLUXuXegkOdtKAhDdJlvE0EiHP8vwG370C9ZwCPUkDjrQRMa5Achyx+IGwoKuFNyPBW2oCZVv8AHcRsxoOQzOzFzhPbs3X4CgfrY2Noxhn0uDaCDQQ/7LZC+JLFIgtzHhQdRjzWwzz8aDBkBgZQCNxQYuFPa0Hj4UGXIxaGKWHWaDp2MAobtoD6SyDIN3moCBjSZ16c0Be1dUW/x2igsBxLb7gHp0oHeCliqFPiQKAFMrGS4CigoyKAQTdFBDmyT2n5UGdcjCRAbigqXBYc/E8UGOV2JKACODufhQRv9ggFSFI3kSI5oJbiyi1xrMrNAnx+3x6WkxoVidfnQQZC69qBY3Gg/agWQlkgmF/GgiZlQDG/mHWgQyZCbgQQNulASuVgXIFxOhgaGgy+uildCeW6UCvVu0nWgxx+2USQBO7daDDGsguhAGpmgDZMBBUY7yNSBtQQ48jgWi0bz0oGUsUG2Y3oKcoVLkxieRz9KDn6pi6AOsaUCClt4M0Ef2+N2hjBXYCgxw5AYBDoPtoKlq+ZIadTxQV7hNoknbigIQzJJUj6UGKqQZbTmaBfwr3bnfrQZM4yyA8N+J2mgxxsWvYgFdNNqCLjyEQWtjcjWfjQUPJtZBps3Wg047u49x3Q6UDcIYJKidNaDkf42AXHcvB+FBvXZplSqkQQN6BGxFnJqg2J1NAYxsvqIkeOxigS3773aBT060F0ZQpyz0jegxwlYtYBv3oI2LJoS+vQUBGfuKFjI38KCImAO2QMZI1oOo9BtA2+460HN3VDbFBUEAkgnpQW8rsN6CyzyNhyDtQSGXQLcetBH9eJgA8RQRZP+RfkNqDGA2i6c0COHAoDbHqOtByPukxtpLA9OvWgYzXHyb8xFAg+hB8g36/Kgll3e2vQ80GXAoP+S5zsImKBXZMcgrcTzNBg+QiQwuO2m1AWwe4ynuft8NKDJ7c3FcjkrEfHwoKi4cX8eNjH7fWgYRQsIAKDmUjuU6dSaAK8GW1jbxoOqgSO1VHLGgqsLYbRZ0oOeQZFacYDLuSd6DdoAk9w2nmgTZg2hZVI2maAlY7mcidqDIQZ1JoFdbtvQZcytqHBA4NBGYMfNFBQVgc+NBGV2N0x4cUGX25YE5AI8KBkhQTIt2APFAS6GC5mOlBTaBKGBvrzQUFSJAJjU/Gg5/7hZoCEAHzEUFbCchlGjqsc0FfIqEKMhuI0Xmgvq4hjF0yNyetAfUxZBNrH/uRoKABWEqpDLvAMt9aBWAavJB3PSg166QunDHkUFjEy8welBFRritvbGh5oEFfkQvWgot+6PA0BGPDkJLeYGg3oMCSjSOAeKBAsoAKwNrqAkEmARHWgP+vhLXNIYdKBDEVBNBDjWdRBO1BVx5l1BuXpQa9pIJg9fCgjYkkkG4ncdaAgwIQBf1oKuME6vr/5xQdV9RR5pnmg0vBkiDQcmQ29rgE760Gx4ghLnvcjVtz8qDoYYghYMDegJXI3cc4j8REUEWzVlWSNIFBl9ZmB0AoEMtxtMab8UB9HukvqeBxQMY5TRiWoAuV1aP0NBnBcgntHMcUCYY1Xs7ifNzQFW9xwunWgQUsJY2zuN6Cxk2SI60AyY82nd3daCY/WUywknmgbWtu2pP18KCZMgELJjrQcwsm4MWjrQdACRroR8qCjRbSog7GgzY101iNz0oCz40gFpG/WgyP6ncAYGwoEAWPcsHpQUC3VTr0oCsEy0kjigbNiiEUseaC5MqYhLESeBQD18ZIF0T9sUEbFjdgbzI4oM38fkaWOg+NBEy/ad+eKBPlw7FviBvQYhI0YAc0AGTulMlo/E8+NBrjlMBioG8bmgaY8arqTQZsioNNOtBFzpEhiD+J3oMCcpkOVXw3oNkUKNpjUGKCp6gS5gNf2oI2a3ULI67UE9TKSNO07zQKGA1B04oMrLrI+RoMuSDstp5H9qBFtYX+1Bzb1YjGe7knigwfMmmXGR4zIoFJfSYIoGMJgRkjr40HL/W9skX5GPx2oHb7RSSBc2g0oMfRGoJ6k0Ex5FbtCablqCu2MkKyi7igxx401MFxtpOlByDtPdhazwFArfas49RSMnBP96BK/t0JIOo5igmXK57gjkDUMBpQEZGi44iei80GVPbO17pbkPPNArQAShj+9BFHuF2JLHrQNWcmNCw3FBv8AVu3JYdCSKClSshTJjQUBGwmWP7UFC6ENpwBzQY4EQTcSxoMVAWC0E6gUEZk2bTpHPjQIEMujduxFBFVBsCwG9AXxs+zFVPNBBl9pmHmujYUBKN9iAKdpFAgubEAEhiTqTQdLzaZHfvFBExPkUO5WTtQZcdj3F4NBmz5Q1qiV5PNAoOUWzbHnET9KDlk9sfKjy/BcaCgcZsQHdc/5kaN9KDD3BOywfuG0mgRT1V8xC9OZoBYyntbbcmg05NYPgsb0HP1MIYeoCpOhYkb/ACoK2TCp7crMTsooIvu8S6FiflQdPVwReWjSgxy+2dRkdpGyigByIpJxqzCNIFBcYJnIyw3BPFB0BxkEsNaCQohk35B2oMuVtlRlb96A5PcMO702I+4aaUEnFJZQI6eNAzkykQo1NBQrMCYA4t5mg82bDaDN9x2I4oLibKMaoiwdhO9B2QOoHqrex45oGFbXtOu/UUHI4/cM4thEG4PmNBVx5wpab3nagt+S6Lljcgbj40Ftcmdx4UA9P3Ja4EKg2A3nxoMBlxqD/knzGgYIaJ7f+w4oC2H2x0DSTs3jQbTCBdbZ4DU+FAp9s8KIk8A91BX9rjPmMqu8D96Dm5w+3F4JIO0KD8qA4vcuDae5dxaIOvXig633GI0O2kig5PizuQMT2KDueT0oEB7nGP5VWDpcuooKCjmMn15PwoEGwKxF1xXdaCoTb3KH8VEAeFBjnYPaEEAfpQR2fQhWM/tQZTm6ALxJoFkdgvaASedqAuMrCNLuG6UEVfdEQT2jkaE/OguW60C+G6bn9KCy0WzaRzMGaCLh3CkGdxzHxoNZlGx0HE0EyBiVF+v4j+9Ai522jTx+lAGF3Zsp3HWgn+kj6udtgNqBr7TAvcfNyZg/rQCfbqPUxJpME/cDQc7vUe5dI5BM/Og7Y2UkFlnjwoOpbDiI7SJ6a/pQc8mRAdcbFfDYfSgJfRQQbeGOhoHk9ILc7EzpbxQQZIxmzH4id/lQBLGN7IA/Qa/WgTPpfO+hj+lAQjnHCHSZk70FXHkUwWILayeaBHMFNuRlMcxNBQmFiMgMTs3FBmM+Vg0cUHP18oADmDyvhxQIJjuLT3N9o2oEuJDN86ajwoOTLmaRgAXHuWO80CVc6gB9epO1BbAviTutBlVIJOp4oMnrAwnaOpE0Gd8oLKgLuNzECg4vgfMwbKIt53P0oK+TPgEYkGQnrpFB0xZDbL4wHPAoFLMCFSDwRrFBB7bLEsQG67UGVMuNY3HSaDHJoY0018KCKjFr4BPE7UGGXKTdbD7W0DAzL3NbI3AoMHUTA0Gzf8UEOT3hm1RaNo/5oArMO7IHZm4GgFA0AP8A+dqnk6mgDY2vnVuiDQDxoMmJkYhk7Ny07UDXH7VyJAkbA6TQMwvERsB08aDhmb3EAaBDuRvFB0udVBLAqNoGvzoN6yt/SgpPbqNR9KDnkOe4C0AUCtY6vI8BtHjQH0PbnLMuzfEwKBelnxtdf6g4ka0DDaTMnpG1AGN2pbXgxtQc/RUmTlIQ6mNJNASuItJZmUbRNAsb4bgZYqdJNB1FkyNenSgOV0UhQ9pPzoMHyM4VUujzNQaxIBcm4Ggg9r6RnG1zbEnig2PJkySvkCkyToflQdQcLKRdtpNAWXDF12u29BPUhZxdzjmgBz5wZdCxPCiQRQKZABBUHyoeKCdqduoP1E0GVmDGVJA+/wDpFA2ytICrqR5qCenkM7SeCNKCAWwJ1+tAQ+QEgqY4O5NBfNvIoCcM3K2S6e7pp0oNhzZphFuHLmY+VB0f18hFqgAbmRQR0LQt1pHm6RQU4bQLskLOxoJ/v4UFhDH/AOVJmghZHMjHF24oKcRUdrC7haBYrrf5FF/B3g0GLg9kQRqSOaAjDlYlT5Ds1BvU7hupjUGgJZzlGkSNDNBMqMMqFW/jHnA5oKcJbWLeYoM2RVWMS9w8w6mguP3eYiWxmR9ooGrk6kT1J3oHCLJ3ag5+vlP2bbD+9BMf+xN2UKngDcfrQUZbiCLm11BFArkgsFNx3G1ATlJGiSeJ0oEXaApUXfiJP60BV3Em2OpFA3GPIlkwvTagC4/b4hdsp560E9XDmkcDjj60Bx48BIlyfxuoOjYcK6lgD9sUCvRP+x60A9RBJgzwQNaCqHYBy5XoefnQQriu0cnJwetBGzs4IRYjegROFAS8kNsKCemtpKOBO1BkXIO2bgBqzH9qDHHdBDEdaDRhxtcR896BPjx+ZRJPM/0oJa2NO07nUmgDYlcAI5nwoGMTaRlJ6jrQEj3ABQnTw0oELlA4HWgLC5ha5EdNqC+ix2yEz1oA2DLEHIV6EGgS5CoKqfUgajmgirkZSw8h8woEUe1QFmgyhcWjKNToBtNAWyBibEF1BlGVC12q8AcfCgwvcyNAOtB0LEwbSR12oAcuS6EUt1UUFAlQpS2Tr1oKPSUkAFiONh86BeoYtBGMj7TrQcxiI7ma48Tt8qAM+dNVUOBwDBoOie4JGqa8igqknS0AneeKCRmBIBW7gnagxy5D/kS0DfWZ+FBr79FIROo8xoKcWQCEYKPy5oGLti4PXrQciysxBMD40CtUi0GFoCRkHasiORQS/LJlNBsOtArcrKD6ZSRvoIoMECnua7oF1HzoI7uvkaWHXbWgRGO2XJVjvGtBUTBjW9dBy060BDaTczKNS/x4oOb+57gtjAdY0+tB1S/JopNvSgxxsvnyGPxGh/SgN5Jhdum5oLcrAhVk/cG3oIcZibgpO4oEXRQINxA2oKjIyypk9OlBmfCVl2iOlBL8bggKWU89aDW36FobhOfnQH0MaEiS55HSgJQDyIwJ+4a0GJylf5AVG2h1oKuLCO6xy370FJx6BcRBO1BQnuJhVCg8mgJfOBqRrsNqBI3uHjQFG+UeFBcoygEDyn7OTQFSAsAR4DegxIJECB+PEdRQIYEt1JJG0UHNkzXqugxdTuaDqC6kSo+JoKpcTzOtu8fWgj43I0a0ngaRQFBYO7uPLUGORWHYQoG5G9AjhJWS5aNttaD/2Q==) repeat; + font: 1em 'Apple SD Gothic Neo', '맑은 고딕','Malgun Gothic', 'Nanum Gothic', '나눔고딕','Driod Sans Fallback', 'Driod Sans', Helvetica, 'Gulim'; + padding: 50px; + color: rgba(20, 10, 0, 0.7); + line-height: 1.6em; + letter-spacing: 0; + word-spacing: 2.4px; + text-shadow: inset 1px 1px 1px black; +} + +.water-color h1, +.water-color h2, +.water-color h3, +.water-color h4{ + padding-top: 30px; + color: rgba(20, 10, 0, 0.8); + /*margin: 30px 0;*/ +} + +.water-color a{ + color: #2662d4; +} + +.water-color h1{ + padding: 40px 0 20px; + font-size: 3em; + line-height: 1em; +} + +.water-color h2{ + border-bottom: 1px solid; + padding: 14px 0; +} + +.water-color img{ + opacity: 0.8; + -webkit-transition: opacity 0.4s ease; +} + +.water-color img:hover{ + opacity: 1.0; +} + +.water-color strong.highlight{ + background-color: #4672c4; + padding: 4px 8px; + border-radius: 10px; + color: white; +} + +.water-color thead{ + background-color: rgba(0, 0 ,0, 0.5); + color: white; +} +.water-color tbody tr:nth-child(2n-1){ + background-color: rgba(70, 40, 0, 0.1); +} + +.water-color pre{ + background-color: rgba(0, 0, 0, 0.5); + color: white; + padding: 20px; +} + +.water-color pre code{ + border: none; +} + +.water-color blockquote{ + padding: 30px; + font-style: italic; + font-size: 1.2em; + font-weight: bold; + color: gray; + background-color: rgba(255, 255, 255, 0.6); + margin: 0 auto; + width: 84%; +} + +.water-color blockquote p:before, +.water-color blockquote p:after{ + position: relative; + top: 0.05em; + /*color: black;*/ + content: ' " '; +} \ No newline at end of file diff --git a/index.html b/index.html index 39ad05a..44a9db5 100644 --- a/index.html +++ b/index.html @@ -18,6 +18,8 @@ + + +``` + +Feel free to add this script to your template situation and toggle with some sort of `dev` flag. + +##### Using Live Reload with the Browser Extension +Instead of adding a script tag to your page, you can live reload your page by installing a browser extension. Please visit [how do I install and use the browser extensions](http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-) for help installing an extension for your browser. + +Once installed please use the default live reload port `35729` and the browser extension will automatically reload your page without needing the ` +``` + +Feel free to add this script to your template situation and toggle with some sort of `dev` flag. + +### Using Live Reload with the Browser Extension +Instead of adding a script tag to your page, you can live reload your page by installing a browser extension. Please visit [how do I install and use the browser extensions](http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-) for help installing an extension for your browser. + +Once installed please use the default live reload port `35729` and the browser extension will automatically reload your page without needing the ` +``` + +Using [`npm`](http://npmjs.org/): + +```bash +npm install lodash + +npm install -g lodash +npm link lodash +``` + +To avoid potential issues, update `npm` before installing Lo-Dash: + +```bash +npm install npm -g +``` + +In [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/): + +```js +var _ = require('lodash'); + +// or as a drop-in replacement for Underscore +var _ = require('lodash/lodash.underscore'); +``` + +**Note:** If Lo-Dash is installed globally, run [`npm link lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your project’s root directory before requiring it. + +In [RingoJS v0.7.0-](http://ringojs.org/): + +```js +var _ = require('lodash')._; +``` + +In [Rhino](http://www.mozilla.org/rhino/): + +```js +load('lodash.js'); +``` + +In an AMD loader like [RequireJS](http://requirejs.org/): + +```js +require({ + 'paths': { + 'underscore': 'path/to/lodash' + } +}, +['underscore'], function(_) { + console.log(_.VERSION); +}); +``` + +## Release Notes + +### v1.0.1 + + * Add support for specifying source map URLs in `-p`/`--source-map` build options + * Ensured the second argument passed to `_.assign` is not treated as a `callback` + * Ensured `-p`/`--source-map` build options correctly set the `sourceMappingURL` + * Made `-p`/`--source-map` build options set source map *“sources”* keys based on the builds performed + * Made `_.defer` use `setImmediate`, in Node.js, when available + * Made `_.where` search arrays for values regardless of their index position + * Removed dead code from `_.template` + +The full changelog is available [here](https://github.com/bestiejs/lodash/wiki/Changelog). + +## BestieJS + +Lo-Dash is part of the BestieJS *“Best in Class”* module collection. This means we promote solid browser/environment support, ES5 precedents, unit testing, and plenty of documentation. + +## Author + +* [John-David Dalton](http://allyoucanleet.com/) + [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](https://twitter.com/jdalton "Follow @jdalton on Twitter") + +## Contributors + +* [Kit Cambridge](http://kitcambridge.github.com/) + [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge "Follow @kitcambridge on Twitter") +* [Mathias Bynens](http://mathiasbynens.be/) + [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter") diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/build.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/build.js new file mode 100755 index 0000000..4e34c82 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/build.js @@ -0,0 +1,2509 @@ +#!/usr/bin/env node +;(function() { + 'use strict'; + + /** Load modules */ + var fs = require('fs'), + path = require('path'), + vm = require('vm'), + minify = require(path.join(__dirname, 'build', 'minify.js')), + _ = require(path.join(__dirname, 'lodash.js')); + + /** The current working directory */ + var cwd = process.cwd(); + + /** Used for array method references */ + var arrayRef = []; + + /** Shortcut used to push arrays of values to an array */ + var push = arrayRef.push; + + /** Shortcut used to convert array-like objects to arrays */ + var slice = arrayRef.slice; + + /** Shortcut to the `stdout` object */ + var stdout = process.stdout; + + /** Used to associate aliases with their real names */ + var aliasToRealMap = { + 'all': 'every', + 'any': 'some', + 'collect': 'map', + 'detect': 'find', + 'drop': 'rest', + 'each': 'forEach', + 'extend': 'assign', + '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 = { + 'assign': ['extend'], + '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'] + }; + + /** Used to track function dependencies */ + var dependencyMap = { + 'after': [], + 'assign': ['isArray', 'forEach', 'forOwn'], + 'at': ['isString'], + 'bind': ['isFunction', 'isObject'], + 'bindAll': ['bind', 'functions'], + 'bindKey': ['isFunction', 'isObject'], + 'clone': ['assign', 'forEach', 'forOwn', 'isArray', 'isObject'], + 'cloneDeep': ['clone'], + 'compact': [], + 'compose': [], + 'contains': ['indexOf', 'isString'], + 'countBy': ['forEach', 'identity', 'isEqual', 'keys'], + 'debounce': [], + 'defaults': ['isArray', 'forEach', 'forOwn'], + 'defer': ['bind'], + 'delay': [], + 'difference': ['indexOf'], + 'escape': [], + 'every': ['identity', 'isArray', 'isEqual', 'keys'], + 'filter': ['identity', 'isArray', 'isEqual', 'keys'], + 'find': ['forEach', 'identity', 'isEqual', 'keys'], + 'first': [], + 'flatten': ['isArray'], + 'forEach': ['identity', 'isArguments', 'isArray', 'isString'], + 'forIn': ['identity', 'isArguments'], + 'forOwn': ['identity', 'isArguments'], + 'functions': ['forIn', 'isFunction'], + 'groupBy': ['forEach', 'identity', 'isEqual', 'keys'], + 'has': [], + 'identity': [], + 'indexOf': ['sortedIndex'], + 'initial': [], + 'intersection': ['indexOf'], + 'invert': ['keys'], + 'invoke': ['forEach'], + 'isArguments': [], + 'isArray': [], + 'isBoolean': [], + 'isDate': [], + 'isElement': [], + 'isEmpty': ['forOwn', 'isArguments', 'isFunction'], + 'isEqual': ['forIn', 'isArguments', 'isFunction'], + 'isFinite': [], + 'isFunction': [], + 'isNaN': ['isNumber'], + 'isNull': [], + 'isNumber': [], + 'isObject': [], + 'isPlainObject': ['forIn', 'isArguments', 'isFunction'], + 'isRegExp': [], + 'isString': [], + 'isUndefined': [], + 'keys': ['forOwn', 'isArguments', 'isObject'], + 'last': [], + 'lastIndexOf': [], + 'map': ['identity', 'isArray', 'isEqual', 'keys'], + 'max': ['isArray', 'isEqual', 'isString', 'keys'], + 'memoize': [], + 'merge': ['forEach', 'forOwn', 'isArray', 'isObject', 'isPlainObject'], + 'min': ['isArray', 'isEqual', 'isString', 'keys'], + 'mixin': ['forEach', 'forOwn', 'functions'], + 'noConflict': [], + 'object': [], + 'omit': ['forIn', 'indexOf'], + 'once': [], + 'pairs': ['keys'], + 'partial': ['isFunction', 'isObject'], + 'partialRight': ['isFunction', 'isObject'], + 'pick': ['forIn', 'isObject'], + 'pluck': ['map'], + 'random': [], + 'range': [], + 'reduce': ['identity', 'isArray', 'isEqual', 'keys'], + 'reduceRight': ['forEach', 'identity', 'isEqual', 'isString', 'keys'], + 'reject': ['filter', 'identity', 'isEqual', 'keys'], + 'rest': [], + 'result': ['isFunction'], + 'shuffle': ['forEach'], + 'size': ['keys'], + 'some': ['identity', 'isArray', 'isEqual', 'keys'], + 'sortBy': ['forEach', 'identity', 'isEqual', 'keys'], + 'sortedIndex': ['identity', 'isEqual', 'keys'], + 'tap': ['mixin'], + 'template': ['defaults', 'escape', 'keys', 'values'], + 'throttle': [], + 'times': [], + 'toArray': ['isString', 'values'], + 'unescape': [], + 'union': ['uniq'], + 'uniq': ['indexOf', 'isEqual', 'keys'], + 'uniqueId': [], + 'value': ['mixin'], + 'values': ['keys'], + 'where': ['filter'], + 'without': ['indexOf'], + 'wrap': [], + 'zip': ['max', 'pluck'], + + // method used by the `backbone` and `underscore` builds + 'chain': ['mixin'], + 'findWhere': ['where'] + }; + + /** Used to inline `iteratorTemplate` */ + var iteratorOptions = [ + 'args', + 'arrays', + 'bottom', + 'firstArg', + 'hasDontEnumBug', + 'hasEnumPrototype', + 'isKeysFast', + 'loop', + 'nonEnumArgs', + 'noCharByIndex', + 'shadowed', + 'top', + 'useHas' + ]; + + /** List of all Lo-Dash methods */ + var allMethods = _.keys(dependencyMap); + + /** List of Backbone's Lo-Dash dependencies */ + var backboneDependencies = [ + 'bind', + 'bindAll', + 'chain', + 'clone', + 'contains', + 'countBy', + 'defaults', + 'escape', + 'every', + 'extend', + 'filter', + 'find', + 'first', + 'forEach', + 'groupBy', + 'has', + 'indexOf', + 'initial', + 'invoke', + 'isArray', + 'isEmpty', + 'isEqual', + 'isFunction', + 'isObject', + 'isRegExp', + 'isString', + 'keys', + 'last', + 'lastIndexOf', + 'map', + 'max', + 'min', + 'mixin', + 'once', + 'pick', + 'reduce', + 'reduceRight', + 'reject', + 'rest', + 'result', + 'shuffle', + 'size', + 'some', + 'sortBy', + 'sortedIndex', + 'toArray', + 'uniqueId', + 'value', + 'without' + ]; + + /** List of methods used by Underscore */ + var underscoreMethods = _.without.apply(_, [allMethods].concat([ + 'at', + 'bindKey', + 'cloneDeep', + 'forIn', + 'forOwn', + 'isPlainObject', + 'merge', + 'partialRight' + ])); + + /** List of ways to export the `lodash` function */ + var exportsAll = [ + 'amd', + 'commonjs', + 'global', + 'node' + ]; + + /*--------------------------------------------------------------------------*/ + + /** + * Adds support for Underscore style chaining to the `source`. + * + * @private + * @param {String} source The source to process. + * @returns {String} Returns the modified source. + */ + function addChainMethods(source) { + // add `_.chain` + source = source.replace(matchFunction(source, 'tap'), function(match) { + return [ + '', + ' /**', + ' * Creates a `lodash` object that wraps the given `value`.', + ' *', + ' * @static', + ' * @memberOf _', + ' * @category Chaining', + ' * @param {Mixed} value The value to wrap.', + ' * @returns {Object} Returns the wrapper object.', + ' * @example', + ' *', + ' * var stooges = [', + " * { 'name': 'moe', 'age': 40 },", + " * { 'name': 'larry', 'age': 50 },", + " * { 'name': 'curly', 'age': 60 }", + ' * ];', + ' *', + ' * var youngest = _.chain(stooges)', + ' * .sortBy(function(stooge) { return stooge.age; })', + " * .map(function(stooge) { return stooge.name + ' is ' + stooge.age; })", + ' * .first();', + " * // => 'moe is 40'", + ' */', + ' function chain(value) {', + ' value = new lodash(value);', + ' value.__chain__ = true;', + ' return value;', + ' }', + '', + match + ].join('\n'); + }); + + // add `wrapperChain` + source = source.replace(matchFunction(source, 'wrapperToString'), function(match) { + return [ + '', + ' /**', + ' * Enables method chaining on the wrapper object.', + ' *', + ' * @name chain', + ' * @memberOf _', + ' * @category Chaining', + ' * @returns {Mixed} Returns the wrapper object.', + ' * @example', + ' *', + ' * var sum = _([1, 2, 3])', + ' * .chain()', + ' * .reduce(function(sum, num) { return sum + num; })', + ' * .value()', + ' * // => 6`', + ' */', + ' function wrapperChain() {', + ' this.__chain__ = true;', + ' return this;', + ' }', + '', + match + ].join('\n'); + }); + + // add `lodash.chain` assignment + source = source.replace(getMethodAssignments(source), function(match) { + return match.replace(/^(?: *\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/\n)?( *)lodash\.VERSION *=/m, '$1lodash.chain = chain;\n\n$&'); + }); + + // add `lodash.prototype.chain` assignment + source = source.replace(/^( *)lodash\.prototype\.value *=.+\n/m, '$1lodash.prototype.chain = wrapperChain;\n$&'); + + // remove `lodash.prototype.toString` and `lodash.prototype.valueOf` assignments + source = source.replace(/^ *lodash\.prototype\.(?:toString|valueOf) *=.+\n/gm, ''); + + // remove `lodash.prototype` batch method assignments + source = source.replace(/(?:\s*\/\/.*)*\n( *)forOwn\(lodash, *function\(func, *methodName\)[\s\S]+?\n\1}.+/g, ''); + + // move `mixin(lodash)` to after the method assignments + source = source.replace(/(?:\s*\/\/.*)*\s*mixin\(lodash\).+/, ''); + source = source.replace(getMethodAssignments(source), function(match) { + return match + [ + '', + '', + ' // add functions to `lodash.prototype`', + ' mixin(lodash);' + ].join('\n'); + }); + + // add `__chain__` checks to `_.mixin` + source = source.replace(matchFunction(source, 'mixin'), function(match) { + return match.replace(/^( *)return new lodash.+/m, function() { + var indent = arguments[1]; + return indent + [ + '', + 'var result = func.apply(lodash, args);', + 'if (this.__chain__) {', + ' result = new lodash(result);', + ' result.__chain__ = true;', + '}', + 'return result;' + ].join('\n' + indent); + }); + }); + + // replace wrapper `Array` method assignments + source = source.replace(/^(?: *\/\/.*\n)*( *)each\(\['[\s\S]+?\n\1}$/m, function() { + return [ + ' // add `Array` mutator functions to the wrapper', + " each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {", + ' var func = arrayRef[methodName];', + ' lodash.prototype[methodName] = function() {', + ' var value = this.__wrapped__;', + ' func.apply(value, arguments);', + '', + ' // avoid array-like object bugs with `Array#shift` and `Array#splice`', + ' // in Firefox < 10 and IE < 9', + ' if (hasObjectSpliceBug && value.length === 0) {', + ' delete value[0];', + ' }', + ' return this;', + ' };', + ' });', + '', + ' // add `Array` accessor functions to the wrapper', + " each(['concat', 'join', 'slice'], function(methodName) {", + ' var func = arrayRef[methodName];', + ' lodash.prototype[methodName] = function() {', + ' var value = this.__wrapped__,', + ' result = func.apply(value, arguments);', + '', + ' if (this.__chain__) {', + ' result = new lodash(result);', + ' result.__chain__ = true;', + ' }', + ' return result;', + ' };', + ' });' + ].join('\n'); + }); + + return source; + } + + /** + * Adds build `commands` to the copyright/license header of the `source`. + * + * @private + * @param {String} source The source to process. + * @param {Array} [commands=[]] An array of commands. + * @returns {String} Returns the modified source. + */ + function addCommandsToHeader(source, commands) { + return source.replace(/(\/\**\n)( \*)( *@license[\s*]+)( *Lo-Dash [\w.-]+)(.*)/, function() { + // remove `node path/to/build.js` from `commands` + if (commands[0] == 'node') { + commands.splice(0, 2); + } + // add quotes to commands with spaces or equals signs + commands = _.map(commands, function(command) { + var separator = (command.match(/[= ]/) || [''])[0]; + if (separator) { + var pair = command.split(separator); + command = pair[0] + separator + '"' + pair[1] + '"'; + } + // escape newlines, carriage returns, multi-line comment end tokens + command = command + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + .replace(/\*\//g, '*\\/'); + + return command; + }); + // add build commands to copyright/license header + var parts = slice.call(arguments, 1); + return ( + parts[0] + + parts[1] + + parts[2] + parts[3] + ' (Custom Build)' + parts[4] + '\n' + + parts[1] + ' Build: `lodash ' + commands.join(' ') + '`' + ); + }); + } + + /** + * Compiles template files matched by the given file path `pattern` into a + * single source, extending `_.templates` with precompiled templates named after + * each template file's basename. + * + * @private + * @param {String} [pattern='/*.jst'] The file path pattern. + * @param {Object} options The options object. + * @returns {String} Returns the compiled source. + */ + function buildTemplate(pattern, options) { + pattern || (pattern = path.join(cwd, '*.jst')); + + var directory = path.dirname(pattern); + + var source = [ + ';(function(window) {', + " var freeExports = typeof exports == 'object' && exports;", + '', + " var freeModule = typeof module == 'object' && module && module.exports == freeExports && module;", + '', + " var freeGlobal = typeof global == 'object' && global;", + ' if (freeGlobal.global === freeGlobal) {', + ' window = freeGlobal;', + ' }', + '', + ' var templates = {},', + ' _ = window._;', + '' + ]; + + // convert to a regexp + pattern = RegExp( + path.basename(pattern) + .replace(/[.+?^=!:${}()|[\]\/\\]/g, '\\$&') + .replace(/\*/g, '.*?') + '$' + ); + + fs.readdirSync(directory).forEach(function(filename) { + var filePath = path.join(directory, filename); + if (pattern.test(filename)) { + var text = fs.readFileSync(filePath, 'utf8'), + precompiled = getFunctionSource(_.template(text, null, options)), + prop = filename.replace(/\..*$/, ''); + + source.push(" templates['" + prop.replace(/['\n\r\t]/g, '\\$&') + "'] = " + precompiled + ';', ''); + } + }); + + source.push( + " if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {", + " define(['" + options.moduleId + "'], function(lodash) {", + ' _ = lodash;', + ' lodash.templates = lodash.extend(lodash.templates || {}, templates);', + ' });', + " } else if (freeExports) {", + " if (freeModule) {", + ' (freeModule.exports = templates).templates = templates;', + ' } else {', + ' freeExports.templates = templates;', + ' }', + ' } else if (_) {', + ' _.templates = _.extend(_.templates || {}, templates);', + ' }', + '}(this));' + ); + + return source.join('\n'); + } + + /** + * Capitalizes a given string. + * + * @private + * @param {String} string The string to capitalize. + * @returns {String} Returns the capitalized string. + */ + function capitalize(string) { + return string[0].toUpperCase() + string.toLowerCase().slice(1); + } + + /** + * Removes unnecessary comments, whitespace, and pseudo private properties. + * + * @private + * @param {String} source The source to process. + * @returns {String} Returns the modified source. + */ + function cleanupSource(source) { + return source + // remove pseudo private properties + .replace(/(?:(?:\s*\/\/.*)*\s*lodash\._[^=]+=.+\n)+/g, '\n') + // remove lines with just whitespace and semicolons + .replace(/^ *;\n/gm, '') + // consolidate multiple newlines + .replace(/\n{3,}/g, '\n\n') + // consolidate consecutive horizontal rule comment separators + .replace(/(?:\s*\/\*-+\*\/\s*){2,}/g, function(separators) { + return separators.match(/^\s*/)[0] + separators.slice(separators.lastIndexOf('/*')); + }); + } + + /** + * Writes the help message to standard output. + * + * @private + */ + function displayHelp() { + console.log([ + '', + ' Commands:', + '', + ' lodash backbone Build with only methods required by Backbone', + ' lodash csp Build supporting default Content Security Policy restrictions', + ' lodash legacy Build tailored for older environments without ES5 support', + ' lodash modern Build tailored for newer environments with ES5 support', + ' lodash mobile Build without method compilation and most bug fixes for old browsers', + ' lodash strict Build with `_.assign`, `_.bindAll`, & `_.defaults` in strict mode', + ' lodash underscore Build tailored for projects already using Underscore', + ' lodash include=... Comma separated method/category names to include in the build', + ' lodash minus=... Comma separated method/category names to remove from those included in the build', + ' lodash plus=... Comma separated method/category names to add to those included in the build', + ' lodash category=... Comma separated categories of methods to include in the build (case-insensitive)', + ' (i.e. “arrays”, “chaining”, “collections”, “functions”, “objects”, and “utilities”)', + ' lodash exports=... Comma separated names of ways to export the `lodash` function', + ' (i.e. “amd”, “commonjs”, “global”, “node”, and “none”)', + ' lodash iife=... Code to replace the immediately-invoked function expression that wraps Lo-Dash', + ' (e.g. `lodash iife="!function(window,undefined){%output%}(this)"`)', + '', + ' lodash template=... File path pattern used to match template files to precompile', + ' (e.g. `lodash template=./*.jst`)', + ' lodash settings=... Template settings used when precompiling templates', + ' (e.g. `lodash settings="{interpolate:/{{([\\s\\S]+?)}}/g}"`)', + ' lodash moduleId=... The AMD module ID of Lo-Dash, which defaults to “lodash”, used by precompiled templates', + '', + ' All arguments, except `legacy` with `csp`, `mobile`, `modern`, or `underscore`, may be combined.', + ' Unless specified by `-o` or `--output`, all files created are saved to the current working directory.', + '', + ' Options:', + '', + ' -c, --stdout Write output to standard output', + ' -d, --debug Write only the non-minified development output', + ' -h, --help Display help information', + ' -m, --minify Write only the minified production output', + ' -o, --output Write output to a given path/filename', + ' -p, --source-map Generate a source map for the minified output, using an optional source map URL', + ' -s, --silent Skip status updates normally logged to the console', + ' -V, --version Output current version of Lo-Dash', + '' + ].join('\n')); + } + + /** + * Gets the aliases associated with a given function name. + * + * @private + * @param {String} methodName The name of the method to get aliases for. + * @returns {Array} Returns an array of aliases. + */ + function getAliases(methodName) { + return realToAliasMap[methodName] || []; + } + + /** + * Gets the category of the given method name. + * + * @private + * @param {String} source The source to inspect. + * @param {String} methodName The method name. + * @returns {String} Returns the method name's category. + */ + function getCategory(source, methodName) { + var result = /@category +(\w+)/.exec(matchFunction(source, methodName)); + return result ? result[1] : ''; + } + + /** + * Gets an array of category dependencies for a given category. + * + * @private + * @param {String} source The source to inspect. + * @param {String} category The category. + * @returns {Array} Returns an array of cetegory dependants. + */ + function getCategoryDependencies(source, category) { + var methods = _.uniq(getMethodsByCategory(source, category).reduce(function(result, methodName) { + push.apply(result, getDependencies(methodName)); + return result; + }, [])); + + var categories = _.uniq(methods.map(function(methodName) { + return getCategory(source, methodName); + })); + + return categories.filter(function(other) { + return other != category; + }); + } + + /** + * Gets an array of depenants for a method by a given name. + * + * @private + * @param {String} methodName The method name. + * @returns {Array} Returns an array of method dependants. + */ + function getDependants(methodName) { + // iterate over the `dependencyMap`, adding the names of methods that + // have `methodName` as a dependency + return _.reduce(dependencyMap, function(result, dependencies, otherName) { + if (_.contains(dependencies, methodName)) { + result.push(otherName); + } + return result; + }, []); + } + + /** + * Gets an array of dependencies for a given method name. If passed an array + * of dependencies it will return an array containing the given dependencies + * plus any additional detected sub-dependencies. + * + * @private + * @param {Array|String} methodName A single method name or array of + * dependencies to query. + * @returns {Array} Returns an array of method dependencies. + */ + function getDependencies(methodName) { + var dependencies = Array.isArray(methodName) ? methodName : dependencyMap[methodName]; + if (!dependencies) { + return []; + } + // recursively accumulate the dependencies of the `methodName` function, and + // the dependencies of its dependencies, and so on + return _.uniq(dependencies.reduce(function(result, otherName) { + result.push.apply(result, getDependencies(otherName).concat(otherName)); + return result; + }, [])); + } + + /** + * Gets the formatted source of the given function. + * + * @private + * @param {Function} func The function to process. + * @returns {String} Returns the formatted source. + */ + function getFunctionSource(func) { + var source = func.source || (func + ''); + + // format leading whitespace + return source.replace(/\n(?:.*)/g, function(match, index) { + match = match.slice(1); + return ( + match == '}' && source.indexOf('}', index + 2) < 0 ? '\n ' : '\n ' + ) + match; + }); + } + + /** + * Gets the `_.isArguments` fallback from `source`. + * + * @private + * @param {String} source The source to inspect. + * @returns {String} Returns the `isArguments` fallback. + */ + function getIsArgumentsFallback(source) { + return (source.match(/(?:\s*\/\/.*)*\n( *)if *\((?:noArgsClass|!isArguments)[\s\S]+?};\n\1}/) || [''])[0]; + } + + /** + * Gets the `_.isFunction` fallback from `source`. + * + * @private + * @param {String} source The source to inspect. + * @returns {String} Returns the `isFunction` fallback. + */ + function getIsFunctionFallback(source) { + return (source.match(/(?:\s*\/\/.*)*\n( *)if *\(isFunction\(\/x\/[\s\S]+?};\n\1}/) || [''])[0]; + } + + /** + * Gets the `iteratorTemplate` from `source`. + * + * @private + * @param {String} source The source to inspect. + * @returns {String} Returns the `iteratorTemplate`. + */ + function getIteratorTemplate(source) { + return (source.match(/^( *)var iteratorTemplate *= *[\s\S]+?\n\1.+?;\n/m) || [''])[0]; + } + + /** + * Gets the Lo-Dash method assignments snippet from `source`. + * + * @private + * @param {String} source The source to inspect. + * @returns {String} Returns the method assignments snippet. + */ + function getMethodAssignments(source) { + return (source.match(/\/\*-+\*\/\n(?:\s*\/\/.*)*\s*lodash\.\w+ *=[\s\S]+?lodash\.VERSION *=.+/) || [''])[0]; + } + + /** + * Gets the names of methods in `source` belonging to the given `category`. + * + * @private + * @param {String} source The source to inspect. + * @param {String} category The category to filter by. + * @returns {Array} Returns a new array of method names belonging to the given category. + */ + function getMethodsByCategory(source, category) { + return allMethods.filter(function(methodName) { + return getCategory(source, methodName) == category; + }); + } + + /** + * Gets the real name, not alias, of a given method name. + * + * @private + * @param {String} methodName The name of the method to resolve. + * @returns {String} Returns the real method name. + */ + function getRealName(methodName) { + return aliasToRealMap[methodName] || methodName; + } + + /** + * Determines if all functions of the given names have been removed from `source`. + * + * @private + * @param {String} source The source to inspect. + * @param {String} [funcName1, funcName2, ...] The names of functions to check. + * @returns {Boolean} Returns `true` if all functions have been removed, else `false`. + */ + function isRemoved(source) { + return slice.call(arguments, 1).every(function(funcName) { + return !matchFunction(source, funcName); + }); + } + + /** + * Searches `source` for a `funcName` function declaration, expression, or + * assignment and returns the matched snippet. + * + * @private + * @param {String} source The source to inspect. + * @param {String} funcName The name of the function to match. + * @returns {String} Returns the matched function snippet. + */ + function matchFunction(source, funcName) { + var result = source.match(RegExp( + // match multi-line comment block (could be on a single line) + '(?:\\n +/\\*[^*]*\\*+(?:[^/][^*]*\\*+)*/\\n)?' + + // begin non-capturing group + '( *)(?:' + + // match a function declaration + 'function ' + funcName + '\\b[\\s\\S]+?\\n\\1}|' + + // match a variable declaration with function expression + 'var ' + funcName + ' *=.*?function[\\s\\S]+?\\n\\1};' + + // end non-capturing group + ')\\n' + )); + + // match variables that are explicitly defined as functions + result || (result = source.match(RegExp( + // match multi-line comment block + '(?:\\n +/\\*[^*]*\\*+(?:[^/][^*]*\\*+)*/)?\\n' + + // match simple variable declarations and those with `createIterator` + ' *var ' + funcName + ' *=(?:.+?|.*?createIterator\\([\\s\\S]+?\\));\\n' + ))); + + return /@type +Function|function\s*\w*\(/.test(result) ? result[0] : ''; + } + + /** + * Converts a comma separated options string into an array. + * + * @private + * @param {String} value The option to convert. + * @returns {Array} Returns the new converted array. + */ + function optionToArray(value) { + return value.match(/\w+=(.*)$/)[1].split(/, */); + } + + /** + * Converts a comma separated options string into an array containing + * only real method names. + * + * @private + * @param {String} source The source to inspect. + * @param {String} value The option to convert. + * @returns {Array} Returns the new converted array. + */ + function optionToMethodsArray(source, value) { + var methodNames = optionToArray(value); + + // convert categories to method names + methodNames.forEach(function(category) { + push.apply(methodNames, getMethodsByCategory(source, category)); + }); + + // convert aliases to real method names + methodNames = methodNames.map(getRealName); + + // remove nonexistent and duplicate method names + return _.uniq(_.intersection(allMethods, methodNames)); + } + + /** + * Removes all `argsAreObjects` references from `source`. + * + * @private + * @param {String} source The source to process. + * @returns {String} Returns the modified source. + */ + function removeArgsAreObjects(source) { + source = removeVar(source, 'argsAreObjects'); + + // remove `argsAreObjects` from `_.isArray` + source = source.replace(matchFunction(source, 'isArray'), function(match) { + return match.replace(/\(argsAreObjects && *([^)]+)\)/g, '$1'); + }); + + // remove `argsAreObjects` from `_.isEqual` + source = source.replace(matchFunction(source, 'isEqual'), function(match) { + return match.replace(/!argsAreObjects[^:]+:\s*/g, ''); + }); + + return source; + } + + /** + * Removes the all references to `varName` from `createIterator` in `source`. + * + * @private + * @param {String} source The source to process. + * @param {String} varName The name of the variable to remove. + * @returns {String} Returns the modified source. + */ + function removeFromCreateIterator(source, varName) { + var snippet = matchFunction(source, 'createIterator'); + if ( snippet) { + // remove data object property assignment + var modified = snippet.replace(RegExp("^ *'" + varName + "': *" + varName + '.+\\n', 'm'), ''); + source = source.replace(snippet, modified); + + // clip at the `factory` assignment + snippet = modified.match(/Function\([\s\S]+$/)[0]; + + modified = snippet + .replace(RegExp('\\b' + varName + '\\b,? *', 'g'), '') + .replace(/, *',/, "',") + .replace(/,\s*\)/, ')') + + source = source.replace(snippet, modified); + } + return source; + } + + /** + * Removes the `funcName` function declaration, expression, or assignment and + * associated code from `source`. + * + * @private + * @param {String} source The source to process. + * @param {String} funcName The name of the function to remove. + * @returns {String} Returns the modified source. + */ + function removeFunction(source, funcName) { + // remove function + var snippet = matchFunction(source, funcName); + if (snippet) { + source = source.replace(snippet, ''); + } + // grab the method assignments snippet + snippet = getMethodAssignments(source); + + // remove assignment and aliases + var modified = getAliases(funcName).concat(funcName).reduce(function(result, otherName) { + return result.replace(RegExp('(?:\\n *//.*\\s*)* *lodash\\.' + otherName + ' *= *.+\\n'), ''); + }, snippet); + + // replace with the modified snippet + source = source.replace(snippet, modified); + + return removeFromCreateIterator(source, funcName); + } + + /** + * Removes all `hasDontEnumBug` references from `source`. + * + * @private + * @param {String} source The source to process. + * @returns {String} Returns the modified source. + */ + function removeHasDontEnumBug(source) { + source = removeFromCreateIterator(source, 'hasDontEnumBug'); + source = removeFromCreateIterator(source, 'shadowed'); + + // remove `hasDontEnumBug` declaration and assignment + source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var hasDontEnumBug\b.*|.+?hasDontEnumBug *=.+/g, ''); + + // remove `shadowed` variable + source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var shadowed[\s\S]+?;\n/, ''); + + // remove `hasDontEnumBug` from `iteratorTemplate` + source = source.replace(getIteratorTemplate(source), function(match) { + return match.replace(/(?: *\/\/.*\n)* *["']( *)<% *if *\(hasDontEnumBug[\s\S]+?["']\1<% *} *%>.+/, ''); + }); + + return source; + } + + /** + * Removes all `hasEnumPrototype` references from `source`. + * + * @private + * @param {String} source The source to process. + * @returns {String} Returns the modified source. + */ + function removeHasEnumPrototype(source) { + source = removeFromCreateIterator(source, 'hasEnumPrototype'); + + // remove `hasEnumPrototype` declaration and assignment + source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var hasEnumPrototype\b.*|.+?hasEnumPrototype *=.+/g, ''); + + // remove `hasEnumPrototype` from `_.keys` + source = source.replace(matchFunction(source, 'keys'), function(match) { + return match + .replace(/\(hasEnumPrototype[^)]+\)(?:\s*\|\|\s*)?/, '') + .replace(/\s*if *\(\s*\)[^}]+}/, ''); + }); + + // remove `hasEnumPrototype` from `iteratorTemplate` + source = source.replace(getIteratorTemplate(source), function(match) { + return match + .replace(/(?: *\/\/.*\n)* *["'] *(?:<% *)?if *\(hasEnumPrototype *(?:&&|\))[\s\S]+?<% *} *(?:%>|["']).+/g, '') + .replace(/hasEnumPrototype *\|\|\s*/g, ''); + }); + + return source; + } + + /** + * Removes the `_.isArguments` fallback from `source`. + * + * @private + * @param {String} source The source to process. + * @returns {String} Returns the modified source. + */ + function removeIsArgumentsFallback(source) { + return source.replace(getIsArgumentsFallback(source), ''); + } + + /** + * Removes the `_.isFunction` fallback from `source`. + * + * @private + * @param {String} source The source to process. + * @returns {String} Returns the modified source. + */ + function removeIsFunctionFallback(source) { + return source.replace(getIsFunctionFallback(source), ''); + } + + /** + * Removes all `iteratesOwnLast` references from `source`. + * + * @private + * @param {String} source The source to process. + * @returns {String} Returns the modified source. + */ + function removeIteratesOwnLast(source) { + // remove `iteratesOwnLast` declaration and assignment + source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var iteratesOwnLast\b.*|.+?iteratesOwnLast *=.+/g, ''); + + // remove `iteratesOwnLast` from `shimIsPlainObject` + source = source.replace(matchFunction(source, 'shimIsPlainObject'), function(match) { + return match.replace(/(?:\s*\/\/.*)*\n( *)if *\(iteratesOwnLast[\s\S]+?\n\1}/, ''); + }); + + return source; + } + + /** + * Removes the `Object.keys` object iteration optimization from `source`. + * + * @private + * @param {String} source The source to process. + * @returns {String} Returns the modified source. + */ + function removeKeysOptimization(source) { + source = removeVar(source, 'isKeysFast'); + + // remove optimized branch in `iteratorTemplate` + source = source.replace(getIteratorTemplate(source), function(match) { + return match.replace(/(?: *\/\/.*\n)* *["']( *)<% *if *\(isKeysFast[\s\S]+?["']\1<% *} *else *{ *%>.+\n([\s\S]+?) *["']\1<% *} *%>.+/, "'\\n' +\n$2"); + }); + + return source; + } + + /** + * Removes all `noArgsClass` references from `source`. + * + * @private + * @param {String} source The source to process. + * @returns {String} Returns the modified source. + */ + function removeNoArgsClass(source) { + source = removeVar(source, 'noArgsClass'); + + // replace `noArgsClass` in the `_.isArguments` fallback + source = source.replace(getIsArgumentsFallback(source), function(match) { + return match.replace(/noArgsClass/g, '!isArguments(arguments)'); + }); + + // remove `noArgsClass` from `_.isEmpty` + source = source.replace(matchFunction(source, 'isEmpty'), function(match) { + return match.replace(/ *\|\|\s*\(noArgsClass *&&[^)]+?\)\)/g, ''); + }); + + return source; + } + + /** + * Removes all `noCharByIndex` references from `source`. + * + * @private + * @param {String} source The source to process. + * @returns {String} Returns the modified source. + */ + function removeNoCharByIndex(source) { + source = removeVar(source, 'noCharByIndex'); + + // remove `noCharByIndex` from `_.at` + source = source.replace(matchFunction(source, 'at'), function(match) { + return match.replace(/^ *if *\(noCharByIndex[^}]+}\n/m, ''); + }); + + // remove `noCharByIndex` from `_.reduceRight` + source = source.replace(matchFunction(source, 'reduceRight'), function(match) { + return match.replace(/}\s*else if *\(noCharByIndex[^}]+/, ''); + }); + + // remove `noCharByIndex` from `_.toArray` + source = source.replace(matchFunction(source, 'toArray'), function(match) { + return match.replace(/noCharByIndex[^:]+:/, ''); + }); + + // `noCharByIndex` from `iteratorTemplate` + source = source.replace(getIteratorTemplate(source), function(match) { + return match + .replace(/'if *\(<%= *arrays *%>[^']*/, '$&\\n') + .replace(/(?: *\/\/.*\n)* *["']( *)<% *if *\(noCharByIndex[\s\S]+?["']\1<% *} *%>.+/, ''); + }); + + return source; + } + + /** + * Removes all `nonEnumArgs` references from `source`. + * + * @private + * @param {String} source The source to process. + * @returns {String} Returns the modified source. + */ + function removeNonEnumArgs(source) { + source = removeFromCreateIterator(source, 'nonEnumArgs'); + + // remove `nonEnumArgs` declaration and assignment + source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *var nonEnumArgs\b.*|.+?nonEnumArgs *=.+/g, ''); + + // remove `nonEnumArgs` from `_.keys` + source = source.replace(matchFunction(source, 'keys'), function(match) { + return match + .replace(/(?:\s*\|\|\s*)?\(nonEnumArgs[^)]+\)\)/, '') + .replace(/\s*if *\(\s*\)[^}]+}/, ''); + }); + + // remove `nonEnumArgs` from `iteratorTemplate` + source = source.replace(getIteratorTemplate(source), function(match) { + return match + .replace(/(?: *\/\/.*\n)*( *["'] *)<% *} *else *if *\(nonEnumArgs[\s\S]+?(\1<% *} *%>.+)/, '$2') + .replace(/ *\|\|\s*nonEnumArgs/, ''); + }); + + return source; + } + + /** + * Removes all `noNodeClass` references from `source`. + * + * @private + * @param {String} source The source to process. + * @returns {String} Returns the modified source. + */ + function removeNoNodeClass(source) { + // remove `noNodeClass` assignment + source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *try *{(?:\s*\/\/.*)*\n *var noNodeClass[\s\S]+?catch[^}]+}\n/, ''); + + // remove `noNodeClass` from `shimIsPlainObject` + source = source.replace(matchFunction(source, 'shimIsPlainObject'), function(match) { + return match.replace(/ *&& *\(!noNodeClass[\s\S]+?\)\)/, ''); + }); + + // remove `noNodeClass` from `_.clone` + source = source.replace(matchFunction(source, 'clone'), function(match) { + return match.replace(/ *\|\|\s*\(noNodeClass[\s\S]+?\)\)/, ''); + }); + + // remove `noNodeClass` from `_.isEqual` + source = source.replace(matchFunction(source, 'isEqual'), function(match) { + return match.replace(/ *\|\|\s*\(noNodeClass[\s\S]+?\)\)\)/, ''); + }); + + return source; + } + + /** + * Removes all `hasObjectSpliceByg` references from `source`. + * + * @private + * @param {String} source The source to process. + * @returns {String} Returns the modified source. + */ + function removeHasObjectSpliceBug(source) { + return removeVar(source, 'hasObjectSpliceBug') + // remove `hasObjectSpliceBug` fix from the `Array` function mixins + .replace(/(?:\s*\/\/.*)*\n( *)if *\(hasObjectSpliceBug[\s\S]+?(?:{\s*}|\n\1})/, ''); + } + + /** + * Removes the `setImmediate` fork of `_.defer`. + * + * @private + * @param {String} source The source to process. + * @returns {String} Returns the modified source. + */ + function removeSetImmediate(source) { + return source.replace(/(?:\s*\/\/.*)*\n( *)if *\(isV8 *&& *freeModule[\s\S]+?\n\1}/, ''); + } + + /** + * Removes a given variable from `source`. + * + * @private + * @param {String} source The source to process. + * @param {String} varName The name of the variable to remove. + * @returns {String} Returns the modified source. + */ + function removeVar(source, varName) { + // simplify `cloneableClasses`, `ctorByClass`, or `hasObjectSpliceBug` + if (/^(?:cloneableClasses|ctorByClass|hasObjectSpliceBug)$/.test(varName)) { + source = source.replace(RegExp('(var ' + varName + ' *=)[\\s\\S]+?\\n\\n'), '$1=null;\n\n'); + } + source = source.replace(RegExp( + // match multi-line comment block + '(?:\\n +/\\*[^*]*\\*+(?:[^/][^*]*\\*+)*/)?\\n' + + // match a variable declaration that's not part of a declaration list + '( *)var ' + varName + ' *= *(?:.+?(?:;|&&\\n[^;]+;)|(?:\\w+\\(|{)[\\s\\S]+?\\n\\1.+?;)\\n|' + + // match a variable in a declaration list + '\\n +' + varName + ' *=.+?,' + ), ''); + + // remove a varaible at the start of a variable declaration list + source = source.replace(RegExp('(var +)' + varName + ' *=.+?,\\s+'), '$1'); + + // remove a variable at the end of a variable declaration list + source = source.replace(RegExp(',\\s*' + varName + ' *=.+?;'), ';'); + + return removeFromCreateIterator(source, varName); + } + + /** + * Replaces the `funcName` function body in `source` with `funcValue`. + * + * @private + * @param {String} source The source to inspect. + * @param {String} varName The name of the function to replace. + * @returns {String} Returns the modified source. + */ + function replaceFunction(source, funcName, funcValue) { + var match = matchFunction(source, funcName); + if (match) { + // clip snippet after the JSDoc comment block + match = match.replace(/^\s*(?:\/\/.*|\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)\n/, ''); + source = source.replace(match, function() { + return funcValue.trimRight() + '\n'; + }); + } + return source; + } + + /** + * Replaces the `varName` variable declaration value in `source` with `varValue`. + * + * @private + * @param {String} source The source to inspect. + * @param {String} varName The name of the variable to replace. + * @returns {String} Returns the modified source. + */ + function replaceVar(source, varName, varValue) { + // replace a variable that's not part of a declaration list + var result = source.replace(RegExp( + '(( *)var ' + varName + ' *= *)' + + '(?:.+?;|(?:Function\\(.+?|.*?[^,])\\n[\\s\\S]+?\\n\\2.+?;)\\n' + ), function(match, captured) { + return captured + varValue + ';\n'; + }); + + if (source == result) { + // replace a varaible at the start or middle of a declaration list + result = source.replace(RegExp('((?:var|\\n) +' + varName + ' *=).+?,'), function(match, captured) { + return captured + ' ' + varValue + ','; + }); + } + if (source == result) { + // replace a variable at the end of a variable declaration list + result = source.replace(RegExp('(,\\s*' + varName + ' *=).+?;'), function(match, captured) { + return captured + ' ' + varValue + ';'; + }); + } + return result; + } + + /** + * Hard-codes the `strict` template option value for `iteratorTemplate`. + * + * @private + * @param {String} source The source to process. + * @param {Boolean} value The value to set. + * @returns {String} Returns the modified source. + */ + function setUseStrictOption(source, value) { + // inject or remove the "use strict" directive + source = source.replace(/^([\s\S]*?function[^{]+{)(?:\s*'use strict';)?/, '$1' + (value ? "\n 'use strict';" : '')); + + // replace `strict` branch in `iteratorTemplate` with hard-coded option + source = source.replace(getIteratorTemplate(source), function(match) { + return match.replace(/(template\()(?:\s*"'use strict.+)?/, '$1' + (value ? '\n "\'use strict\';\\n" +' : '')); + }); + + return source; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a debug and/or minified build, executing the `callback` for each. + * The `callback` is invoked with two arguments; (filePath, outputSource). + * + * Note: For a list of commands see `displayHelp()` or run `lodash --help`. + * + * @param {Array} [options=[]] An array of commands. + * @param {Function} callback The function called per build. + */ + function build(options, callback) { + options || (options = []); + + // the debug version of `source` + var debugSource; + + // used to specify the source map URL + var sourceMapURL; + + // used to report invalid command-line arguments + var invalidArgs = _.reject(options.slice(options[0] == 'node' ? 2 : 0), function(value, index, options) { + if (/^(?:-o|--output)$/.test(options[index - 1]) || + /^(?:category|exclude|exports|iife|include|moduleId|minus|plus|settings|template)=.*$/.test(value)) { + return true; + } + var result = [ + 'backbone', + 'csp', + 'legacy', + 'mobile', + 'modern', + 'modularize', + 'strict', + 'underscore', + '-c', '--stdout', + '-d', '--debug', + '-h', '--help', + '-m', '--minify', + '-o', '--output', + '-p', '--source-map', + '-s', '--silent', + '-V', '--version' + ].indexOf(value) > -1; + + if (!result && /^(?:-p|--source-map)$/.test(options[index - 1])) { + result = true; + sourceMapURL = value; + } + return result; + }); + + // report invalid arguments + if (invalidArgs.length) { + console.log( + '\n' + + 'Invalid argument' + (invalidArgs.length > 1 ? 's' : '') + + ' passed: ' + invalidArgs.join(', ') + ); + displayHelp(); + return; + } + + // display help message + if (_.find(options, function(arg) { + return /^(?:-h|--help)$/.test(arg); + })) { + displayHelp(); + return; + } + + // display `lodash.VERSION` + if (_.find(options, function(arg) { + return /^(?:-V|--version)$/.test(arg); + })) { + console.log(_.VERSION); + return; + } + + /*------------------------------------------------------------------------*/ + + // backup `dependencyMap` to restore later + var dependencyBackup = _.cloneDeep(dependencyMap); + + // used to specify a custom IIFE to wrap Lo-Dash + var iife = options.reduce(function(result, value) { + var match = value.match(/iife=(.*)/); + return match ? match[1] : result; + }, null); + + // the path to the source file + var filePath = path.join(__dirname, 'lodash.js'); + + // flag to specify a Backbone build + var isBackbone = options.indexOf('backbone') > -1; + + // flag to specify a Content Security Policy build + var isCSP = options.indexOf('csp') > -1 || options.indexOf('CSP') > -1; + + // flag to specify only creating the debug build + var isDebug = options.indexOf('-d') > -1 || options.indexOf('--debug') > -1; + + // flag to indicate that a custom IIFE was specified + var isIIFE = typeof iife == 'string'; + + // flag to specify creating a source map for the minified source + var isMapped = options.indexOf('-p') > -1 || options.indexOf('--source-map') > -1; + + // flag to specify only creating the minified build + var isMinify = options.indexOf('-m') > -1 || options.indexOf('--minify') > -1; + + // flag to specify a mobile build + var isMobile = isCSP || options.indexOf('mobile') > -1; + + // flag to specify a modern build + var isModern = isMobile || options.indexOf('modern') > -1; + + // flag to specify a modularize build + var isModularize = options.indexOf('modularize') > -1; + + // flag to specify writing output to standard output + var isStdOut = options.indexOf('-c') > -1 || options.indexOf('--stdout') > -1; + + // flag to specify skipping status updates normally logged to the console + var isSilent = isStdOut || options.indexOf('-s') > -1 || options.indexOf('--silent') > -1; + + // flag to specify `_.assign`, `_.bindAll`, and `_.defaults` are + // constructed using the "use strict" directive + var isStrict = options.indexOf('strict') > -1; + + // flag to specify an Underscore build + var isUnderscore = isBackbone || options.indexOf('underscore') > -1; + + // flag to specify a legacy build + var isLegacy = !(isModern || isUnderscore) && options.indexOf('legacy') > -1; + + // used to specify methods of specific categories + var categories = options.reduce(function(result, value) { + return /category/.test(value) ? optionToArray(value) : result; + }, []); + + // used to specify the ways to export the `lodash` function + var exportsOptions = options.reduce(function(result, value) { + return /exports/.test(value) ? optionToArray(value).sort() : result; + }, isUnderscore + ? ['commonjs', 'global', 'node'] + : exportsAll.slice() + ); + + // used to specify the AMD module ID of Lo-Dash used by precompiled templates + var moduleId = options.reduce(function(result, value) { + var match = value.match(/moduleId=(.*)/); + return match ? match[1] : result; + }, 'lodash'); + + // used to specify the output path for builds + var 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; + }, ''); + + // used to match external template files to precompile + var templatePattern = options.reduce(function(result, value) { + var match = value.match(/template=(.+)$/); + return match + ? path.join(fs.realpathSync(path.dirname(match[1])), path.basename(match[1])) + : result; + }, ''); + + // used when precompiling template files + var templateSettings = options.reduce(function(result, value) { + var match = value.match(/settings=(.+)$/); + return match + ? _.assign(result, Function('return {' + match[1].replace(/^{|}$/g, '') + '}')()) + : result; + }, _.assign(_.clone(_.templateSettings), { + 'moduleId': moduleId + })); + + // flag to specify a template build + var isTemplate = !!templatePattern; + + // the lodash.js source + var source = fs.readFileSync(filePath, 'utf8'); + + // flag to specify replacing Lo-Dash's `_.clone` with Underscore's + var useUnderscoreClone = isUnderscore; + + // flags to specify exposing Lo-Dash methods in an Underscore build + var exposeAssign = !isUnderscore, + exposeForIn = !isUnderscore, + exposeForOwn = !isUnderscore, + exposeIsPlainObject = !isUnderscore; + + // flags to specify export options + var isAMD = exportsOptions.indexOf('amd') > -1, + isCommonJS = exportsOptions.indexOf('commonjs') > -1, + isGlobal = exportsOptions.indexOf('global') > -1, + isNode = exportsOptions.indexOf('node') > -1; + + /*------------------------------------------------------------------------*/ + + // names of methods to include in the build + var buildMethods = !isTemplate && (function() { + var result; + + var includeMethods = options.reduce(function(accumulator, value) { + return /include/.test(value) + ? _.union(accumulator, optionToMethodsArray(source, value)) + : accumulator; + }, []); + + var minusMethods = options.reduce(function(accumulator, value) { + return /exclude|minus/.test(value) + ? _.union(accumulator, optionToMethodsArray(source, value)) + : accumulator; + }, []); + + var plusMethods = options.reduce(function(accumulator, value) { + return /plus/.test(value) + ? _.union(accumulator, optionToMethodsArray(source, value)) + : accumulator; + }, []); + + // set flags to include Lo-Dash's methods if explicitly requested + if (isUnderscore) { + var methods = _.without.apply(_, [_.union(includeMethods, plusMethods)].concat(minusMethods)); + exposeAssign = methods.indexOf('assign') > -1; + exposeForIn = methods.indexOf('forIn') > -1; + exposeForOwn = methods.indexOf('forOwn') > -1; + exposeIsPlainObject = methods.indexOf('isPlainObject') > -1; + + methods = _.without.apply(_, [plusMethods].concat(minusMethods)); + useUnderscoreClone = methods.indexOf('clone') < 0; + } + // update dependencies + if (isLegacy) { + dependencyMap.defer = _.without(dependencyMap.defer, 'bind'); + } + if (isUnderscore) { + dependencyMap.contains = _.without(dependencyMap.contains, 'isString'); + dependencyMap.countBy = _.without(dependencyMap.countBy, 'isEqual', 'keys'); + dependencyMap.every = _.without(dependencyMap.every, 'isEqual', 'keys'); + dependencyMap.filter = _.without(dependencyMap.filter, 'isEqual'); + dependencyMap.find = _.without(dependencyMap.find, 'isEqual', 'keys'); + dependencyMap.groupBy = _.without(dependencyMap.groupBy, 'isEqual', 'keys'); + dependencyMap.isEqual = _.without(dependencyMap.isEqual, 'forIn', 'isArguments'); + dependencyMap.isEmpty = ['isArray', 'isString']; + dependencyMap.map = _.without(dependencyMap.map, 'isEqual', 'keys'); + dependencyMap.max = _.without(dependencyMap.max, 'isEqual', 'isString', 'keys'); + dependencyMap.min = _.without(dependencyMap.min, 'isEqual', 'isString', 'keys'); + dependencyMap.pick = _.without(dependencyMap.pick, 'forIn', 'isObject'); + dependencyMap.reduce = _.without(dependencyMap.reduce, 'isEqual', 'keys'); + dependencyMap.reject = _.without(dependencyMap.reject, 'isEqual', 'keys'); + dependencyMap.some = _.without(dependencyMap.some, 'isEqual', 'keys'); + dependencyMap.sortBy = _.without(dependencyMap.sortBy, 'isEqual', 'keys'); + dependencyMap.sortedIndex = _.without(dependencyMap.sortedIndex, 'isEqual', 'keys'); + dependencyMap.template = _.without(dependencyMap.template, 'keys', 'values'); + dependencyMap.uniq = _.without(dependencyMap.uniq, 'isEqual', 'keys'); + dependencyMap.where.push('find', 'isEmpty'); + + if (useUnderscoreClone) { + dependencyMap.clone = _.without(dependencyMap.clone, 'forEach', 'forOwn'); + } + } + if (isModern || isUnderscore) { + dependencyMap.reduceRight = _.without(dependencyMap.reduceRight, 'isEqual', 'isString'); + } + + // add method names explicitly + if (includeMethods.length) { + result = getDependencies(includeMethods); + } + // add method names required by Backbone and Underscore builds + if (isBackbone && !result) { + result = getDependencies(backboneDependencies); + } + else if (isUnderscore && !result) { + result = getDependencies(underscoreMethods); + } + // add method names by category + if (categories.length) { + result = _.union(result || [], getDependencies(categories.reduce(function(accumulator, category) { + // resolve method names belonging to each category (case-insensitive) + return accumulator.concat(getMethodsByCategory(source, capitalize(category))); + }, []))); + } + if (!result) { + result = allMethods.slice(); + } + if (plusMethods.length) { + result = _.union(result, getDependencies(plusMethods)); + } + if (minusMethods.length) { + result = _.without.apply(_, [result].concat(minusMethods, getDependants(minusMethods))); + } + return result; + }()); + + /*------------------------------------------------------------------------*/ + + // load customized Lo-Dash module + var lodash = !isTemplate && (function() { + var context = vm.createContext({ + 'clearTimeout': clearTimeout, + 'console': console, + 'setTimeout': setTimeout + }); + + source = setUseStrictOption(source, isStrict); + + if (isLegacy) { + _.each(['getPrototypeOf', 'isBindFast', 'isKeysFast', 'nativeBind', 'nativeIsArray', 'nativeKeys'], function(varName) { + source = replaceVar(source, varName, 'false'); + }); + + source = replaceVar(source, 'noArgsClass', 'true'); + source = removeKeysOptimization(source); + } + if (isMobile || isUnderscore) { + source = removeKeysOptimization(source); + } + if (isModern || isUnderscore) { + source = removeHasDontEnumBug(source); + source = removeHasEnumPrototype(source); + source = removeIteratesOwnLast(source); + source = removeNoCharByIndex(source); + source = removeNoNodeClass(source); + + if (!isMobile) { + source = removeNonEnumArgs(source); + } + } + if (isModern) { + // remove `_.isPlainObject` fallback + source = source.replace(matchFunction(source, 'isPlainObject'), function(match) { + return match.replace(/!getPrototypeOf.+?: */, ''); + }); + } + if (isUnderscore) { + // replace `_.assign` + source = replaceFunction(source, 'assign', [ + ' function assign(object) {', + ' if (!object) {', + ' return object;', + ' }', + ' for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {', + ' var iterable = arguments[argsIndex];', + ' if (iterable) {', + ' for (var key in iterable) {', + ' object[key] = iterable[key];', + ' }', + ' }', + ' }', + ' return object;', + ' }' + ].join('\n')); + + // replace `_.clone` + if (useUnderscoreClone) { + source = replaceFunction(source, 'clone', [ + ' function clone(value) {', + ' return isObject(value)', + ' ? (isArray(value) ? slice(value) : assign({}, value))', + ' : value', + ' }' + ].join('\n')); + } + + // replace `_.contains` + source = replaceFunction(source, 'contains', [ + ' function contains(collection, target) {', + ' var length = collection ? collection.length : 0,', + ' result = false;', + " if (typeof length == 'number') {", + ' result = indexOf(collection, target) > -1;', + ' } else {', + ' each(collection, function(value) {', + ' return (result = value === target) && indicatorObject;', + ' });', + ' }', + ' return result;', + ' }' + ].join('\n')); + + // replace `_.defaults` + source = replaceFunction(source, 'defaults', [ + ' function defaults(object) {', + ' if (!object) {', + ' return object;', + ' }', + ' for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {', + ' var iterable = arguments[argsIndex];', + ' if (iterable) {', + ' for (var key in iterable) {', + ' if (object[key] == null) {', + ' object[key] = iterable[key];', + ' }', + ' }', + ' }', + ' }', + ' return object;', + ' }' + ].join('\n')); + + // replace `_.difference` + source = replaceFunction(source, 'difference', [ + ' function difference(array) {', + ' var index = -1,', + ' length = array.length,', + ' flattened = concat.apply(arrayRef, arguments),', + ' result = [];', + '', + ' while (++index < length) {', + ' var value = array[index]', + ' if (indexOf(flattened, value, length) < 0) {', + ' result.push(value);', + ' }', + ' }', + ' return result', + ' }' + ].join('\n')); + + // replace `_.intersection` + source = replaceFunction(source, 'intersection', [ + ' function intersection(array) {', + ' var args = arguments,', + ' argsLength = args.length,', + ' index = -1,', + ' length = array ? array.length : 0,', + ' result = [];', + '', + ' outer:', + ' while (++index < length) {', + ' var value = array[index];', + ' if (indexOf(result, value) < 0) {', + ' var argsIndex = argsLength;', + ' while (--argsIndex) {', + ' if (indexOf(args[argsIndex], value) < 0) {', + ' continue outer;', + ' }', + ' }', + ' result.push(value);', + ' }', + ' }', + ' return result;', + ' }' + ].join('\n')); + + // replace `_.isEmpty` + source = replaceFunction(source, 'isEmpty', [ + ' function isEmpty(value) {', + ' if (!value) {', + ' return true;', + ' }', + ' if (isArray(value) || isString(value)) {', + ' return !value.length;', + ' }', + ' for (var key in value) {', + ' if (hasOwnProperty.call(value, key)) {', + ' return false;', + ' }', + ' }', + ' return true;', + ' }' + ].join('\n')); + + // replace `_.isEqual` + source = replaceFunction(source, 'isEqual', [ + ' function isEqual(a, b, stackA, stackB) {', + ' if (a === b) {', + ' return a !== 0 || (1 / a == 1 / b);', + ' }', + ' var type = typeof a,', + ' otherType = typeof b;', + '', + ' if (a === a &&', + " (!a || (type != 'function' && type != 'object')) &&", + " (!b || (otherType != 'function' && otherType != 'object'))) {", + ' return false;', + ' }', + ' if (a == null || b == null) {', + ' return a === b;', + ' }', + ' var className = toString.call(a),', + ' otherClass = toString.call(b);', + '', + ' if (className != otherClass) {', + ' return false;', + ' }', + ' switch (className) {', + ' case boolClass:', + ' case dateClass:', + ' return +a == +b;', + '', + ' case numberClass:', + ' return a != +a', + ' ? b != +b', + ' : (a == 0 ? (1 / a == 1 / b) : a == +b);', + '', + ' case regexpClass:', + ' case stringClass:', + " return a == b + '';", + ' }', + ' var isArr = className == arrayClass;', + ' if (!isArr) {', + ' if (a.__wrapped__ || b.__wrapped__) {', + ' return isEqual(a.__wrapped__ || a, b.__wrapped__ || b, stackA, stackB);', + ' }', + ' if (className != objectClass) {', + ' return false;', + ' }', + ' var ctorA = a.constructor,', + ' ctorB = b.constructor;', + '', + ' if (ctorA != ctorB && !(', + ' isFunction(ctorA) && ctorA instanceof ctorA &&', + ' isFunction(ctorB) && ctorB instanceof ctorB', + ' )) {', + ' return false;', + ' }', + ' }', + ' stackA || (stackA = []);', + ' stackB || (stackB = []);', + '', + ' var length = stackA.length;', + ' while (length--) {', + ' if (stackA[length] == a) {', + ' return stackB[length] == b;', + ' }', + ' }', + ' var result = true,', + ' size = 0;', + '', + ' stackA.push(a);', + ' stackB.push(b);', + '', + ' if (isArr) {', + ' size = b.length;', + ' result = size == a.length;', + '', + ' if (result) {', + ' while (size--) {', + ' if (!(result = isEqual(a[size], b[size], stackA, stackB))) {', + ' break;', + ' }', + ' }', + ' }', + ' return result;', + ' }', + ' forIn(b, function(value, key, b) {', + ' if (hasOwnProperty.call(b, key)) {', + ' size++;', + ' return !(result = hasOwnProperty.call(a, key) && isEqual(a[key], value, stackA, stackB)) && indicatorObject;', + ' }', + ' });', + '', + ' if (result) {', + ' forIn(a, function(value, key, a) {', + ' if (hasOwnProperty.call(a, key)) {', + ' return !(result = --size > -1) && indicatorObject;', + ' }', + ' });', + ' }', + ' return result;', + ' }' + ].join('\n')); + + // replace `_.omit` + source = replaceFunction(source, 'omit', [ + ' function omit(object) {', + ' var props = concat.apply(arrayRef, arguments),', + ' result = {};', + '', + ' forIn(object, function(value, key) {', + ' if (indexOf(props, key, 1) < 0) {', + ' result[key] = value;', + ' }', + ' });', + ' return result;', + ' }' + ].join('\n')); + + // replace `_.pick` + source = replaceFunction(source, 'pick', [ + ' function pick(object) {', + ' var index = 0,', + ' props = concat.apply(arrayRef, arguments),', + ' length = props.length,', + ' result = {};', + '', + ' while (++index < length) {', + ' var prop = props[index];', + ' if (prop in object) {', + ' result[prop] = object[prop];', + ' }', + ' }', + ' return result;', + ' }' + ].join('\n')); + + // replace `_.result` + source = replaceFunction(source, 'result', [ + ' function result(object, property) {', + ' var value = object ? object[property] : null;', + ' return isFunction(value) ? object[property]() : value;', + ' }' + ].join('\n')); + + // replace `_.template` + source = replaceFunction(source, 'template', [ + ' function template(text, data, options) {', + " text || (text = '');", + ' options = defaults({}, options, lodash.templateSettings);', + '', + ' var index = 0,', + ' source = "__p += \'",', + ' variable = options.variable;', + '', + ' var reDelimiters = RegExp(', + " (options.escape || reNoMatch).source + '|' +", + " (options.interpolate || reNoMatch).source + '|' +", + " (options.evaluate || reNoMatch).source + '|$'", + " , 'g');", + '', + ' text.replace(reDelimiters, function(match, escapeValue, interpolateValue, evaluateValue, offset) {', + ' source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);', + ' if (escapeValue) {', + ' source += "\' +\\n_.escape(" + escapeValue + ") +\\n\'";', + ' }', + ' if (evaluateValue) {', + ' source += "\';\\n" + evaluateValue + ";\\n__p += \'";', + ' }', + ' if (interpolateValue) {', + ' source += "\' +\\n((__t = (" + interpolateValue + ")) == null ? \'\' : __t) +\\n\'";', + ' }', + ' index = offset + match.length;', + ' return match;', + ' });', + '', + ' source += "\';\\n";', + ' if (!variable) {', + " variable = 'obj';", + " source = 'with (' + variable + ' || {}) {\\n' + source + '\\n}\\n';", + ' }', + " source = 'function(' + variable + ') {\\n' +", + ' "var __t, __p = \'\', __j = Array.prototype.join;\\n" +', + ' "function print() { __p += __j.call(arguments, \'\') }\\n" +', + ' source +', + " 'return __p\\n}';", + '', + ' try {', + " var result = Function('_', 'return ' + source)(lodash);", + ' } catch(e) {', + ' e.source = source;', + ' throw e;', + ' }', + ' if (data) {', + ' return result(data);', + ' }', + ' result.source = source;', + ' return result;', + ' }' + ].join('\n')); + + // replace `_.uniq` + source = replaceFunction(source, 'uniq', [ + ' function uniq(array, isSorted, callback, thisArg) {', + ' var index = -1,', + ' length = array ? array.length : 0,', + ' result = [],', + ' seen = result;', + '', + " if (typeof isSorted == 'function') {", + ' thisArg = callback;', + ' callback = isSorted;', + ' isSorted = false;', + ' }', + ' if (callback) {', + ' seen = [];', + ' callback = createCallback(callback, thisArg);', + ' }', + ' while (++index < length) {', + ' var value = array[index],', + ' computed = callback ? callback(value, index, array) : value;', + '', + ' if (isSorted', + ' ? !index || seen[seen.length - 1] !== computed', + ' : indexOf(seen, computed) < 0', + ' ) {', + ' if (callback) {', + ' seen.push(computed);', + ' }', + ' result.push(value);', + ' }', + ' }', + ' return result;', + ' }' + ].join('\n')); + + // replace `_.uniqueId` + source = replaceFunction(source, 'uniqueId', [ + ' function uniqueId(prefix) {', + " var id = ++idCounter + '';", + ' return prefix ? prefix + id : id;', + ' }' + ].join('\n')); + + // replace `_.where` + source = replaceFunction(source, 'where', [ + ' function where(collection, properties, first) {', + ' return (first && isEmpty(properties))', + ' ? null', + ' : (first ? find : filter)(collection, properties);', + ' }' + ].join('\n')); + + // replace `_.without` + source = replaceFunction(source, 'without', [ + ' function without(array) {', + ' var index = -1,', + ' length = array.length,', + ' result = [];', + '', + ' while (++index < length) {', + ' var value = array[index]', + ' if (indexOf(arguments, value, 1) < 0) {', + ' result.push(value);', + ' }', + ' }', + ' return result', + ' }' + ].join('\n')); + + // add `_.findWhere` + source = source.replace(matchFunction(source, 'find'), function (match) { + return match + [ + '', + ' function findWhere(object, properties) {', + ' return where(object, properties, true);', + ' }', + '' + ].join('\n') + }); + + source = source.replace(getMethodAssignments(source), function(match) { + return match.replace(/^( *)lodash.find *=.+/m, '$&\n$1lodash.findWhere = findWhere;'); + }); + + // add Underscore style chaining + source = addChainMethods(source); + + // remove `_.templateSettings.imports assignment + source = source.replace(/,[^']*'imports':[^}]+}/, ''); + + // remove large array optimizations + source = removeFunction(source, 'cachedContains'); + source = removeVar(source, 'largeArraySize'); + + // remove `_.isEqual` use from `createCallback` + source = source.replace(matchFunction(source, 'createCallback'), function(match) { + return match.replace(/isEqual\(([^,]+), *([^,]+)[^)]+\)/, '$1 === $2'); + }); + + // remove conditional `charCodeCallback` use from `_.max` and `_.min` + _.each(['max', 'min'], function(methodName) { + source = source.replace(matchFunction(source, methodName), function(match) { + return match.replace(/!callback *&& *isString\(collection\)[\s\S]+?: */g, ''); + }); + }); + + // remove unneeded variables + if (useUnderscoreClone) { + source = removeVar(source, 'cloneableClasses'); + source = removeVar(source, 'ctorByClass'); + } + // remove unused features from `createBound` + if (buildMethods.indexOf('partial') < 0 && buildMethods.indexOf('partialRight') < 0) { + source = source.replace(matchFunction(source, 'createBound'), function(match) { + return match + .replace(/, *right[^)]*/, '') + .replace(/(function createBound\([^{]+{)[\s\S]+?(\n *function bound)/, '$1$2') + .replace(/thisBinding *=[^}]+}/, 'thisBinding = thisArg;\n') + .replace(/\(args *=.+/, 'partialArgs.concat(slice(args))'); + }); + } + } + vm.runInContext(source, context); + return context._; + }()); + + /*------------------------------------------------------------------------*/ + + if (isTemplate) { + source = buildTemplate(templatePattern, templateSettings); + } + else { + // remove methods from the build + allMethods.forEach(function(otherName) { + if (!_.contains(buildMethods, otherName)) { + source = removeFunction(source, otherName); + } + }); + + // remove `isArguments` fallback before `isArguments` is transformed by + // other parts of the build process + if (isRemoved(source, 'isArguments')) { + source = removeIsArgumentsFallback(source); + } + + // remove `iteratorTemplate` dependency checks from `_.template` + source = source.replace(matchFunction(source, 'template'), function(match) { + return match + .replace(/iteratorTemplate *&& */g, '') + .replace(/iteratorTemplate *\? *([^:]+?) *:[^,;]+/g, '$1'); + }); + + /*----------------------------------------------------------------------*/ + + if (isLegacy) { + source = removeSetImmediate(source); + + _.each(['isBindFast', 'isV8', 'nativeBind', 'nativeIsArray', 'nativeKeys', 'reNative'], function(varName) { + source = removeVar(source, varName); + }); + + // remove native `Function#bind` branch in `_.bind` + source = source.replace(matchFunction(source, 'bind'), function(match) { + return match.replace(/(?:\s*\/\/.*)*\s*return isBindFast[^:]+:\s*/, 'return '); + }); + + // remove native `Array.isArray` branch in `_.isArray` + source = source.replace(matchFunction(source, 'isArray'), function(match) { + return match.replace(/nativeIsArray * \|\|\s*/, ''); + }); + + // replace `_.keys` with `shimKeys` + if (!isRemoved(source, 'keys')) { + source = source.replace( + matchFunction(source, 'keys').replace(/[\s\S]+?var keys *= */, ''), + matchFunction(source, 'shimKeys').replace(/[\s\S]+?function shimKeys/, 'function').replace(/}\n$/, '};\n') + ); + + source = removeFunction(source, 'shimKeys'); + } + // replace `_.isArguments` with fallback + if (!isRemoved(source, 'isArguments')) { + source = source.replace( + matchFunction(source, 'isArguments').replace(/[\s\S]+?function isArguments/, ''), + getIsArgumentsFallback(source).match(/isArguments *= *function([\s\S]+?) *};/)[1] + ' }\n' + ); + + source = removeIsArgumentsFallback(source); + } + } + if (isModern) { + source = removeArgsAreObjects(source); + source = removeHasObjectSpliceBug(source); + source = removeIsArgumentsFallback(source); + } + if (isModern || isUnderscore) { + source = removeNoArgsClass(source); + source = removeNoNodeClass(source); + } + if (isMobile || isUnderscore) { + source = removeVar(source, 'iteratorTemplate'); + + // inline all functions defined with `createIterator` + _.functions(lodash).forEach(function(methodName) { + // strip leading underscores to match pseudo private functions + var reFunc = RegExp('(\\bvar ' + methodName.replace(/^_/, '') + ' *= *)createIterator\\(((?:{|[a-zA-Z])[\\s\\S]+?)\\);\\n'); + if (reFunc.test(source)) { + // extract, format, and inject the compiled function's source code + source = source.replace(reFunc, function(match, captured) { + return captured + getFunctionSource(lodash[methodName]) + ';\n'; + }); + } + }); + } + if (isUnderscore) { + // remove `_.assign`, `_.forIn`, `_.forOwn`, and `_.isPlainObject` assignments + (function() { + var snippet = getMethodAssignments(source), + modified = snippet; + + if (!exposeAssign) { + modified = modified.replace(/^(?: *\/\/.*\s*)* *lodash\.assign *= *.+\n/m, ''); + } + if (!exposeForIn) { + modified = modified.replace(/^(?: *\/\/.*\s*)* *lodash\.forIn *= *.+\n/m, ''); + } + if (!exposeForOwn) { + modified = modified.replace(/^(?: *\/\/.*\s*)* *lodash\.forOwn *= *.+\n/m, ''); + } + if (!exposeIsPlainObject) { + modified = modified.replace(/^(?: *\/\/.*\s*)* *lodash\.isPlainObject *= *.+\n/m, ''); + } + source = source.replace(snippet, modified); + }()); + + // remove `thisArg` from unexposed `forIn` and `forOwn` + _.each([ + { 'methodName': 'forIn', 'flag': exposeForIn }, + { 'methodName': 'forOwn', 'flag': exposeForOwn } + ], function(data) { + if (!data.flag) { + source = source.replace(matchFunction(source, data.methodName), function(match) { + return match + .replace(/(callback), *thisArg/g, '$1') + .replace(/^( *)callback *=.+/m, '$1callback || (callback = identity);') + }); + } + }); + + // remove chainability from `each` and `_.forEach` + _.each(['each', 'forEach'], function(methodName) { + source = source.replace(matchFunction(source, methodName), function(match) { + return match.replace(/\n *return .+?([};\s]+)$/, '$1'); + }); + }); + + // unexpose "exit early" feature of `each`, `_.forEach`, `_.forIn`, and `_.forOwn` + _.each(['each', 'forEach', 'forIn', 'forOwn'], function(methodName) { + source = source.replace(matchFunction(source, methodName), function(match) { + return match.replace(/=== *false\)/g, '=== indicatorObject)'); + }); + }); + + // modify `_.every`, `_.find`, `_.isEqual`, and `_.some` to use the private `indicatorObject` + _.each(['every', 'isEqual'], function(methodName) { + source = source.replace(matchFunction(source, methodName), function(match) { + return match.replace(/\(result *= *(.+?)\);/g, '!(result = $1) && indicatorObject;'); + }); + }); + + source = source.replace(matchFunction(source, 'find'), function(match) { + return match.replace(/return false/, 'return indicatorObject'); + }); + + source = source.replace(matchFunction(source, 'some'), function(match) { + return match.replace(/!\(result *= *(.+?)\);/, '(result = $1) && indicatorObject;'); + }); + } + if (!(isMobile || isUnderscore)) { + // inline `iteratorTemplate` template + source = source.replace(getIteratorTemplate(source), function() { + var snippet = getFunctionSource(lodash._iteratorTemplate); + + // prepend data object references to property names to avoid having to + // use a with-statement + iteratorOptions.forEach(function(property) { + snippet = snippet.replace(RegExp('([^\\w.])\\b' + property + '\\b', 'g'), '$1obj.' + property); + }); + + // remove unnecessary code + snippet = snippet + .replace(/var __t.+/, "var __p = '';") + .replace(/function print[^}]+}/, '') + .replace(/'(?:\\n|\s)+'/g, "''") + .replace(/__p *\+= *' *';/g, '') + .replace(/(__p *\+= *)' *' *\+/g, '$1') + .replace(/({) *;|; *(})/g, '$1$2') + .replace(/\(\(__t *= *\( *([^)]+) *\)\) *== *null *\? *'' *: *__t\)/g, '($1)'); + + // remove the with-statement + snippet = snippet.replace(/ *with *\(.+?\) *{/, '\n').replace(/}([^}]*}[^}]*$)/, '$1'); + + // minor cleanup + snippet = snippet + .replace(/obj *\|\|\s*\(obj *= *{}\);/, '') + .replace(/var __p = '';\s*__p \+=/, 'var __p ='); + + // remove comments, including sourceURLs + snippet = snippet.replace(/\s*\/\/.*(?:\n|$)/g, ''); + + return ' var iteratorTemplate = ' + snippet + ';\n'; + }); + } + } + + /*------------------------------------------------------------------------*/ + + // customize Lo-Dash's IIFE + (function() { + if (isIIFE) { + var token = '%output%', + index = iife.indexOf(token); + + source = source.match(/^\/\**[\s\S]+?\*\/\n/) + + iife.slice(0, index) + + source.replace(/^[\s\S]+?\(function[^{]+?{|}\(this\)\)[;\s]*$/g, '') + + iife.slice(index + token.length); + } + }()); + + /*------------------------------------------------------------------------*/ + + // customize Lo-Dash's export bootstrap + (function() { + if (!isAMD) { + source = source.replace(/(?: *\/\/.*\n)*( *)if *\(typeof +define[\s\S]+?else /, '$1'); + } + if (!isNode) { + source = source.replace(/(?: *\/\/.*\n)*( *)if *\(freeModule[\s\S]+?else *{([\s\S]+?\n)\1}\n/, '$1$2'); + } + if (!isCommonJS) { + source = source.replace(/(?: *\/\/.*\n)*(?:( *)else *{)?\s*freeExports\.\w+ *=[\s\S]+?(?:\n\1})?\n/, ''); + } + if (!isGlobal) { + source = source.replace(/(?:( *)(})? *else(?: *if *\(_\))? *{)?(?:\s*\/\/.*)*\s*(?:window\._|_\.templates) *=[\s\S]+?(?:\n\1})?\n/g, '$1$2\n'); + } + // remove `if (freeExports) {...}` if it's empty + if (isAMD && isGlobal) { + source = source.replace(/(?: *\/\/.*\n)* *(?:else )?if *\(freeExports\) *{\s*}\n/, ''); + } else { + source = source.replace(/(?: *\/\/.*\n)* *(?:else )?if *\(freeExports\) *{\s*}(?:\s*else *{([\s\S]+?) *})?\n/, '$1\n'); + } + }()); + + /*------------------------------------------------------------------------*/ + + if (!isTemplate) { + // modify/remove references to removed methods/variables + if (isRemoved(source, 'invert')) { + source = replaceVar(source, 'htmlUnescapes', "{'&':'&','<':'<','>':'>','"':'\"',''':\"'\"}"); + } + if (isRemoved(source, 'isArguments')) { + source = replaceVar(source, 'noArgsClass', 'false'); + } + if (isRemoved(source, 'isFunction')) { + source = removeIsFunctionFallback(source); + } + if (isRemoved(source, 'mixin')) { + source = removeHasObjectSpliceBug(source); + + // simplify the `lodash` function + source = replaceFunction(source, 'lodash', [ + ' function lodash() {', + ' // no operation performed', + ' }' + ].join('\n')); + + // remove all `lodash.prototype` additions + source = source + .replace(/(?:\s*\/\/.*)*\n( *)forOwn\(lodash, *function\(func, *methodName\)[\s\S]+?\n\1}.+/g, '') + .replace(/(?:\s*\/\/.*)*\n( *)each\(\['[\s\S]+?\n\1}.+/g, '') + .replace(/(?:\s*\/\/.*)*\s*lodash\.prototype.+\n/g, '') + .replace(/(?:\s*\/\/.*)*\s*mixin\(lodash\).+\n/, ''); + } + // remove functions, variables, and snippets that the minifier may miss + if (isRemoved(source, 'clone')) { + source = removeVar(source, 'cloneableClasses'); + source = removeVar(source, 'ctorByClass'); + } + if (isRemoved(source, 'isArray')) { + source = removeVar(source, 'nativeIsArray'); + } + if (isRemoved(source, 'isPlainObject')) { + source = removeVar(source, 'getPrototypeOf'); + source = removeIteratesOwnLast(source); + } + if (isRemoved(source, 'keys')) { + source = removeFunction(source, 'shimKeys'); + } + if (isRemoved(source, 'template')) { + // remove `templateSettings` assignment + source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *lodash\.templateSettings[\s\S]+?};\n/, ''); + } + if (isRemoved(source, 'isArguments', 'isEmpty')) { + source = removeNoArgsClass(source); + } + if (isRemoved(source, 'clone', 'isEqual', 'isPlainObject')) { + source = removeNoNodeClass(source); + } + if ((source.match(/\bcreateIterator\b/g) || []).length < 2) { + source = removeFunction(source, 'createIterator'); + source = removeVar(source, 'defaultsIteratorOptions'); + source = removeVar(source, 'eachIteratorOptions'); + source = removeVar(source, 'forOwnIteratorOptions'); + source = removeVar(source, 'templateIterator'); + source = removeHasDontEnumBug(source); + source = removeHasEnumPrototype(source); + } + if (isRemoved(source, 'createIterator', 'bind', 'keys')) { + source = removeSetImmediate(source); + source = removeVar(source, 'isBindFast'); + source = removeVar(source, 'isV8'); + source = removeVar(source, 'nativeBind'); + } + if (isRemoved(source, 'createIterator', 'keys')) { + source = removeVar(source, 'nativeKeys'); + source = removeKeysOptimization(source); + source = removeNonEnumArgs(source); + } + if (!source.match(/var (?:hasDontEnumBug|hasEnumPrototype|iteratesOwnLast|nonEnumArgs)\b/g)) { + // remove IIFE used to assign `hasDontEnumBug`, `hasEnumPrototype`, `iteratesOwnLast`, and `nonEnumArgs` + source = source.replace(/^ *\(function\(\) *{[\s\S]+?}\(1\)\);\n/m, ''); + } + } + if ((source.match(/\bfreeModule\b/g) || []).length < 2) { + source = removeVar(source, 'freeModule'); + } + if ((source.match(/\bfreeExports\b/g) || []).length < 2) { + source = removeVar(source, 'freeExports'); + } + + debugSource = cleanupSource(source); + source = cleanupSource(source); + + /*------------------------------------------------------------------------*/ + + // flag to track if `outputPath` has been used by `callback` + var outputUsed = false; + + // flag to specify creating a custom build + var isCustom = ( + isLegacy || isMapped || isModern || isStrict || isUnderscore || outputPath || + /(?:category|exclude|exports|iife|include|minus|plus)=/.test(options) || + !_.isEqual(exportsOptions, exportsAll) + ); + + // used as the basename of the output path + var basename = outputPath + ? path.basename(outputPath, '.js') + : 'lodash' + (isTemplate ? '.template' : isCustom ? '.custom' : ''); + + // restore `dependencyMap` + dependencyMap = dependencyBackup; + + // output debug build + if (!isMinify && (isCustom || isDebug || isTemplate)) { + if (isCustom) { + debugSource = addCommandsToHeader(debugSource, options); + } + if (isDebug && isStdOut) { + stdout.write(debugSource); + callback({ + 'source': debugSource + }); + } + else if (!isStdOut) { + filePath = outputPath || path.join(cwd, basename + '.js'); + outputUsed = true; + callback({ + 'source': debugSource, + 'outputPath': filePath + }); + } + } + // begin the minification process + if (!isDebug) { + if (outputPath && outputUsed) { + outputPath = path.join(path.dirname(outputPath), path.basename(outputPath, '.js') + '.min.js'); + } else if (!outputPath) { + outputPath = path.join(cwd, basename + '.min.js'); + } + minify(source, { + 'filePath': filePath, + 'isMapped': isMapped, + 'isSilent': isSilent, + 'isTemplate': isTemplate, + 'modes': isIIFE && ['simple', 'hybrid'], + 'outputPath': outputPath, + 'sourceMapURL': sourceMapURL, + 'onComplete': function(data) { + if (isCustom) { + data.source = addCommandsToHeader(data.source, options); + } + if (isStdOut) { + stdout.write(data.source); + callback(data); + } else { + callback(data); + } + } + }); + } + } + + /*--------------------------------------------------------------------------*/ + + // expose `build` + if (module != require.main) { + module.exports = build; + } + else { + // or invoked directly + build(process.argv, function(data) { + var outputPath = data.outputPath, + sourceMap = data.sourceMap; + + if (outputPath) { + fs.writeFileSync(outputPath, data.source, 'utf8'); + if (sourceMap) { + fs.writeFileSync(path.join(path.dirname(outputPath), path.basename(outputPath, '.js') + '.map'), sourceMap, 'utf8'); + } + } + }); + } +}()); diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.compat.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.compat.js new file mode 100644 index 0000000..37ebc92 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/dist/lodash.compat.js @@ -0,0 +1,5152 @@ +/** + * @license + * Lo-Dash 1.0.1 (Custom Build) + * Build: `lodash -o ./dist/lodash.compat.js` + * Copyright 2012-2013 The Dojo Foundation + * Based on Underscore.js 1.4.4 + * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud Inc. + * Available under MIT license + */ +;(function(window, undefined) { + + /** Detect free variable `exports` */ + var freeExports = typeof exports == 'object' && exports; + + /** Detect free variable `module` */ + var freeModule = typeof module == 'object' && module && module.exports == freeExports && module; + + /** Detect free variable `global` and use it as `window` */ + var freeGlobal = typeof global == 'object' && global; + if (freeGlobal.global === freeGlobal) { + window = freeGlobal; + } + + /** Used for array and object method references */ + var arrayRef = [], + objectRef = {}; + + /** Used to generate unique IDs */ + var idCounter = 0; + + /** Used internally to indicate various things */ + var indicatorObject = objectRef; + + /** Used by `cachedContains` as the default size when optimizations are enabled for large arrays */ + var largeArraySize = 30; + + /** Used to restore the original `_` reference in `noConflict` */ + var oldDash = window._; + + /** Used to match HTML entities */ + var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g; + + /** Used to match empty string literals in compiled template source */ + var reEmptyStringLeading = /\b__p \+= '';/g, + reEmptyStringMiddle = /\b(__p \+=) '' \+/g, + reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; + + /** Used to match regexp flags from their coerced string values */ + var reFlags = /\w*$/; + + /** Used to detect if a method is native */ + var reNative = RegExp('^' + + (objectRef.valueOf + '') + .replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + .replace(/valueOf|for [^\]]+/g, '.+?') + '$' + ); + + /** + * Used to match ES6 template delimiters + * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.6 + */ + var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; + + /** Used to match "interpolate" template delimiters */ + var reInterpolate = /<%=([\s\S]+?)%>/g; + + /** Used to ensure capturing order of template delimiters */ + var reNoMatch = /($^)/; + + /** Used to match HTML characters */ + var reUnescapedHtml = /[&<>"']/g; + + /** Used to match unescaped characters in compiled string literals */ + var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g; + + /** Used to fix the JScript [[DontEnum]] bug */ + var shadowed = [ + 'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', + 'toLocaleString', 'toString', 'valueOf' + ]; + + /** Used to make template sourceURLs easier to identify */ + var templateCounter = 0; + + /** Native method shortcuts */ + var ceil = Math.ceil, + concat = arrayRef.concat, + floor = Math.floor, + getPrototypeOf = reNative.test(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf, + hasOwnProperty = objectRef.hasOwnProperty, + push = arrayRef.push, + toString = objectRef.toString; + + /* Native method shortcuts for methods with the same name as other `lodash` methods */ + var nativeBind = reNative.test(nativeBind = slice.bind) && nativeBind, + nativeIsArray = reNative.test(nativeIsArray = Array.isArray) && nativeIsArray, + nativeIsFinite = window.isFinite, + nativeIsNaN = window.isNaN, + nativeKeys = reNative.test(nativeKeys = Object.keys) && nativeKeys, + nativeMax = Math.max, + nativeMin = Math.min, + nativeRandom = Math.random; + + /** `Object#toString` result shortcuts */ + var argsClass = '[object Arguments]', + arrayClass = '[object Array]', + boolClass = '[object Boolean]', + dateClass = '[object Date]', + funcClass = '[object Function]', + numberClass = '[object Number]', + objectClass = '[object Object]', + regexpClass = '[object RegExp]', + stringClass = '[object String]'; + + /** Detect various environments */ + var isIeOpera = !!window.attachEvent, + isV8 = nativeBind && !/\n|true/.test(nativeBind + isIeOpera); + + /* Detect if `Function#bind` exists and is inferred to be fast (all but V8) */ + var isBindFast = nativeBind && !isV8; + + /* Detect if `Object.keys` exists and is inferred to be fast (IE, Opera, V8) */ + var isKeysFast = nativeKeys && (isIeOpera || isV8); + + /** + * Detect the JScript [[DontEnum]] bug: + * + * In IE < 9 an objects own properties, shadowing non-enumerable ones, are + * made non-enumerable as well. + */ + var hasDontEnumBug; + + /** + * Detect if a `prototype` properties are enumerable by default: + * + * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1 + * (if the prototype or a property on the prototype has been set) + * incorrectly sets a function's `prototype` property [[Enumerable]] + * value to `true`. + */ + var hasEnumPrototype; + + /** Detect if own properties are iterated after inherited properties (IE < 9) */ + var iteratesOwnLast; + + /** + * Detect if `Array#shift` and `Array#splice` augment array-like objects + * incorrectly: + * + * Firefox < 10, IE compatibility mode, and IE < 9 have buggy Array `shift()` + * and `splice()` functions that fail to remove the last element, `value[0]`, + * of array-like objects even though the `length` property is set to `0`. + * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()` + * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9. + */ + var hasObjectSpliceBug = (hasObjectSpliceBug = { '0': 1, 'length': 1 }, + arrayRef.splice.call(hasObjectSpliceBug, 0, 1), hasObjectSpliceBug[0]); + + /** Detect if `arguments` object indexes are non-enumerable (Firefox < 4, IE < 9, PhantomJS, Safari < 5.1) */ + var nonEnumArgs = true; + + (function() { + var props = []; + function ctor() { this.x = 1; } + ctor.prototype = { 'valueOf': 1, 'y': 1 }; + for (var prop in new ctor) { props.push(prop); } + for (prop in arguments) { nonEnumArgs = !prop; } + + hasDontEnumBug = !/valueOf/.test(props); + hasEnumPrototype = ctor.propertyIsEnumerable('prototype'); + iteratesOwnLast = props[0] != 'x'; + }(1)); + + /** Detect if `arguments` objects are `Object` objects (all but Opera < 10.5) */ + var argsAreObjects = arguments.constructor == Object; + + /** Detect if `arguments` objects [[Class]] is unresolvable (Firefox < 4, IE < 9) */ + var noArgsClass = !isArguments(arguments); + + /** + * Detect lack of support for accessing string characters by index: + * + * IE < 8 can't access characters by index and IE 8 can only access + * characters by index on string literals. + */ + var noCharByIndex = ('x'[0] + Object('x')[0]) != 'xx'; + + /** + * Detect if a DOM node's [[Class]] is unresolvable (IE < 9) + * and that the JS engine won't error when attempting to coerce an object to + * a string without a `toString` function. + */ + try { + var noNodeClass = toString.call(document) == objectClass && !({ 'toString': 0 } + ''); + } catch(e) { } + + /** Used to identify object classifications that `_.clone` supports */ + var cloneableClasses = {}; + cloneableClasses[funcClass] = false; + cloneableClasses[argsClass] = cloneableClasses[arrayClass] = + cloneableClasses[boolClass] = cloneableClasses[dateClass] = + cloneableClasses[numberClass] = cloneableClasses[objectClass] = + cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true; + + /** Used to lookup a built-in constructor by [[Class]] */ + var ctorByClass = {}; + ctorByClass[arrayClass] = Array; + ctorByClass[boolClass] = Boolean; + ctorByClass[dateClass] = Date; + ctorByClass[objectClass] = Object; + ctorByClass[numberClass] = Number; + ctorByClass[regexpClass] = RegExp; + ctorByClass[stringClass] = String; + + /** Used to determine if values are of the language type Object */ + var objectTypes = { + 'boolean': false, + 'function': true, + 'object': true, + 'number': false, + 'string': false, + 'undefined': false + }; + + /** Used to escape characters for inclusion in compiled string literals */ + var stringEscapes = { + '\\': '\\', + "'": "'", + '\n': 'n', + '\r': 'r', + '\t': 't', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a `lodash` object, that wraps the given `value`, to enable method + * chaining. + * + * In addition to Lo-Dash methods, wrappers also have the following `Array` methods: + * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`, + * and `unshift` + * + * The chainable wrapper functions are: + * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`, `compose`, + * `concat`, `countBy`, `debounce`, `defaults`, `defer`, `delay`, `difference`, + * `filter`, `flatten`, `forEach`, `forIn`, `forOwn`, `functions`, `groupBy`, + * `initial`, `intersection`, `invert`, `invoke`, `keys`, `map`, `max`, `memoize`, + * `merge`, `min`, `object`, `omit`, `once`, `pairs`, `partial`, `partialRight`, + * `pick`, `pluck`, `push`, `range`, `reject`, `rest`, `reverse`, `shuffle`, + * `slice`, `sort`, `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, + * `union`, `uniq`, `unshift`, `values`, `where`, `without`, `wrap`, and `zip` + * + * The non-chainable wrapper functions are: + * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `has`, `identity`, + * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`, `isEmpty`, + * `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`, `isObject`, + * `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`, `lastIndexOf`, + * `mixin`, `noConflict`, `pop`, `random`, `reduce`, `reduceRight`, `result`, + * `shift`, `size`, `some`, `sortedIndex`, `template`, `unescape`, and `uniqueId` + * + * The wrapper functions `first` and `last` return wrapped values when `n` is + * passed, otherwise they return unwrapped values. + * + * @name _ + * @constructor + * @category Chaining + * @param {Mixed} value The value to wrap in a `lodash` instance. + * @returns {Object} Returns a `lodash` instance. + */ + function lodash(value) { + // exit early if already wrapped, even if wrapped by a different `lodash` constructor + if (value && typeof value == 'object' && value.__wrapped__) { + return value; + } + // allow invoking `lodash` without the `new` operator + if (!(this instanceof lodash)) { + return new lodash(value); + } + this.__wrapped__ = value; + } + + /** + * By default, the template delimiters used by Lo-Dash are similar to those in + * embedded Ruby (ERB). Change the following template settings to use alternative + * delimiters. + * + * @static + * @memberOf _ + * @type Object + */ + lodash.templateSettings = { + + /** + * Used to detect `data` property values to be HTML-escaped. + * + * @memberOf _.templateSettings + * @type RegExp + */ + 'escape': /<%-([\s\S]+?)%>/g, + + /** + * Used to detect code to be evaluated. + * + * @memberOf _.templateSettings + * @type RegExp + */ + 'evaluate': /<%([\s\S]+?)%>/g, + + /** + * Used to detect `data` property values to inject. + * + * @memberOf _.templateSettings + * @type RegExp + */ + 'interpolate': reInterpolate, + + /** + * Used to reference the data object in the template text. + * + * @memberOf _.templateSettings + * @type String + */ + 'variable': '', + + /** + * Used to import variables into the compiled template. + * + * @memberOf _.templateSettings + * @type Object + */ + 'imports': { + + /** + * A reference to the `lodash` function. + * + * @memberOf _.templateSettings.imports + * @type Function + */ + '_': lodash + } + }; + + /*--------------------------------------------------------------------------*/ + + /** + * The template used to create iterator functions. + * + * @private + * @param {Obect} data The data object used to populate the text. + * @returns {String} Returns the interpolated text. + */ + var iteratorTemplate = function(obj) { + + var __p = 'var index, iterable = ' + + (obj.firstArg ) + + ', result = iterable;\nif (!iterable) return result;\n' + + (obj.top ) + + ';\n'; + if (obj.arrays) { + __p += 'var length = iterable.length; index = -1;\nif (' + + (obj.arrays ) + + ') { '; + if (obj.noCharByIndex) { + __p += '\n if (isString(iterable)) {\n iterable = iterable.split(\'\')\n } '; + } ; + __p += '\n while (++index < length) {\n ' + + (obj.loop ) + + '\n }\n}\nelse { '; + } else if (obj.nonEnumArgs) { + __p += '\n var length = iterable.length; index = -1;\n if (length && isArguments(iterable)) {\n while (++index < length) {\n index += \'\';\n ' + + (obj.loop ) + + '\n }\n } else { '; + } ; + + if (obj.hasEnumPrototype) { + __p += '\n var skipProto = typeof iterable == \'function\';\n '; + } ; + + if (obj.isKeysFast && obj.useHas) { + __p += '\n var ownIndex = -1,\n ownProps = objectTypes[typeof iterable] ? nativeKeys(iterable) : [],\n length = ownProps.length;\n\n while (++ownIndex < length) {\n index = ownProps[ownIndex];\n '; + if (obj.hasEnumPrototype) { + __p += 'if (!(skipProto && index == \'prototype\')) {\n '; + } ; + __p += + (obj.loop ) + + ''; + if (obj.hasEnumPrototype) { + __p += '}\n'; + } ; + __p += ' } '; + } else { + __p += '\n for (index in iterable) {'; + if (obj.hasEnumPrototype || obj.useHas) { + __p += '\n if ('; + if (obj.hasEnumPrototype) { + __p += '!(skipProto && index == \'prototype\')'; + } if (obj.hasEnumPrototype && obj.useHas) { + __p += ' && '; + } if (obj.useHas) { + __p += 'hasOwnProperty.call(iterable, index)'; + } ; + __p += ') { '; + } ; + __p += + (obj.loop ) + + '; '; + if (obj.hasEnumPrototype || obj.useHas) { + __p += '\n }'; + } ; + __p += '\n } '; + } ; + + if (obj.hasDontEnumBug) { + __p += '\n\n var ctor = iterable.constructor;\n '; + for (var k = 0; k < 7; k++) { + __p += '\n index = \'' + + (obj.shadowed[k] ) + + '\';\n if ('; + if (obj.shadowed[k] == 'constructor') { + __p += '!(ctor && ctor.prototype === iterable) && '; + } ; + __p += 'hasOwnProperty.call(iterable, index)) {\n ' + + (obj.loop ) + + '\n } '; + } ; + + } ; + + if (obj.arrays || obj.nonEnumArgs) { + __p += '\n}'; + } ; + __p += + (obj.bottom ) + + ';\nreturn result'; + + + return __p + }; + + /** Reusable iterator options for `assign` and `defaults` */ + var defaultsIteratorOptions = { + 'args': 'object, source, guard', + 'top': + 'var args = arguments,\n' + + ' argsIndex = 0,\n' + + " argsLength = typeof guard == 'number' ? 2 : args.length;\n" + + 'while (++argsIndex < argsLength) {\n' + + ' iterable = args[argsIndex];\n' + + ' if (iterable && objectTypes[typeof iterable]) {', + 'loop': "if (typeof result[index] == 'undefined') result[index] = iterable[index]", + 'bottom': ' }\n}' + }; + + /** Reusable iterator options shared by `each`, `forIn`, and `forOwn` */ + var eachIteratorOptions = { + 'args': 'collection, callback, thisArg', + 'top': "callback = callback && typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg)", + 'arrays': "typeof length == 'number'", + 'loop': 'if (callback(iterable[index], index, collection) === false) return result' + }; + + /** Reusable iterator options for `forIn` and `forOwn` */ + var forOwnIteratorOptions = { + 'top': 'if (!objectTypes[typeof iterable]) return result;\n' + eachIteratorOptions.top, + 'arrays': false + }; + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a function optimized to search large arrays for a given `value`, + * starting at `fromIndex`, using strict equality for comparisons, i.e. `===`. + * + * @private + * @param {Array} array The array to search. + * @param {Mixed} value The value to search for. + * @param {Number} [fromIndex=0] The index to search from. + * @param {Number} [largeSize=30] The length at which an array is considered large. + * @returns {Boolean} Returns `true`, if `value` is found, else `false`. + */ + function cachedContains(array, fromIndex, largeSize) { + fromIndex || (fromIndex = 0); + + var length = array.length, + isLarge = (length - fromIndex) >= (largeSize || largeArraySize); + + if (isLarge) { + var cache = {}, + index = fromIndex - 1; + + while (++index < length) { + // manually coerce `value` to a string because `hasOwnProperty`, in some + // older versions of Firefox, coerces objects incorrectly + var key = array[index] + ''; + (hasOwnProperty.call(cache, key) ? cache[key] : (cache[key] = [])).push(array[index]); + } + } + return function(value) { + if (isLarge) { + var key = value + ''; + return hasOwnProperty.call(cache, key) && indexOf(cache[key], value) > -1; + } + return indexOf(array, value, fromIndex) > -1; + } + } + + /** + * Used by `_.max` and `_.min` as the default `callback` when a given + * `collection` is a string value. + * + * @private + * @param {String} value The character to inspect. + * @returns {Number} Returns the code unit of given character. + */ + function charAtCallback(value) { + return value.charCodeAt(0); + } + + /** + * Used by `sortBy` to compare transformed `collection` values, stable sorting + * them in ascending order. + * + * @private + * @param {Object} a The object to compare to `b`. + * @param {Object} b The object to compare to `a`. + * @returns {Number} Returns the sort order indicator of `1` or `-1`. + */ + function compareAscending(a, b) { + var ai = a.index, + bi = b.index; + + a = a.criteria; + b = b.criteria; + + // ensure a stable sort in V8 and other engines + // http://code.google.com/p/v8/issues/detail?id=90 + if (a !== b) { + if (a > b || typeof a == 'undefined') { + return 1; + } + if (a < b || typeof b == 'undefined') { + return -1; + } + } + return ai < bi ? -1 : 1; + } + + /** + * Creates a function that, when called, invokes `func` with the `this` binding + * of `thisArg` and prepends any `partialArgs` to the arguments passed to the + * bound function. + * + * @private + * @param {Function|String} func The function to bind or the method name. + * @param {Mixed} [thisArg] The `this` binding of `func`. + * @param {Array} partialArgs An array of arguments to be partially applied. + * @param {Object} [rightIndicator] Used to indicate partially applying arguments from the right. + * @returns {Function} Returns the new bound function. + */ + function createBound(func, thisArg, partialArgs, rightIndicator) { + var isFunc = isFunction(func), + isPartial = !partialArgs, + key = thisArg; + + // juggle arguments + if (isPartial) { + partialArgs = thisArg; + } + if (!isFunc) { + thisArg = func; + } + + function bound() { + // `Function#bind` spec + // http://es5.github.com/#x15.3.4.5 + var args = arguments, + thisBinding = isPartial ? this : thisArg; + + if (!isFunc) { + func = thisArg[key]; + } + if (partialArgs.length) { + args = args.length + ? (args = slice(args), rightIndicator ? args.concat(partialArgs) : partialArgs.concat(args)) + : partialArgs; + } + if (this instanceof bound) { + // ensure `new bound` is an instance of `bound` and `func` + noop.prototype = func.prototype; + thisBinding = new noop; + noop.prototype = null; + + // mimic the constructor's `return` behavior + // http://es5.github.com/#x13.2.2 + var result = func.apply(thisBinding, args); + return isObject(result) ? result : thisBinding; + } + return func.apply(thisBinding, args); + } + return bound; + } + + /** + * Produces a callback bound to an optional `thisArg`. If `func` is a property + * name, the created callback will return the property value for a given element. + * If `func` is an object, the created callback will return `true` for elements + * that contain the equivalent object properties, otherwise it will return `false`. + * + * @private + * @param {Mixed} [func=identity] The value to convert to a callback. + * @param {Mixed} [thisArg] The `this` binding of the created callback. + * @param {Number} [argCount=3] The number of arguments the callback accepts. + * @returns {Function} Returns a callback function. + */ + function createCallback(func, thisArg, argCount) { + if (func == null) { + return identity; + } + var type = typeof func; + if (type != 'function') { + if (type != 'object') { + return function(object) { + return object[func]; + }; + } + var props = keys(func); + return function(object) { + var length = props.length, + result = false; + while (length--) { + if (!(result = isEqual(object[props[length]], func[props[length]], indicatorObject))) { + break; + } + } + return result; + }; + } + if (typeof thisArg != 'undefined') { + if (argCount === 1) { + return function(value) { + return func.call(thisArg, value); + }; + } + if (argCount === 2) { + return function(a, b) { + return func.call(thisArg, a, b); + }; + } + if (argCount === 4) { + return function(accumulator, value, index, object) { + return func.call(thisArg, accumulator, value, index, object); + }; + } + return function(value, index, object) { + return func.call(thisArg, value, index, object); + }; + } + return func; + } + + /** + * Creates compiled iteration functions. + * + * @private + * @param {Object} [options1, options2, ...] The compile options object(s). + * arrays - A string of code to determine if the iterable is an array or array-like. + * useHas - A boolean to specify using `hasOwnProperty` checks in the object loop. + * args - A string of comma separated arguments the iteration function will accept. + * top - A string of code to execute before the iteration branches. + * loop - A string of code to execute in the object loop. + * bottom - A string of code to execute after the iteration branches. + * + * @returns {Function} Returns the compiled function. + */ + function createIterator() { + var data = { + // support properties + 'hasDontEnumBug': hasDontEnumBug, + 'hasEnumPrototype': hasEnumPrototype, + 'isKeysFast': isKeysFast, + 'nonEnumArgs': nonEnumArgs, + 'noCharByIndex': noCharByIndex, + 'shadowed': shadowed, + + // iterator options + 'arrays': 'isArray(iterable)', + 'bottom': '', + 'loop': '', + 'top': '', + 'useHas': true + }; + + // merge options into a template data object + for (var object, index = 0; object = arguments[index]; index++) { + for (var key in object) { + data[key] = object[key]; + } + } + var args = data.args; + data.firstArg = /^[^,]+/.exec(args)[0]; + + // create the function factory + var factory = Function( + 'createCallback, hasOwnProperty, isArguments, isArray, isString, ' + + 'objectTypes, nativeKeys', + 'return function(' + args + ') {\n' + iteratorTemplate(data) + '\n}' + ); + // return the compiled function + return factory( + createCallback, hasOwnProperty, isArguments, isArray, isString, + objectTypes, nativeKeys + ); + } + + /** + * A function compiled to iterate `arguments` objects, arrays, objects, and + * strings consistenly across environments, executing the `callback` for each + * element in the `collection`. The `callback` is bound to `thisArg` and invoked + * with three arguments; (value, index|key, collection). Callbacks may exit + * iteration early by explicitly returning `false`. + * + * @private + * @type Function + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array|Object|String} Returns `collection`. + */ + var each = createIterator(eachIteratorOptions); + + /** + * Used by `template` to escape characters for inclusion in compiled + * string literals. + * + * @private + * @param {String} match The matched character to escape. + * @returns {String} Returns the escaped character. + */ + function escapeStringChar(match) { + return '\\' + stringEscapes[match]; + } + + /** + * Used by `escape` to convert characters to HTML entities. + * + * @private + * @param {String} match The matched character to escape. + * @returns {String} Returns the escaped character. + */ + function escapeHtmlChar(match) { + return htmlEscapes[match]; + } + + /** + * Checks if `value` is a DOM node in IE < 9. + * + * @private + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the `value` is a DOM node, else `false`. + */ + function isNode(value) { + // IE < 9 presents DOM nodes as `Object` objects except they have `toString` + // methods that are `typeof` "string" and still can coerce nodes to strings + return typeof value.toString != 'function' && typeof (value + '') == 'string'; + } + + /** + * A no-operation function. + * + * @private + */ + function noop() { + // no operation performed + } + + /** + * Slices the `collection` from the `start` index up to, but not including, + * the `end` index. + * + * Note: This function is used, instead of `Array#slice`, to support node lists + * in IE < 9 and to ensure dense arrays are returned. + * + * @private + * @param {Array|Object|String} collection The collection to slice. + * @param {Number} start The start index. + * @param {Number} end The end index. + * @returns {Array} Returns the new array. + */ + function slice(array, start, end) { + start || (start = 0); + if (typeof end == 'undefined') { + end = array ? array.length : 0; + } + var index = -1, + length = end - start || 0, + result = Array(length < 0 ? 0 : length); + + while (++index < length) { + result[index] = array[start + index]; + } + return result; + } + + /** + * Used by `unescape` to convert HTML entities to characters. + * + * @private + * @param {String} match The matched character to unescape. + * @returns {String} Returns the unescaped character. + */ + function unescapeHtmlChar(match) { + return htmlUnescapes[match]; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Checks if `value` is an `arguments` object. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is an `arguments` object, else `false`. + * @example + * + * (function() { return _.isArguments(arguments); })(1, 2, 3); + * // => true + * + * _.isArguments([1, 2, 3]); + * // => false + */ + function isArguments(value) { + return toString.call(value) == argsClass; + } + // fallback for browsers that can't detect `arguments` objects by [[Class]] + if (noArgsClass) { + isArguments = function(value) { + return value ? hasOwnProperty.call(value, 'callee') : false; + }; + } + + /** + * Iterates over `object`'s own and inherited enumerable properties, executing + * the `callback` for each property. The `callback` is bound to `thisArg` and + * invoked with three arguments; (value, key, object). Callbacks may exit iteration + * early by explicitly returning `false`. + * + * @static + * @memberOf _ + * @type Function + * @category Objects + * @param {Object} object The object to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns `object`. + * @example + * + * function Dog(name) { + * this.name = name; + * } + * + * Dog.prototype.bark = function() { + * alert('Woof, woof!'); + * }; + * + * _.forIn(new Dog('Dagny'), function(value, key) { + * alert(key); + * }); + * // => alerts 'name' and 'bark' (order is not guaranteed) + */ + var forIn = createIterator(eachIteratorOptions, forOwnIteratorOptions, { + 'useHas': false + }); + + /** + * Iterates over an object's own enumerable properties, executing the `callback` + * for each property. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, key, object). Callbacks may exit iteration early by explicitly + * returning `false`. + * + * @static + * @memberOf _ + * @type Function + * @category Objects + * @param {Object} object The object to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns `object`. + * @example + * + * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) { + * alert(key); + * }); + * // => alerts '0', '1', and 'length' (order is not guaranteed) + */ + var forOwn = createIterator(eachIteratorOptions, forOwnIteratorOptions); + + /** + * Checks if `value` is an array. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is an array, else `false`. + * @example + * + * (function() { return _.isArray(arguments); })(); + * // => false + * + * _.isArray([1, 2, 3]); + * // => true + */ + var isArray = nativeIsArray || function(value) { + // `instanceof` may cause a memory leak in IE 7 if `value` is a host object + // http://ajaxian.com/archives/working-aroung-the-instanceof-memory-leak + return (argsAreObjects && value instanceof Array) || toString.call(value) == arrayClass; + }; + + /** + * Creates an array composed of the own enumerable property names of `object`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns a new array of property names. + * @example + * + * _.keys({ 'one': 1, 'two': 2, 'three': 3 }); + * // => ['one', 'two', 'three'] (order is not guaranteed) + */ + var keys = !nativeKeys ? shimKeys : function(object) { + if (!isObject(object)) { + return []; + } + if ((hasEnumPrototype && typeof object == 'function') || + (nonEnumArgs && object.length && isArguments(object))) { + return shimKeys(object); + } + return nativeKeys(object); + }; + + /** + * A fallback implementation of `isPlainObject` that checks if a given `value` + * is an object created by the `Object` constructor, assuming objects created + * by the `Object` constructor have no inherited enumerable properties and that + * there are no `Object.prototype` extensions. + * + * @private + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`. + */ + function shimIsPlainObject(value) { + // avoid non-objects and false positives for `arguments` objects + var result = false; + if (!(value && typeof value == 'object') || isArguments(value)) { + return result; + } + // check that the constructor is `Object` (i.e. `Object instanceof Object`) + var ctor = value.constructor; + if ((!isFunction(ctor) && (!noNodeClass || !isNode(value))) || ctor instanceof ctor) { + // IE < 9 iterates inherited properties before own properties. If the first + // iterated property is an object's own property then there are no inherited + // enumerable properties. + if (iteratesOwnLast) { + forIn(value, function(value, key, object) { + result = !hasOwnProperty.call(object, key); + return false; + }); + return result === false; + } + // In most environments an object's own properties are iterated before + // its inherited properties. If the last iterated property is an object's + // own property then there are no inherited enumerable properties. + forIn(value, function(value, key) { + result = key; + }); + return result === false || hasOwnProperty.call(value, result); + } + return result; + } + + /** + * A fallback implementation of `Object.keys` that produces an array of the + * given object's own enumerable property names. + * + * @private + * @param {Object} object The object to inspect. + * @returns {Array} Returns a new array of property names. + */ + function shimKeys(object) { + var result = []; + forOwn(object, function(value, key) { + result.push(key); + }); + return result; + } + + /** + * Used to convert characters to HTML entities: + * + * Though the `>` character is escaped for symmetry, characters like `>` and `/` + * don't require escaping in HTML and have no special meaning unless they're part + * of a tag or an unquoted attribute value. + * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact") + */ + var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + }; + + /** Used to convert HTML entities to characters */ + var htmlUnescapes = invert(htmlEscapes); + + /*--------------------------------------------------------------------------*/ + + /** + * Assigns own enumerable properties of source object(s) to the destination + * object. Subsequent sources will overwrite propery assignments of previous + * sources. If a `callback` function is passed, it will be executed to produce + * the assigned values. The `callback` is bound to `thisArg` and invoked with + * two arguments; (objectValue, sourceValue). + * + * @static + * @memberOf _ + * @type Function + * @alias extend + * @category Objects + * @param {Object} object The destination object. + * @param {Object} [source1, source2, ...] The source objects. + * @param {Function} [callback] The function to customize assigning values. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns the destination object. + * @example + * + * _.assign({ 'name': 'moe' }, { 'age': 40 }); + * // => { 'name': 'moe', 'age': 40 } + * + * var defaults = _.partialRight(_.assign, function(a, b) { + * return typeof a == 'undefined' ? b : a; + * }); + * + * var food = { 'name': 'apple' }; + * defaults(food, { 'name': 'banana', 'type': 'fruit' }); + * // => { 'name': 'apple', 'type': 'fruit' } + */ + var assign = createIterator(defaultsIteratorOptions, { + 'top': + defaultsIteratorOptions.top.replace(';', + ';\n' + + "if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {\n" + + ' var callback = createCallback(args[--argsLength - 1], args[argsLength--], 2);\n' + + "} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {\n" + + ' callback = args[--argsLength];\n' + + '}' + ), + 'loop': 'result[index] = callback ? callback(result[index], iterable[index]) : iterable[index]' + }); + + /** + * Creates a clone of `value`. If `deep` is `true`, nested objects will also + * be cloned, otherwise they will be assigned by reference. If a `callback` + * function is passed, it will be executed to produce the cloned values. If + * `callback` returns `undefined`, cloning will be handled by the method instead. + * The `callback` is bound to `thisArg` and invoked with one argument; (value). + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to clone. + * @param {Boolean} [deep=false] A flag to indicate a deep clone. + * @param {Function} [callback] The function to customize cloning values. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @param- {Array} [stackA=[]] Internally used to track traversed source objects. + * @param- {Array} [stackB=[]] Internally used to associate clones with source counterparts. + * @returns {Mixed} Returns the cloned `value`. + * @example + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * var shallow = _.clone(stooges); + * shallow[0] === stooges[0]; + * // => true + * + * var deep = _.clone(stooges, true); + * deep[0] === stooges[0]; + * // => false + * + * _.mixin({ + * 'clone': _.partialRight(_.clone, function(value) { + * return _.isElement(value) ? value.cloneNode(false) : undefined; + * }) + * }); + * + * var clone = _.clone(document.body); + * clone.childNodes.length; + * // => 0 + */ + function clone(value, deep, callback, thisArg, stackA, stackB) { + var result = value; + + // allows working with "Collections" methods without using their `callback` + // argument, `index|key`, for this method's `callback` + if (typeof deep == 'function') { + thisArg = callback; + callback = deep; + deep = false; + } + if (typeof callback == 'function') { + callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 1); + result = callback(result); + + var done = typeof result != 'undefined'; + if (!done) { + result = value; + } + } + // inspect [[Class]] + var isObj = isObject(result); + if (isObj) { + var className = toString.call(result); + if (!cloneableClasses[className] || (noNodeClass && isNode(result))) { + return result; + } + var isArr = isArray(result); + } + // shallow clone + if (!isObj || !deep) { + return isObj && !done + ? (isArr ? slice(result) : assign({}, result)) + : result; + } + var ctor = ctorByClass[className]; + switch (className) { + case boolClass: + case dateClass: + return done ? result : new ctor(+result); + + case numberClass: + case stringClass: + return done ? result : new ctor(result); + + case regexpClass: + return done ? result : ctor(result.source, reFlags.exec(result)); + } + // check for circular references and return corresponding clone + stackA || (stackA = []); + stackB || (stackB = []); + + var length = stackA.length; + while (length--) { + if (stackA[length] == value) { + return stackB[length]; + } + } + // init cloned object + if (!done) { + result = isArr ? ctor(result.length) : {}; + + // add array properties assigned by `RegExp#exec` + if (isArr) { + if (hasOwnProperty.call(value, 'index')) { + result.index = value.index; + } + if (hasOwnProperty.call(value, 'input')) { + result.input = value.input; + } + } + } + // add the source value to the stack of traversed objects + // and associate it with its clone + stackA.push(value); + stackB.push(result); + + // recursively populate clone (susceptible to call stack limits) + (isArr ? forEach : forOwn)(done ? result : value, function(objValue, key) { + result[key] = clone(objValue, deep, callback, undefined, stackA, stackB); + }); + + return result; + } + + /** + * Creates a deep clone of `value`. If a `callback` function is passed, it will + * be executed to produce the cloned values. If `callback` returns the value it + * was passed, cloning will be handled by the method instead. The `callback` is + * bound to `thisArg` and invoked with one argument; (value). + * + * Note: This function is loosely based on the structured clone algorithm. Functions + * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and + * objects created by constructors other than `Object` are cloned to plain `Object` objects. + * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to deep clone. + * @param {Function} [callback] The function to customize cloning values. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the deep cloned `value`. + * @example + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * var deep = _.cloneDeep(stooges); + * deep[0] === stooges[0]; + * // => false + * + * var view = { + * 'label': 'docs', + * 'node': element + * }; + * + * var clone = _.cloneDeep(view, function(value) { + * return _.isElement(value) ? value.cloneNode(true) : value; + * }); + * + * clone.node == view.node; + * // => false + */ + function cloneDeep(value, callback, thisArg) { + return clone(value, true, callback, thisArg); + } + + /** + * Assigns own enumerable properties of source object(s) to the destination + * object for all destination properties that resolve to `undefined`. Once a + * property is set, additional defaults of the same property will be ignored. + * + * @static + * @memberOf _ + * @type Function + * @category Objects + * @param {Object} object The destination object. + * @param {Object} [source1, source2, ...] The source objects. + * @param- {Object} [guard] Internally used to allow working with `_.reduce` + * without using its callback's `key` and `object` arguments as sources. + * @returns {Object} Returns the destination object. + * @example + * + * var food = { 'name': 'apple' }; + * _.defaults(food, { 'name': 'banana', 'type': 'fruit' }); + * // => { 'name': 'apple', 'type': 'fruit' } + */ + var defaults = createIterator(defaultsIteratorOptions); + + /** + * Creates a sorted array of all enumerable properties, own and inherited, + * of `object` that have function values. + * + * @static + * @memberOf _ + * @alias methods + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns a new array of property names that have function values. + * @example + * + * _.functions(_); + * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...] + */ + function functions(object) { + var result = []; + forIn(object, function(value, key) { + if (isFunction(value)) { + result.push(key); + } + }); + return result.sort(); + } + + /** + * Checks if the specified object `property` exists and is a direct property, + * instead of an inherited property. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to check. + * @param {String} property The property to check for. + * @returns {Boolean} Returns `true` if key is a direct property, else `false`. + * @example + * + * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b'); + * // => true + */ + function has(object, property) { + return object ? hasOwnProperty.call(object, property) : false; + } + + /** + * Creates an object composed of the inverted keys and values of the given `object`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to invert. + * @returns {Object} Returns the created inverted object. + * @example + * + * _.invert({ 'first': 'moe', 'second': 'larry' }); + * // => { 'moe': 'first', 'larry': 'second' } (order is not guaranteed) + */ + function invert(object) { + var index = -1, + props = keys(object), + length = props.length, + result = {}; + + while (++index < length) { + var key = props[index]; + result[object[key]] = key; + } + return result; + } + + /** + * Checks if `value` is a boolean value. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a boolean value, else `false`. + * @example + * + * _.isBoolean(null); + * // => false + */ + function isBoolean(value) { + return value === true || value === false || toString.call(value) == boolClass; + } + + /** + * Checks if `value` is a date. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a date, else `false`. + * @example + * + * _.isDate(new Date); + * // => true + */ + function isDate(value) { + return value instanceof Date || toString.call(value) == dateClass; + } + + /** + * Checks if `value` is a DOM element. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a DOM element, else `false`. + * @example + * + * _.isElement(document.body); + * // => true + */ + function isElement(value) { + return value ? value.nodeType === 1 : false; + } + + /** + * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a + * length of `0` and objects with no own enumerable properties are considered + * "empty". + * + * @static + * @memberOf _ + * @category Objects + * @param {Array|Object|String} value The value to inspect. + * @returns {Boolean} Returns `true`, if the `value` is empty, else `false`. + * @example + * + * _.isEmpty([1, 2, 3]); + * // => false + * + * _.isEmpty({}); + * // => true + * + * _.isEmpty(''); + * // => true + */ + function isEmpty(value) { + var result = true; + if (!value) { + return result; + } + var className = toString.call(value), + length = value.length; + + if ((className == arrayClass || className == stringClass || + className == argsClass || (noArgsClass && isArguments(value))) || + (className == objectClass && typeof length == 'number' && isFunction(value.splice))) { + return !length; + } + forOwn(value, function() { + return (result = false); + }); + return result; + } + + /** + * Performs a deep comparison between two values to determine if they are + * equivalent to each other. If `callback` is passed, it will be executed to + * compare values. If `callback` returns `undefined`, comparisons will be handled + * by the method instead. The `callback` is bound to `thisArg` and invoked with + * two arguments; (a, b). + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} a The value to compare. + * @param {Mixed} b The other value to compare. + * @param {Function} [callback] The function to customize comparing values. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @param- {Object} [stackA=[]] Internally used track traversed `a` objects. + * @param- {Object} [stackB=[]] Internally used track traversed `b` objects. + * @returns {Boolean} Returns `true`, if the values are equvalent, else `false`. + * @example + * + * var moe = { 'name': 'moe', 'age': 40 }; + * var copy = { 'name': 'moe', 'age': 40 }; + * + * moe == copy; + * // => false + * + * _.isEqual(moe, copy); + * // => true + * + * var words = ['hello', 'goodbye']; + * var otherWords = ['hi', 'goodbye']; + * + * _.isEqual(words, otherWords, function(a, b) { + * var reGreet = /^(?:hello|hi)$/i, + * aGreet = _.isString(a) && reGreet.test(a), + * bGreet = _.isString(b) && reGreet.test(b); + * + * return (aGreet || bGreet) ? (aGreet == bGreet) : undefined; + * }); + * // => true + */ + function isEqual(a, b, callback, thisArg, stackA, stackB) { + // used to indicate that when comparing objects, `a` has at least the properties of `b` + var whereIndicator = callback === indicatorObject; + if (callback && !whereIndicator) { + callback = typeof thisArg == 'undefined' ? callback : createCallback(callback, thisArg, 2); + var result = callback(a, b); + if (typeof result != 'undefined') { + return !!result; + } + } + // exit early for identical values + if (a === b) { + // treat `+0` vs. `-0` as not equal + return a !== 0 || (1 / a == 1 / b); + } + var type = typeof a, + otherType = typeof b; + + // exit early for unlike primitive values + if (a === a && + (!a || (type != 'function' && type != 'object')) && + (!b || (otherType != 'function' && otherType != 'object'))) { + return false; + } + // exit early for `null` and `undefined`, avoiding ES3's Function#call behavior + // http://es5.github.com/#x15.3.4.4 + if (a == null || b == null) { + return a === b; + } + // compare [[Class]] names + var className = toString.call(a), + otherClass = toString.call(b); + + if (className == argsClass) { + className = objectClass; + } + if (otherClass == argsClass) { + otherClass = objectClass; + } + if (className != otherClass) { + return false; + } + switch (className) { + case boolClass: + case dateClass: + // coerce dates and booleans to numbers, dates to milliseconds and booleans + // to `1` or `0`, treating invalid dates coerced to `NaN` as not equal + return +a == +b; + + case numberClass: + // treat `NaN` vs. `NaN` as equal + return a != +a + ? b != +b + // but treat `+0` vs. `-0` as not equal + : (a == 0 ? (1 / a == 1 / b) : a == +b); + + case regexpClass: + case stringClass: + // coerce regexes to strings (http://es5.github.com/#x15.10.6.4) + // treat string primitives and their corresponding object instances as equal + return a == b + ''; + } + var isArr = className == arrayClass; + if (!isArr) { + // unwrap any `lodash` wrapped values + if (a.__wrapped__ || b.__wrapped__) { + return isEqual(a.__wrapped__ || a, b.__wrapped__ || b, callback, thisArg, stackA, stackB); + } + // exit for functions and DOM nodes + if (className != objectClass || (noNodeClass && (isNode(a) || isNode(b)))) { + return false; + } + // in older versions of Opera, `arguments` objects have `Array` constructors + var ctorA = !argsAreObjects && isArguments(a) ? Object : a.constructor, + ctorB = !argsAreObjects && isArguments(b) ? Object : b.constructor; + + // non `Object` object instances with different constructors are not equal + if (ctorA != ctorB && !( + isFunction(ctorA) && ctorA instanceof ctorA && + isFunction(ctorB) && ctorB instanceof ctorB + )) { + return false; + } + } + // assume cyclic structures are equal + // the algorithm for detecting cyclic structures is adapted from ES 5.1 + // section 15.12.3, abstract operation `JO` (http://es5.github.com/#x15.12.3) + stackA || (stackA = []); + stackB || (stackB = []); + + var length = stackA.length; + while (length--) { + if (stackA[length] == a) { + return stackB[length] == b; + } + } + var size = 0; + result = true; + + // add `a` and `b` to the stack of traversed objects + stackA.push(a); + stackB.push(b); + + // recursively compare objects and arrays (susceptible to call stack limits) + if (isArr) { + length = a.length; + size = b.length; + + // compare lengths to determine if a deep comparison is necessary + result = size == a.length; + if (!result && !whereIndicator) { + return result; + } + // deep compare the contents, ignoring non-numeric properties + while (size--) { + var index = length, + value = b[size]; + + if (whereIndicator) { + while (index--) { + if ((result = isEqual(a[index], value, callback, thisArg, stackA, stackB))) { + break; + } + } + } else if (!(result = isEqual(a[size], value, callback, thisArg, stackA, stackB))) { + break; + } + } + return result; + } + // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys` + // which, in this case, is more costly + forIn(b, function(value, key, b) { + if (hasOwnProperty.call(b, key)) { + // count the number of properties. + size++; + // deep compare each property value. + return (result = hasOwnProperty.call(a, key) && isEqual(a[key], value, callback, thisArg, stackA, stackB)); + } + }); + + if (result && !whereIndicator) { + // ensure both objects have the same number of properties + forIn(a, function(value, key, a) { + if (hasOwnProperty.call(a, key)) { + // `size` will be `-1` if `a` has more properties than `b` + return (result = --size > -1); + } + }); + } + return result; + } + + /** + * Checks if `value` is, or can be coerced to, a finite number. + * + * Note: This is not the same as native `isFinite`, which will return true for + * booleans and empty strings. See http://es5.github.com/#x15.1.2.5. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is finite, else `false`. + * @example + * + * _.isFinite(-101); + * // => true + * + * _.isFinite('10'); + * // => true + * + * _.isFinite(true); + * // => false + * + * _.isFinite(''); + * // => false + * + * _.isFinite(Infinity); + * // => false + */ + function isFinite(value) { + return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value)); + } + + /** + * Checks if `value` is a function. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a function, else `false`. + * @example + * + * _.isFunction(_); + * // => true + */ + function isFunction(value) { + return typeof value == 'function'; + } + // fallback for older versions of Chrome and Safari + if (isFunction(/x/)) { + isFunction = function(value) { + return value instanceof Function || toString.call(value) == funcClass; + }; + } + + /** + * Checks if `value` is the language type of Object. + * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is an object, else `false`. + * @example + * + * _.isObject({}); + * // => true + * + * _.isObject([1, 2, 3]); + * // => true + * + * _.isObject(1); + * // => false + */ + function isObject(value) { + // check if the value is the ECMAScript language type of Object + // http://es5.github.com/#x8 + // and avoid a V8 bug + // http://code.google.com/p/v8/issues/detail?id=2291 + return value ? objectTypes[typeof value] : false; + } + + /** + * Checks if `value` is `NaN`. + * + * Note: This is not the same as native `isNaN`, which will return `true` for + * `undefined` and other values. See http://es5.github.com/#x15.1.2.4. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is `NaN`, else `false`. + * @example + * + * _.isNaN(NaN); + * // => true + * + * _.isNaN(new Number(NaN)); + * // => true + * + * isNaN(undefined); + * // => true + * + * _.isNaN(undefined); + * // => false + */ + function isNaN(value) { + // `NaN` as a primitive is the only value that is not equal to itself + // (perform the [[Class]] check first to avoid errors with some host objects in IE) + return isNumber(value) && value != +value + } + + /** + * Checks if `value` is `null`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is `null`, else `false`. + * @example + * + * _.isNull(null); + * // => true + * + * _.isNull(undefined); + * // => false + */ + function isNull(value) { + return value === null; + } + + /** + * Checks if `value` is a number. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a number, else `false`. + * @example + * + * _.isNumber(8.4 * 5); + * // => true + */ + function isNumber(value) { + return typeof value == 'number' || toString.call(value) == numberClass; + } + + /** + * Checks if a given `value` is an object created by the `Object` constructor. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if `value` is a plain object, else `false`. + * @example + * + * function Stooge(name, age) { + * this.name = name; + * this.age = age; + * } + * + * _.isPlainObject(new Stooge('moe', 40)); + * // => false + * + * _.isPlainObject([1, 2, 3]); + * // => false + * + * _.isPlainObject({ 'name': 'moe', 'age': 40 }); + * // => true + */ + var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) { + if (!(value && typeof value == 'object')) { + return false; + } + var valueOf = value.valueOf, + objProto = typeof valueOf == 'function' && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto); + + return objProto + ? value == objProto || (getPrototypeOf(value) == objProto && !isArguments(value)) + : shimIsPlainObject(value); + }; + + /** + * Checks if `value` is a regular expression. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a regular expression, else `false`. + * @example + * + * _.isRegExp(/moe/); + * // => true + */ + function isRegExp(value) { + return value instanceof RegExp || toString.call(value) == regexpClass; + } + + /** + * Checks if `value` is a string. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is a string, else `false`. + * @example + * + * _.isString('moe'); + * // => true + */ + function isString(value) { + return typeof value == 'string' || toString.call(value) == stringClass; + } + + /** + * Checks if `value` is `undefined`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true`, if the `value` is `undefined`, else `false`. + * @example + * + * _.isUndefined(void 0); + * // => true + */ + function isUndefined(value) { + return typeof value == 'undefined'; + } + + /** + * Recursively merges own enumerable properties of the source object(s), that + * don't resolve to `undefined`, into the destination object. Subsequent sources + * will overwrite propery assignments of previous sources. If a `callback` function + * is passed, it will be executed to produce the merged values of the destination + * and source properties. If `callback` returns `undefined`, merging will be + * handled by the method instead. The `callback` is bound to `thisArg` and + * invoked with two arguments; (objectValue, sourceValue). + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The destination object. + * @param {Object} [source1, source2, ...] The source objects. + * @param {Function} [callback] The function to customize merging properties. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @param- {Object} [deepIndicator] Internally used to indicate that `stackA` + * and `stackB` are arrays of traversed objects instead of source objects. + * @param- {Array} [stackA=[]] Internally used to track traversed source objects. + * @param- {Array} [stackB=[]] Internally used to associate values with their + * source counterparts. + * @returns {Object} Returns the destination object. + * @example + * + * var names = { + * 'stooges': [ + * { 'name': 'moe' }, + * { 'name': 'larry' } + * ] + * }; + * + * var ages = { + * 'stooges': [ + * { 'age': 40 }, + * { 'age': 50 } + * ] + * }; + * + * _.merge(names, ages); + * // => { 'stooges': [{ 'name': 'moe', 'age': 40 }, { 'name': 'larry', 'age': 50 }] } + * + * var food = { + * 'fruits': ['apple'], + * 'vegetables': ['beet'] + * }; + * + * var otherFood = { + * 'fruits': ['banana'], + * 'vegetables': ['carrot'] + * }; + * + * _.merge(food, otherFood, function(a, b) { + * return _.isArray(a) ? a.concat(b) : undefined; + * }); + * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] } + */ + function merge(object, source, deepIndicator) { + var args = arguments, + index = 0, + length = 2; + + if (!isObject(object)) { + return object; + } + if (deepIndicator === indicatorObject) { + var callback = args[3], + stackA = args[4], + stackB = args[5]; + } else { + stackA = []; + stackB = []; + + // allows working with `_.reduce` and `_.reduceRight` without + // using their `callback` arguments, `index|key` and `collection` + if (typeof deepIndicator != 'number') { + length = args.length; + } + if (length > 3 && typeof args[length - 2] == 'function') { + callback = createCallback(args[--length - 1], args[length--], 2); + } else if (length > 2 && typeof args[length - 1] == 'function') { + callback = args[--length]; + } + } + while (++index < length) { + (isArray(args[index]) ? forEach : forOwn)(args[index], function(source, key) { + var found, + isArr, + result = source, + value = object[key]; + + if (source && ((isArr = isArray(source)) || isPlainObject(source))) { + // avoid merging previously merged cyclic sources + var stackLength = stackA.length; + while (stackLength--) { + if ((found = stackA[stackLength] == source)) { + value = stackB[stackLength]; + break; + } + } + if (!found) { + value = isArr + ? (isArray(value) ? value : []) + : (isPlainObject(value) ? value : {}); + + if (callback) { + result = callback(value, source); + if (typeof result != 'undefined') { + value = result; + } + } + // add `source` and associated `value` to the stack of traversed objects + stackA.push(source); + stackB.push(value); + + // recursively merge objects and arrays (susceptible to call stack limits) + if (!callback) { + value = merge(value, source, indicatorObject, callback, stackA, stackB); + } + } + } + else { + if (callback) { + result = callback(value, source); + if (typeof result == 'undefined') { + result = source; + } + } + if (typeof result != 'undefined') { + value = result; + } + } + object[key] = value; + }); + } + return object; + } + + /** + * Creates a shallow clone of `object` excluding the specified properties. + * Property names may be specified as individual arguments or as arrays of + * property names. If a `callback` function is passed, it will be executed + * for each property in the `object`, omitting the properties `callback` + * returns truthy for. The `callback` is bound to `thisArg` and invoked + * with three arguments; (value, key, object). + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The source object. + * @param {Function|String} callback|[prop1, prop2, ...] The properties to omit + * or the function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns an object without the omitted properties. + * @example + * + * _.omit({ 'name': 'moe', 'age': 40 }, 'age'); + * // => { 'name': 'moe' } + * + * _.omit({ 'name': 'moe', 'age': 40 }, function(value) { + * return typeof value == 'number'; + * }); + * // => { 'name': 'moe' } + */ + function omit(object, callback, thisArg) { + var isFunc = typeof callback == 'function', + result = {}; + + if (isFunc) { + callback = createCallback(callback, thisArg); + } else { + var props = concat.apply(arrayRef, arguments); + } + forIn(object, function(value, key, object) { + if (isFunc + ? !callback(value, key, object) + : indexOf(props, key, 1) < 0 + ) { + result[key] = value; + } + }); + return result; + } + + /** + * Creates a two dimensional array of the given object's key-value pairs, + * i.e. `[[key1, value1], [key2, value2]]`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns new array of key-value pairs. + * @example + * + * _.pairs({ 'moe': 30, 'larry': 40 }); + * // => [['moe', 30], ['larry', 40]] (order is not guaranteed) + */ + function pairs(object) { + var index = -1, + props = keys(object), + length = props.length, + result = Array(length); + + while (++index < length) { + var key = props[index]; + result[index] = [key, object[key]]; + } + return result; + } + + /** + * Creates a shallow clone of `object` composed of the specified properties. + * Property names may be specified as individual arguments or as arrays of property + * names. If `callback` is passed, it will be executed for each property in the + * `object`, picking the properties `callback` returns truthy for. The `callback` + * is bound to `thisArg` and invoked with three arguments; (value, key, object). + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The source object. + * @param {Array|Function|String} callback|[prop1, prop2, ...] The function called + * per iteration or properties to pick, either as individual arguments or arrays. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns an object composed of the picked properties. + * @example + * + * _.pick({ 'name': 'moe', '_userid': 'moe1' }, 'name'); + * // => { 'name': 'moe' } + * + * _.pick({ 'name': 'moe', '_userid': 'moe1' }, function(value, key) { + * return key.charAt(0) != '_'; + * }); + * // => { 'name': 'moe' } + */ + function pick(object, callback, thisArg) { + var result = {}; + if (typeof callback != 'function') { + var index = 0, + props = concat.apply(arrayRef, arguments), + length = isObject(object) ? props.length : 0; + + while (++index < length) { + var key = props[index]; + if (key in object) { + result[key] = object[key]; + } + } + } else { + callback = createCallback(callback, thisArg); + forIn(object, function(value, key, object) { + if (callback(value, key, object)) { + result[key] = value; + } + }); + } + return result; + } + + /** + * Creates an array composed of the own enumerable property values of `object`. + * + * @static + * @memberOf _ + * @category Objects + * @param {Object} object The object to inspect. + * @returns {Array} Returns a new array of property values. + * @example + * + * _.values({ 'one': 1, 'two': 2, 'three': 3 }); + * // => [1, 2, 3] + */ + function values(object) { + var index = -1, + props = keys(object), + length = props.length, + result = Array(length); + + while (++index < length) { + result[index] = object[props[index]]; + } + return result; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Creates an array of elements from the specified indexes, or keys, of the + * `collection`. Indexes may be specified as individual arguments or as arrays + * of indexes. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Array|Number|String} [index1, index2, ...] The indexes of + * `collection` to retrieve, either as individual arguments or arrays. + * @returns {Array} Returns a new array of elements corresponding to the + * provided indexes. + * @example + * + * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]); + * // => ['a', 'c', 'e'] + * + * _.at(['moe', 'larry', 'curly'], 0, 2); + * // => ['moe', 'curly'] + */ + function at(collection) { + var index = -1, + props = concat.apply(arrayRef, slice(arguments, 1)), + length = props.length, + result = Array(length); + + if (noCharByIndex && isString(collection)) { + collection = collection.split(''); + } + while(++index < length) { + result[index] = collection[props[index]]; + } + return result; + } + + /** + * Checks if a given `target` element is present in a `collection` using strict + * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used + * as the offset from the end of the collection. + * + * @static + * @memberOf _ + * @alias include + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Mixed} target The value to check for. + * @param {Number} [fromIndex=0] The index to search from. + * @returns {Boolean} Returns `true` if the `target` element is found, else `false`. + * @example + * + * _.contains([1, 2, 3], 1); + * // => true + * + * _.contains([1, 2, 3], 1, 2); + * // => false + * + * _.contains({ 'name': 'moe', 'age': 40 }, 'moe'); + * // => true + * + * _.contains('curly', 'ur'); + * // => true + */ + function contains(collection, target, fromIndex) { + var index = -1, + length = collection ? collection.length : 0, + result = false; + + fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0; + if (typeof length == 'number') { + result = (isString(collection) + ? collection.indexOf(target, fromIndex) + : indexOf(collection, target, fromIndex) + ) > -1; + } else { + each(collection, function(value) { + if (++index >= fromIndex) { + return !(result = value === target); + } + }); + } + return result; + } + + /** + * Creates an object composed of keys returned from running each element of the + * `collection` through the given `callback`. The corresponding value of each key + * is the number of times the key was returned by the `callback`. The `callback` + * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); }); + * // => { '4': 1, '6': 2 } + * + * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math); + * // => { '4': 1, '6': 2 } + * + * _.countBy(['one', 'two', 'three'], 'length'); + * // => { '3': 2, '5': 1 } + */ + function countBy(collection, callback, thisArg) { + var result = {}; + callback = createCallback(callback, thisArg); + + forEach(collection, function(value, key, collection) { + key = callback(value, key, collection) + ''; + (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1); + }); + return result; + } + + /** + * Checks if the `callback` returns a truthy value for **all** elements of a + * `collection`. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias all + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Boolean} Returns `true` if all elements pass the callback check, + * else `false`. + * @example + * + * _.every([true, 1, null, 'yes'], Boolean); + * // => false + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * // using "_.pluck" callback shorthand + * _.every(stooges, 'age'); + * // => true + * + * // using "_.where" callback shorthand + * _.every(stooges, { 'age': 50 }); + * // => false + */ + function every(collection, callback, thisArg) { + var result = true; + callback = createCallback(callback, thisArg); + + if (isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + if (!(result = !!callback(collection[index], index, collection))) { + break; + } + } + } else { + each(collection, function(value, index, collection) { + return (result = !!callback(value, index, collection)); + }); + } + return result; + } + + /** + * Examines each element in a `collection`, returning an array of all elements + * the `callback` returns truthy for. The `callback` is bound to `thisArg` and + * invoked with three arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias select + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of elements that passed the callback check. + * @example + * + * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); + * // => [2, 4, 6] + * + * var food = [ + * { 'name': 'apple', 'organic': false, 'type': 'fruit' }, + * { 'name': 'carrot', 'organic': true, 'type': 'vegetable' } + * ]; + * + * // using "_.pluck" callback shorthand + * _.filter(food, 'organic'); + * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }] + * + * // using "_.where" callback shorthand + * _.filter(food, { 'type': 'fruit' }); + * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }] + */ + function filter(collection, callback, thisArg) { + var result = []; + callback = createCallback(callback, thisArg); + + if (isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + var value = collection[index]; + if (callback(value, index, collection)) { + result.push(value); + } + } + } else { + each(collection, function(value, index, collection) { + if (callback(value, index, collection)) { + result.push(value); + } + }); + } + return result; + } + + /** + * Examines each element in a `collection`, returning the first that the `callback` + * returns truthy for. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias detect + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the element that passed the callback check, + * else `undefined`. + * @example + * + * var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); + * // => 2 + * + * var food = [ + * { 'name': 'apple', 'organic': false, 'type': 'fruit' }, + * { 'name': 'banana', 'organic': true, 'type': 'fruit' }, + * { 'name': 'beet', 'organic': false, 'type': 'vegetable' }, + * { 'name': 'carrot', 'organic': true, 'type': 'vegetable' } + * ]; + * + * // using "_.where" callback shorthand + * var veggie = _.find(food, { 'type': 'vegetable' }); + * // => { 'name': 'beet', 'organic': false, 'type': 'vegetable' } + * + * // using "_.pluck" callback shorthand + * var healthy = _.find(food, 'organic'); + * // => { 'name': 'banana', 'organic': true, 'type': 'fruit' } + */ + function find(collection, callback, thisArg) { + var result; + callback = createCallback(callback, thisArg); + + forEach(collection, function(value, index, collection) { + if (callback(value, index, collection)) { + result = value; + return false; + } + }); + return result; + } + + /** + * Iterates over a `collection`, executing the `callback` for each element in + * the `collection`. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). Callbacks may exit iteration early + * by explicitly returning `false`. + * + * @static + * @memberOf _ + * @alias each + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array|Object|String} Returns `collection`. + * @example + * + * _([1, 2, 3]).forEach(alert).join(','); + * // => alerts each number and returns '1,2,3' + * + * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, alert); + * // => alerts each number value (order is not guaranteed) + */ + function forEach(collection, callback, thisArg) { + if (callback && typeof thisArg == 'undefined' && isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + if (callback(collection[index], index, collection) === false) { + break; + } + } + } else { + each(collection, callback, thisArg); + } + return collection; + } + + /** + * Creates an object composed of keys returned from running each element of the + * `collection` through the `callback`. The corresponding value of each key is + * an array of elements passed to `callback` that returned the key. The `callback` + * is bound to `thisArg` and invoked with three arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false` + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Object} Returns the composed aggregate object. + * @example + * + * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); }); + * // => { '4': [4.2], '6': [6.1, 6.4] } + * + * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math); + * // => { '4': [4.2], '6': [6.1, 6.4] } + * + * // using "_.pluck" callback shorthand + * _.groupBy(['one', 'two', 'three'], 'length'); + * // => { '3': ['one', 'two'], '5': ['three'] } + */ + function groupBy(collection, callback, thisArg) { + var result = {}; + callback = createCallback(callback, thisArg); + + forEach(collection, function(value, key, collection) { + key = callback(value, key, collection) + ''; + (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value); + }); + return result; + } + + /** + * Invokes the method named by `methodName` on each element in the `collection`, + * returning an array of the results of each invoked method. Additional arguments + * will be passed to each invoked method. If `methodName` is a function, it will + * be invoked for, and `this` bound to, each element in the `collection`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|String} methodName The name of the method to invoke or + * the function invoked per iteration. + * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with. + * @returns {Array} Returns a new array of the results of each invoked method. + * @example + * + * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort'); + * // => [[1, 5, 7], [1, 2, 3]] + * + * _.invoke([123, 456], String.prototype.split, ''); + * // => [['1', '2', '3'], ['4', '5', '6']] + */ + function invoke(collection, methodName) { + var args = slice(arguments, 2), + index = -1, + isFunc = typeof methodName == 'function', + length = collection ? collection.length : 0, + result = Array(typeof length == 'number' ? length : 0); + + forEach(collection, function(value) { + result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args); + }); + return result; + } + + /** + * Creates an array of values by running each element in the `collection` + * through the `callback`. The `callback` is bound to `thisArg` and invoked with + * three arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias collect + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of the results of each `callback` execution. + * @example + * + * _.map([1, 2, 3], function(num) { return num * 3; }); + * // => [3, 6, 9] + * + * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; }); + * // => [3, 6, 9] (order is not guaranteed) + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * // using "_.pluck" callback shorthand + * _.map(stooges, 'name'); + * // => ['moe', 'larry'] + */ + function map(collection, callback, thisArg) { + var index = -1, + length = collection ? collection.length : 0, + result = Array(typeof length == 'number' ? length : 0); + + callback = createCallback(callback, thisArg); + if (isArray(collection)) { + while (++index < length) { + result[index] = callback(collection[index], index, collection); + } + } else { + each(collection, function(value, key, collection) { + result[++index] = callback(value, key, collection); + }); + } + return result; + } + + /** + * Retrieves the maximum value of an `array`. If `callback` is passed, + * it will be executed for each value in the `array` to generate the + * criterion by which the value is ranked. The `callback` is bound to + * `thisArg` and invoked with three arguments; (value, index, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the maximum value. + * @example + * + * _.max([4, 2, 8, 6]); + * // => 8 + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * _.max(stooges, function(stooge) { return stooge.age; }); + * // => { 'name': 'larry', 'age': 50 }; + * + * // using "_.pluck" callback shorthand + * _.max(stooges, 'age'); + * // => { 'name': 'larry', 'age': 50 }; + */ + function max(collection, callback, thisArg) { + var computed = -Infinity, + result = computed; + + if (!callback && isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + var value = collection[index]; + if (value > result) { + result = value; + } + } + } else { + callback = !callback && isString(collection) + ? charAtCallback + : createCallback(callback, thisArg); + + each(collection, function(value, index, collection) { + var current = callback(value, index, collection); + if (current > computed) { + computed = current; + result = value; + } + }); + } + return result; + } + + /** + * Retrieves the minimum value of an `array`. If `callback` is passed, + * it will be executed for each value in the `array` to generate the + * criterion by which the value is ranked. The `callback` is bound to `thisArg` + * and invoked with three arguments; (value, index, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the minimum value. + * @example + * + * _.min([4, 2, 8, 6]); + * // => 2 + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * _.min(stooges, function(stooge) { return stooge.age; }); + * // => { 'name': 'moe', 'age': 40 }; + * + * // using "_.pluck" callback shorthand + * _.min(stooges, 'age'); + * // => { 'name': 'moe', 'age': 40 }; + */ + function min(collection, callback, thisArg) { + var computed = Infinity, + result = computed; + + if (!callback && isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + var value = collection[index]; + if (value < result) { + result = value; + } + } + } else { + callback = !callback && isString(collection) + ? charAtCallback + : createCallback(callback, thisArg); + + each(collection, function(value, index, collection) { + var current = callback(value, index, collection); + if (current < computed) { + computed = current; + result = value; + } + }); + } + return result; + } + + /** + * Retrieves the value of a specified property from all elements in the `collection`. + * + * @static + * @memberOf _ + * @type Function + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {String} property The property to pluck. + * @returns {Array} Returns a new array of property values. + * @example + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * _.pluck(stooges, 'name'); + * // => ['moe', 'larry'] + */ + var pluck = map; + + /** + * Reduces a `collection` to a value that is the accumulated result of running + * each element in the `collection` through the `callback`, where each successive + * `callback` execution consumes the return value of the previous execution. + * If `accumulator` is not passed, the first element of the `collection` will be + * used as the initial `accumulator` value. The `callback` is bound to `thisArg` + * and invoked with four arguments; (accumulator, value, index|key, collection). + * + * @static + * @memberOf _ + * @alias foldl, inject + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [accumulator] Initial value of the accumulator. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the accumulated value. + * @example + * + * var sum = _.reduce([1, 2, 3], function(sum, num) { + * return sum + num; + * }); + * // => 6 + * + * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) { + * result[key] = num * 3; + * return result; + * }, {}); + * // => { 'a': 3, 'b': 6, 'c': 9 } + */ + function reduce(collection, callback, accumulator, thisArg) { + var noaccum = arguments.length < 3; + callback = createCallback(callback, thisArg, 4); + + if (isArray(collection)) { + var index = -1, + length = collection.length; + + if (noaccum) { + accumulator = collection[++index]; + } + while (++index < length) { + accumulator = callback(accumulator, collection[index], index, collection); + } + } else { + each(collection, function(value, index, collection) { + accumulator = noaccum + ? (noaccum = false, value) + : callback(accumulator, value, index, collection) + }); + } + return accumulator; + } + + /** + * This method is similar to `_.reduce`, except that it iterates over a + * `collection` from right to left. + * + * @static + * @memberOf _ + * @alias foldr + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function} [callback=identity] The function called per iteration. + * @param {Mixed} [accumulator] Initial value of the accumulator. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the accumulated value. + * @example + * + * var list = [[0, 1], [2, 3], [4, 5]]; + * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []); + * // => [4, 5, 2, 3, 0, 1] + */ + function reduceRight(collection, callback, accumulator, thisArg) { + var iterable = collection, + length = collection ? collection.length : 0, + noaccum = arguments.length < 3; + + if (typeof length != 'number') { + var props = keys(collection); + length = props.length; + } else if (noCharByIndex && isString(collection)) { + iterable = collection.split(''); + } + callback = createCallback(callback, thisArg, 4); + forEach(collection, function(value, index, collection) { + index = props ? props[--length] : --length; + accumulator = noaccum + ? (noaccum = false, iterable[index]) + : callback(accumulator, iterable[index], index, collection); + }); + return accumulator; + } + + /** + * The opposite of `_.filter`, this method returns the elements of a + * `collection` that `callback` does **not** return truthy for. + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of elements that did **not** pass the + * callback check. + * @example + * + * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; }); + * // => [1, 3, 5] + * + * var food = [ + * { 'name': 'apple', 'organic': false, 'type': 'fruit' }, + * { 'name': 'carrot', 'organic': true, 'type': 'vegetable' } + * ]; + * + * // using "_.pluck" callback shorthand + * _.reject(food, 'organic'); + * // => [{ 'name': 'apple', 'organic': false, 'type': 'fruit' }] + * + * // using "_.where" callback shorthand + * _.reject(food, { 'type': 'fruit' }); + * // => [{ 'name': 'carrot', 'organic': true, 'type': 'vegetable' }] + */ + function reject(collection, callback, thisArg) { + callback = createCallback(callback, thisArg); + return filter(collection, function(value, index, collection) { + return !callback(value, index, collection); + }); + } + + /** + * Creates an array of shuffled `array` values, using a version of the + * Fisher-Yates shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to shuffle. + * @returns {Array} Returns a new shuffled collection. + * @example + * + * _.shuffle([1, 2, 3, 4, 5, 6]); + * // => [4, 1, 6, 3, 5, 2] + */ + function shuffle(collection) { + var index = -1, + length = collection ? collection.length : 0, + result = Array(typeof length == 'number' ? length : 0); + + forEach(collection, function(value) { + var rand = floor(nativeRandom() * (++index + 1)); + result[index] = result[rand]; + result[rand] = value; + }); + return result; + } + + /** + * Gets the size of the `collection` by returning `collection.length` for arrays + * and array-like objects or the number of own enumerable properties for objects. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to inspect. + * @returns {Number} Returns `collection.length` or number of own enumerable properties. + * @example + * + * _.size([1, 2]); + * // => 2 + * + * _.size({ 'one': 1, 'two': 2, 'three': 3 }); + * // => 3 + * + * _.size('curly'); + * // => 5 + */ + function size(collection) { + var length = collection ? collection.length : 0; + return typeof length == 'number' ? length : keys(collection).length; + } + + /** + * Checks if the `callback` returns a truthy value for **any** element of a + * `collection`. The function returns as soon as it finds passing value, and + * does not iterate over the entire `collection`. The `callback` is bound to + * `thisArg` and invoked with three arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias any + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Boolean} Returns `true` if any element passes the callback check, + * else `false`. + * @example + * + * _.some([null, 0, 'yes', false], Boolean); + * // => true + * + * var food = [ + * { 'name': 'apple', 'organic': false, 'type': 'fruit' }, + * { 'name': 'carrot', 'organic': true, 'type': 'vegetable' } + * ]; + * + * // using "_.pluck" callback shorthand + * _.some(food, 'organic'); + * // => true + * + * // using "_.where" callback shorthand + * _.some(food, { 'type': 'meat' }); + * // => false + */ + function some(collection, callback, thisArg) { + var result; + callback = createCallback(callback, thisArg); + + if (isArray(collection)) { + var index = -1, + length = collection.length; + + while (++index < length) { + if ((result = callback(collection[index], index, collection))) { + break; + } + } + } else { + each(collection, function(value, index, collection) { + return !(result = callback(value, index, collection)); + }); + } + return !!result; + } + + /** + * Creates an array of elements, sorted in ascending order by the results of + * running each element in the `collection` through the `callback`. This method + * performs a stable sort, that is, it will preserve the original sort order of + * equal elements. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, index|key, collection). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a new array of sorted elements. + * @example + * + * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); }); + * // => [3, 1, 2] + * + * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math); + * // => [3, 1, 2] + * + * // using "_.pluck" callback shorthand + * _.sortBy(['banana', 'strawberry', 'apple'], 'length'); + * // => ['apple', 'banana', 'strawberry'] + */ + function sortBy(collection, callback, thisArg) { + var index = -1, + length = collection ? collection.length : 0, + result = Array(typeof length == 'number' ? length : 0); + + callback = createCallback(callback, thisArg); + forEach(collection, function(value, key, collection) { + result[++index] = { + 'criteria': callback(value, key, collection), + 'index': index, + 'value': value + }; + }); + + length = result.length; + result.sort(compareAscending); + while (length--) { + result[length] = result[length].value; + } + return result; + } + + /** + * Converts the `collection` to an array. + * + * @static + * @memberOf _ + * @category Collections + * @param {Array|Object|String} collection The collection to convert. + * @returns {Array} Returns the new converted array. + * @example + * + * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4); + * // => [2, 3, 4] + */ + function toArray(collection) { + if (collection && typeof collection.length == 'number') { + return noCharByIndex && isString(collection) + ? collection.split('') + : slice(collection); + } + return values(collection); + } + + /** + * Examines each element in a `collection`, returning an array of all elements + * that have the given `properties`. When checking `properties`, this method + * performs a deep comparison between values to determine if they are equivalent + * to each other. + * + * @static + * @memberOf _ + * @type Function + * @category Collections + * @param {Array|Object|String} collection The collection to iterate over. + * @param {Object} properties The object of property values to filter by. + * @returns {Array} Returns a new array of elements that have the given `properties`. + * @example + * + * var stooges = [ + * { 'name': 'moe', 'age': 40 }, + * { 'name': 'larry', 'age': 50 } + * ]; + * + * _.where(stooges, { 'age': 40 }); + * // => [{ 'name': 'moe', 'age': 40 }] + */ + var where = filter; + + /*--------------------------------------------------------------------------*/ + + /** + * Creates an array with all falsey values of `array` removed. The values + * `false`, `null`, `0`, `""`, `undefined` and `NaN` are all falsey. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to compact. + * @returns {Array} Returns a new filtered array. + * @example + * + * _.compact([0, 1, false, 2, '', 3]); + * // => [1, 2, 3] + */ + function compact(array) { + var index = -1, + length = array ? array.length : 0, + result = []; + + while (++index < length) { + var value = array[index]; + if (value) { + result.push(value); + } + } + return result; + } + + /** + * Creates an array of `array` elements not present in the other arrays + * using strict equality for comparisons, i.e. `===`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to process. + * @param {Array} [array1, array2, ...] Arrays to check. + * @returns {Array} Returns a new array of `array` elements not present in the + * other arrays. + * @example + * + * _.difference([1, 2, 3, 4, 5], [5, 2, 10]); + * // => [1, 3, 4] + */ + function difference(array) { + var index = -1, + length = array ? array.length : 0, + flattened = concat.apply(arrayRef, arguments), + contains = cachedContains(flattened, length), + result = []; + + while (++index < length) { + var value = array[index]; + if (!contains(value)) { + result.push(value); + } + } + return result; + } + + /** + * Gets the first element of the `array`. If a number `n` is passed, the first + * `n` elements of the `array` are returned. If a `callback` function is passed, + * the first elements the `callback` returns truthy for are returned. The `callback` + * is bound to `thisArg` and invoked with three arguments; (value, index, array). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias head, take + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|Number|String} [callback|n] The function called + * per element or the number of elements to return. If a property name or + * object is passed, it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the first element(s) of `array`. + * @example + * + * _.first([1, 2, 3]); + * // => 1 + * + * _.first([1, 2, 3], 2); + * // => [1, 2] + * + * _.first([1, 2, 3], function(num) { + * return num < 3; + * }); + * // => [1, 2] + * + * var food = [ + * { 'name': 'banana', 'organic': true }, + * { 'name': 'beet', 'organic': false }, + * ]; + * + * // using "_.pluck" callback shorthand + * _.first(food, 'organic'); + * // => [{ 'name': 'banana', 'organic': true }] + * + * var food = [ + * { 'name': 'apple', 'type': 'fruit' }, + * { 'name': 'banana', 'type': 'fruit' }, + * { 'name': 'beet', 'type': 'vegetable' } + * ]; + * + * // using "_.where" callback shorthand + * _.first(food, { 'type': 'fruit' }); + * // => [{ 'name': 'apple', 'type': 'fruit' }, { 'name': 'banana', 'type': 'fruit' }] + */ + function first(array, callback, thisArg) { + if (array) { + var n = 0, + length = array.length; + + if (typeof callback != 'number' && callback != null) { + var index = -1; + callback = createCallback(callback, thisArg); + while (++index < length && callback(array[index], index, array)) { + n++; + } + } else { + n = callback; + if (n == null || thisArg) { + return array[0]; + } + } + return slice(array, 0, nativeMin(nativeMax(0, n), length)); + } + } + + /** + * Flattens a nested array (the nesting can be to any depth). If `shallow` is + * truthy, `array` will only be flattened a single level. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to compact. + * @param {Boolean} shallow A flag to indicate only flattening a single level. + * @returns {Array} Returns a new flattened array. + * @example + * + * _.flatten([1, [2], [3, [[4]]]]); + * // => [1, 2, 3, 4]; + * + * _.flatten([1, [2], [3, [[4]]]], true); + * // => [1, 2, 3, [[4]]]; + */ + function flatten(array, shallow) { + var index = -1, + length = array ? array.length : 0, + result = []; + + while (++index < length) { + var value = array[index]; + + // recursively flatten arrays (susceptible to call stack limits) + if (isArray(value)) { + push.apply(result, shallow ? value : flatten(value)); + } else { + result.push(value); + } + } + return result; + } + + /** + * Gets the index at which the first occurrence of `value` is found using + * strict equality for comparisons, i.e. `===`. If the `array` is already + * sorted, passing `true` for `fromIndex` will run a faster binary search. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to search. + * @param {Mixed} value The value to search for. + * @param {Boolean|Number} [fromIndex=0] The index to search from or `true` to + * perform a binary search on a sorted `array`. + * @returns {Number} Returns the index of the matched value or `-1`. + * @example + * + * _.indexOf([1, 2, 3, 1, 2, 3], 2); + * // => 1 + * + * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3); + * // => 4 + * + * _.indexOf([1, 1, 2, 2, 3, 3], 2, true); + * // => 2 + */ + function indexOf(array, value, fromIndex) { + var index = -1, + length = array ? array.length : 0; + + if (typeof fromIndex == 'number') { + index = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0) - 1; + } else if (fromIndex) { + index = sortedIndex(array, value); + return array[index] === value ? index : -1; + } + while (++index < length) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + /** + * Gets all but the last element of `array`. If a number `n` is passed, the + * last `n` elements are excluded from the result. If a `callback` function + * is passed, the last elements the `callback` returns truthy for are excluded + * from the result. The `callback` is bound to `thisArg` and invoked with three + * arguments; (value, index, array). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|Number|String} [callback|n=1] The function called + * per element or the number of elements to exclude. If a property name or + * object is passed, it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a slice of `array`. + * @example + * + * _.initial([1, 2, 3]); + * // => [1, 2] + * + * _.initial([1, 2, 3], 2); + * // => [1] + * + * _.initial([1, 2, 3], function(num) { + * return num > 1; + * }); + * // => [1] + * + * var food = [ + * { 'name': 'beet', 'organic': false }, + * { 'name': 'carrot', 'organic': true } + * ]; + * + * // using "_.pluck" callback shorthand + * _.initial(food, 'organic'); + * // => [{ 'name': 'beet', 'organic': false }] + * + * var food = [ + * { 'name': 'banana', 'type': 'fruit' }, + * { 'name': 'beet', 'type': 'vegetable' }, + * { 'name': 'carrot', 'type': 'vegetable' } + * ]; + * + * // using "_.where" callback shorthand + * _.initial(food, { 'type': 'vegetable' }); + * // => [{ 'name': 'banana', 'type': 'fruit' }] + */ + function initial(array, callback, thisArg) { + if (!array) { + return []; + } + var n = 0, + length = array.length; + + if (typeof callback != 'number' && callback != null) { + var index = length; + callback = createCallback(callback, thisArg); + while (index-- && callback(array[index], index, array)) { + n++; + } + } else { + n = (callback == null || thisArg) ? 1 : callback || n; + } + return slice(array, 0, nativeMin(nativeMax(0, length - n), length)); + } + + /** + * Computes the intersection of all the passed-in arrays using strict equality + * for comparisons, i.e. `===`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} [array1, array2, ...] Arrays to process. + * @returns {Array} Returns a new array of unique elements that are present + * in **all** of the arrays. + * @example + * + * _.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]); + * // => [1, 2] + */ + function intersection(array) { + var args = arguments, + argsLength = args.length, + cache = { '0': {} }, + index = -1, + length = array ? array.length : 0, + isLarge = length >= 100, + result = [], + seen = result; + + outer: + while (++index < length) { + var value = array[index]; + if (isLarge) { + var key = value + ''; + var inited = hasOwnProperty.call(cache[0], key) + ? !(seen = cache[0][key]) + : (seen = cache[0][key] = []); + } + if (inited || indexOf(seen, value) < 0) { + if (isLarge) { + seen.push(value); + } + var argsIndex = argsLength; + while (--argsIndex) { + if (!(cache[argsIndex] || (cache[argsIndex] = cachedContains(args[argsIndex], 0, 100)))(value)) { + continue outer; + } + } + result.push(value); + } + } + return result; + } + + /** + * Gets the last element of the `array`. If a number `n` is passed, the last + * `n` elements of the `array` are returned. If a `callback` function is passed, + * the last elements the `callback` returns truthy for are returned. The `callback` + * is bound to `thisArg` and invoked with three arguments; (value, index, array). + * + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|Number|String} [callback|n] The function called + * per element or the number of elements to return. If a property name or + * object is passed, it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Mixed} Returns the last element(s) of `array`. + * @example + * + * _.last([1, 2, 3]); + * // => 3 + * + * _.last([1, 2, 3], 2); + * // => [2, 3] + * + * _.last([1, 2, 3], function(num) { + * return num > 1; + * }); + * // => [2, 3] + * + * var food = [ + * { 'name': 'beet', 'organic': false }, + * { 'name': 'carrot', 'organic': true } + * ]; + * + * // using "_.pluck" callback shorthand + * _.last(food, 'organic'); + * // => [{ 'name': 'carrot', 'organic': true }] + * + * var food = [ + * { 'name': 'banana', 'type': 'fruit' }, + * { 'name': 'beet', 'type': 'vegetable' }, + * { 'name': 'carrot', 'type': 'vegetable' } + * ]; + * + * // using "_.where" callback shorthand + * _.last(food, { 'type': 'vegetable' }); + * // => [{ 'name': 'beet', 'type': 'vegetable' }, { 'name': 'carrot', 'type': 'vegetable' }] + */ + function last(array, callback, thisArg) { + if (array) { + var n = 0, + length = array.length; + + if (typeof callback != 'number' && callback != null) { + var index = length; + callback = createCallback(callback, thisArg); + while (index-- && callback(array[index], index, array)) { + n++; + } + } else { + n = callback; + if (n == null || thisArg) { + return array[length - 1]; + } + } + return slice(array, nativeMax(0, length - n)); + } + } + + /** + * Gets the index at which the last occurrence of `value` is found using strict + * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used + * as the offset from the end of the collection. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to search. + * @param {Mixed} value The value to search for. + * @param {Number} [fromIndex=array.length-1] The index to search from. + * @returns {Number} Returns the index of the matched value or `-1`. + * @example + * + * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2); + * // => 4 + * + * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3); + * // => 1 + */ + function lastIndexOf(array, value, fromIndex) { + var index = array ? array.length : 0; + if (typeof fromIndex == 'number') { + index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1; + } + while (index--) { + if (array[index] === value) { + return index; + } + } + return -1; + } + + /** + * Creates an object composed from arrays of `keys` and `values`. Pass either + * a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`, or + * two arrays, one of `keys` and one of corresponding `values`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} keys The array of keys. + * @param {Array} [values=[]] The array of values. + * @returns {Object} Returns an object composed of the given keys and + * corresponding values. + * @example + * + * _.object(['moe', 'larry'], [30, 40]); + * // => { 'moe': 30, 'larry': 40 } + */ + function object(keys, values) { + var index = -1, + length = keys ? keys.length : 0, + result = {}; + + while (++index < length) { + var key = keys[index]; + if (values) { + result[key] = values[index]; + } else { + result[key[0]] = key[1]; + } + } + return result; + } + + /** + * Creates an array of numbers (positive and/or negative) progressing from + * `start` up to but not including `end`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Number} [start=0] The start of the range. + * @param {Number} end The end of the range. + * @param {Number} [step=1] The value to increment or descrement by. + * @returns {Array} Returns a new range array. + * @example + * + * _.range(10); + * // => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + * + * _.range(1, 11); + * // => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + * + * _.range(0, 30, 5); + * // => [0, 5, 10, 15, 20, 25] + * + * _.range(0, -10, -1); + * // => [0, -1, -2, -3, -4, -5, -6, -7, -8, -9] + * + * _.range(0); + * // => [] + */ + function range(start, end, step) { + start = +start || 0; + step = +step || 1; + + if (end == null) { + end = start; + start = 0; + } + // use `Array(length)` so V8 will avoid the slower "dictionary" mode + // http://youtu.be/XAqIpGU8ZZk#t=17m25s + var index = -1, + length = nativeMax(0, ceil((end - start) / step)), + result = Array(length); + + while (++index < length) { + result[index] = start; + start += step; + } + return result; + } + + /** + * The opposite of `_.initial`, this method gets all but the first value of `array`. + * If a number `n` is passed, the first `n` values are excluded from the result. + * If a `callback` function is passed, the first elements the `callback` returns + * truthy for are excluded from the result. The `callback` is bound to `thisArg` + * and invoked with three arguments; (value, index, array). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias drop, tail + * @category Arrays + * @param {Array} array The array to query. + * @param {Function|Object|Number|String} [callback|n=1] The function called + * per element or the number of elements to exclude. If a property name or + * object is passed, it will be used to create a "_.pluck" or "_.where" + * style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a slice of `array`. + * @example + * + * _.rest([1, 2, 3]); + * // => [2, 3] + * + * _.rest([1, 2, 3], 2); + * // => [3] + * + * _.rest([1, 2, 3], function(num) { + * return num < 3; + * }); + * // => [3] + * + * var food = [ + * { 'name': 'banana', 'organic': true }, + * { 'name': 'beet', 'organic': false }, + * ]; + * + * // using "_.pluck" callback shorthand + * _.rest(food, 'organic'); + * // => [{ 'name': 'beet', 'organic': false }] + * + * var food = [ + * { 'name': 'apple', 'type': 'fruit' }, + * { 'name': 'banana', 'type': 'fruit' }, + * { 'name': 'beet', 'type': 'vegetable' } + * ]; + * + * // using "_.where" callback shorthand + * _.rest(food, { 'type': 'fruit' }); + * // => [{ 'name': 'beet', 'type': 'vegetable' }] + */ + function rest(array, callback, thisArg) { + if (typeof callback != 'number' && callback != null) { + var n = 0, + index = -1, + length = array ? array.length : 0; + + callback = createCallback(callback, thisArg); + while (++index < length && callback(array[index], index, array)) { + n++; + } + } else { + n = (callback == null || thisArg) ? 1 : nativeMax(0, callback); + } + return slice(array, n); + } + + /** + * Uses a binary search to determine the smallest index at which the `value` + * should be inserted into `array` in order to maintain the sort order of the + * sorted `array`. If `callback` is passed, it will be executed for `value` and + * each element in `array` to compute their sort ranking. The `callback` is + * bound to `thisArg` and invoked with one argument; (value). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to iterate over. + * @param {Mixed} value The value to evaluate. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Number} Returns the index at which the value should be inserted + * into `array`. + * @example + * + * _.sortedIndex([20, 30, 50], 40); + * // => 2 + * + * // using "_.pluck" callback shorthand + * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x'); + * // => 2 + * + * var dict = { + * 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 } + * }; + * + * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { + * return dict.wordToNumber[word]; + * }); + * // => 2 + * + * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) { + * return this.wordToNumber[word]; + * }, dict); + * // => 2 + */ + function sortedIndex(array, value, callback, thisArg) { + var low = 0, + high = array ? array.length : low; + + // explicitly reference `identity` for better inlining in Firefox + callback = callback ? createCallback(callback, thisArg, 1) : identity; + value = callback(value); + + while (low < high) { + var mid = (low + high) >>> 1; + callback(array[mid]) < value + ? low = mid + 1 + : high = mid; + } + return low; + } + + /** + * Computes the union of the passed-in arrays using strict equality for + * comparisons, i.e. `===`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} [array1, array2, ...] Arrays to process. + * @returns {Array} Returns a new array of unique values, in order, that are + * present in one or more of the arrays. + * @example + * + * _.union([1, 2, 3], [101, 2, 1, 10], [2, 1]); + * // => [1, 2, 3, 101, 10] + */ + function union() { + return uniq(concat.apply(arrayRef, arguments)); + } + + /** + * Creates a duplicate-value-free version of the `array` using strict equality + * for comparisons, i.e. `===`. If the `array` is already sorted, passing `true` + * for `isSorted` will run a faster algorithm. If `callback` is passed, each + * element of `array` is passed through a callback` before uniqueness is computed. + * The `callback` is bound to `thisArg` and invoked with three arguments; (value, index, array). + * + * If a property name is passed for `callback`, the created "_.pluck" style + * callback will return the property value of the given element. + * + * If an object is passed for `callback`, the created "_.where" style callback + * will return `true` for elements that have the propeties of the given object, + * else `false`. + * + * @static + * @memberOf _ + * @alias unique + * @category Arrays + * @param {Array} array The array to process. + * @param {Boolean} [isSorted=false] A flag to indicate that the `array` is already sorted. + * @param {Function|Object|String} [callback=identity] The function called per + * iteration. If a property name or object is passed, it will be used to create + * a "_.pluck" or "_.where" style callback, respectively. + * @param {Mixed} [thisArg] The `this` binding of `callback`. + * @returns {Array} Returns a duplicate-value-free array. + * @example + * + * _.uniq([1, 2, 1, 3, 1]); + * // => [1, 2, 3] + * + * _.uniq([1, 1, 2, 2, 3], true); + * // => [1, 2, 3] + * + * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return Math.floor(num); }); + * // => [1, 2, 3] + * + * _.uniq([1, 2, 1.5, 3, 2.5], function(num) { return this.floor(num); }, Math); + * // => [1, 2, 3] + * + * // using "_.pluck" callback shorthand + * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); + * // => [{ 'x': 1 }, { 'x': 2 }] + */ + function uniq(array, isSorted, callback, thisArg) { + var index = -1, + length = array ? array.length : 0, + result = [], + seen = result; + + // juggle arguments + if (typeof isSorted == 'function') { + thisArg = callback; + callback = isSorted; + isSorted = false; + } + // init value cache for large arrays + var isLarge = !isSorted && length >= 75; + if (isLarge) { + var cache = {}; + } + if (callback) { + seen = []; + callback = createCallback(callback, thisArg); + } + while (++index < length) { + var value = array[index], + computed = callback ? callback(value, index, array) : value; + + if (isLarge) { + var key = computed + ''; + var inited = hasOwnProperty.call(cache, key) + ? !(seen = cache[key]) + : (seen = cache[key] = []); + } + if (isSorted + ? !index || seen[seen.length - 1] !== computed + : inited || indexOf(seen, computed) < 0 + ) { + if (callback || isLarge) { + seen.push(computed); + } + result.push(value); + } + } + return result; + } + + /** + * Creates an array with all occurrences of the passed values removed using + * strict equality for comparisons, i.e. `===`. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} array The array to filter. + * @param {Mixed} [value1, value2, ...] Values to remove. + * @returns {Array} Returns a new filtered array. + * @example + * + * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1); + * // => [2, 3, 4] + */ + function without(array) { + var index = -1, + length = array ? array.length : 0, + contains = cachedContains(arguments, 1), + result = []; + + while (++index < length) { + var value = array[index]; + if (!contains(value)) { + result.push(value); + } + } + return result; + } + + /** + * Groups the elements of each array at their corresponding indexes. Useful for + * separate data sources that are coordinated through matching array indexes. + * For a matrix of nested arrays, `_.zip.apply(...)` can transpose the matrix + * in a similar fashion. + * + * @static + * @memberOf _ + * @category Arrays + * @param {Array} [array1, array2, ...] Arrays to process. + * @returns {Array} Returns a new array of grouped elements. + * @example + * + * _.zip(['moe', 'larry'], [30, 40], [true, false]); + * // => [['moe', 30, true], ['larry', 40, false]] + */ + function zip(array) { + var index = -1, + length = array ? max(pluck(arguments, 'length')) : 0, + result = Array(length); + + while (++index < length) { + result[index] = pluck(arguments, index); + } + return result; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a function that is restricted to executing `func` only after it is + * called `n` times. The `func` is executed with the `this` binding of the + * created function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Number} n The number of times the function must be called before + * it is executed. + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var renderNotes = _.after(notes.length, render); + * _.forEach(notes, function(note) { + * note.asyncSave({ 'success': renderNotes }); + * }); + * // `renderNotes` is run once, after all notes have saved + */ + function after(n, func) { + if (n < 1) { + return func(); + } + return function() { + if (--n < 1) { + return func.apply(this, arguments); + } + }; + } + + /** + * Creates a function that, when called, invokes `func` with the `this` + * binding of `thisArg` and prepends any additional `bind` arguments to those + * passed to the bound function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to bind. + * @param {Mixed} [thisArg] The `this` binding of `func`. + * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * var func = function(greeting) { + * return greeting + ' ' + this.name; + * }; + * + * func = _.bind(func, { 'name': 'moe' }, 'hi'); + * func(); + * // => 'hi moe' + */ + function bind(func, thisArg) { + // use `Function#bind` if it exists and is fast + // (in V8 `Function#bind` is slower except when partially applied) + return isBindFast || (nativeBind && arguments.length > 2) + ? nativeBind.call.apply(nativeBind, arguments) + : createBound(func, thisArg, slice(arguments, 2)); + } + + /** + * Binds methods on `object` to `object`, overwriting the existing method. + * Method names may be specified as individual arguments or as arrays of method + * names. If no method names are provided, all the function properties of `object` + * will be bound. + * + * @static + * @memberOf _ + * @category Functions + * @param {Object} object The object to bind and assign the bound methods to. + * @param {String} [methodName1, methodName2, ...] Method names on the object to bind. + * @returns {Object} Returns `object`. + * @example + * + * var view = { + * 'label': 'docs', + * 'onClick': function() { alert('clicked ' + this.label); } + * }; + * + * _.bindAll(view); + * jQuery('#docs').on('click', view.onClick); + * // => alerts 'clicked docs', when the button is clicked + */ + function bindAll(object) { + var funcs = concat.apply(arrayRef, arguments), + index = funcs.length > 1 ? 0 : (funcs = functions(object), -1), + length = funcs.length; + + while (++index < length) { + var key = funcs[index]; + object[key] = bind(object[key], object); + } + return object; + } + + /** + * Creates a function that, when called, invokes the method at `object[key]` + * and prepends any additional `bindKey` arguments to those passed to the bound + * function. This method differs from `_.bind` by allowing bound functions to + * reference methods that will be redefined or don't yet exist. + * See http://michaux.ca/articles/lazy-function-definition-pattern. + * + * @static + * @memberOf _ + * @category Functions + * @param {Object} object The object the method belongs to. + * @param {String} key The key of the method. + * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied. + * @returns {Function} Returns the new bound function. + * @example + * + * var object = { + * 'name': 'moe', + * 'greet': function(greeting) { + * return greeting + ' ' + this.name; + * } + * }; + * + * var func = _.bindKey(object, 'greet', 'hi'); + * func(); + * // => 'hi moe' + * + * object.greet = function(greeting) { + * return greeting + ', ' + this.name + '!'; + * }; + * + * func(); + * // => 'hi, moe!' + */ + function bindKey(object, key) { + return createBound(object, key, slice(arguments, 2)); + } + + /** + * Creates a function that is the composition of the passed functions, + * where each function consumes the return value of the function that follows. + * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`. + * Each function is executed with the `this` binding of the composed function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} [func1, func2, ...] Functions to compose. + * @returns {Function} Returns the new composed function. + * @example + * + * var greet = function(name) { return 'hi ' + name; }; + * var exclaim = function(statement) { return statement + '!'; }; + * var welcome = _.compose(exclaim, greet); + * welcome('moe'); + * // => 'hi moe!' + */ + function compose() { + var funcs = arguments; + return function() { + var args = arguments, + length = funcs.length; + + while (length--) { + args = [funcs[length].apply(this, args)]; + } + return args[0]; + }; + } + + /** + * Creates a function that will delay the execution of `func` until after + * `wait` milliseconds have elapsed since the last time it was invoked. Pass + * `true` for `immediate` to cause debounce to invoke `func` on the leading, + * instead of the trailing, edge of the `wait` timeout. Subsequent calls to + * the debounced function will return the result of the last `func` call. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to debounce. + * @param {Number} wait The number of milliseconds to delay. + * @param {Boolean} immediate A flag to indicate execution is on the leading + * edge of the timeout. + * @returns {Function} Returns the new debounced function. + * @example + * + * var lazyLayout = _.debounce(calculateLayout, 300); + * jQuery(window).on('resize', lazyLayout); + */ + function debounce(func, wait, immediate) { + var args, + result, + thisArg, + timeoutId; + + function delayed() { + timeoutId = null; + if (!immediate) { + result = func.apply(thisArg, args); + } + } + return function() { + var isImmediate = immediate && !timeoutId; + args = arguments; + thisArg = this; + + clearTimeout(timeoutId); + timeoutId = setTimeout(delayed, wait); + + if (isImmediate) { + result = func.apply(thisArg, args); + } + return result; + }; + } + + /** + * Executes the `func` function after `wait` milliseconds. Additional arguments + * will be passed to `func` when it is invoked. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to delay. + * @param {Number} wait The number of milliseconds to delay execution. + * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with. + * @returns {Number} Returns the `setTimeout` timeout id. + * @example + * + * var log = _.bind(console.log, console); + * _.delay(log, 1000, 'logged later'); + * // => 'logged later' (Appears after one second.) + */ + function delay(func, wait) { + var args = slice(arguments, 2); + return setTimeout(function() { func.apply(undefined, args); }, wait); + } + + /** + * Defers executing the `func` function until the current call stack has cleared. + * Additional arguments will be passed to `func` when it is invoked. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to defer. + * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the function with. + * @returns {Number} Returns the `setTimeout` timeout id. + * @example + * + * _.defer(function() { alert('deferred'); }); + * // returns from the function before `alert` is called + */ + function defer(func) { + var args = slice(arguments, 1); + return setTimeout(function() { func.apply(undefined, args); }, 1); + } + // use `setImmediate` if it's available in Node.js + if (isV8 && freeModule && typeof setImmediate == 'function') { + defer = bind(setImmediate, window); + } + + /** + * Creates a function that memoizes the result of `func`. If `resolver` is + * passed, it will be used to determine the cache key for storing the result + * based on the arguments passed to the memoized function. By default, the first + * argument passed to the memoized function is used as the cache key. The `func` + * is executed with the `this` binding of the memoized function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to have its output memoized. + * @param {Function} [resolver] A function used to resolve the cache key. + * @returns {Function} Returns the new memoizing function. + * @example + * + * var fibonacci = _.memoize(function(n) { + * return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2); + * }); + */ + function memoize(func, resolver) { + var cache = {}; + return function() { + var key = (resolver ? resolver.apply(this, arguments) : arguments[0]) + ''; + return hasOwnProperty.call(cache, key) + ? cache[key] + : (cache[key] = func.apply(this, arguments)); + }; + } + + /** + * Creates a function that is restricted to execute `func` once. Repeat calls to + * the function will return the value of the first call. The `func` is executed + * with the `this` binding of the created function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to restrict. + * @returns {Function} Returns the new restricted function. + * @example + * + * var initialize = _.once(createApplication); + * initialize(); + * initialize(); + * // `initialize` executes `createApplication` once + */ + function once(func) { + var ran, + result; + + return function() { + if (ran) { + return result; + } + ran = true; + result = func.apply(this, arguments); + + // clear the `func` variable so the function may be garbage collected + func = null; + return result; + }; + } + + /** + * Creates a function that, when called, invokes `func` with any additional + * `partial` arguments prepended to those passed to the new function. This + * method is similar to `_.bind`, except it does **not** alter the `this` binding. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to partially apply arguments to. + * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * var greet = function(greeting, name) { return greeting + ' ' + name; }; + * var hi = _.partial(greet, 'hi'); + * hi('moe'); + * // => 'hi moe' + */ + function partial(func) { + return createBound(func, slice(arguments, 1)); + } + + /** + * This method is similar to `_.partial`, except that `partial` arguments are + * appended to those passed to the new function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to partially apply arguments to. + * @param {Mixed} [arg1, arg2, ...] Arguments to be partially applied. + * @returns {Function} Returns the new partially applied function. + * @example + * + * var defaultsDeep = _.partialRight(_.merge, _.defaults); + * + * var options = { + * 'variable': 'data', + * 'imports': { 'jq': $ } + * }; + * + * defaultsDeep(options, _.templateSettings); + * + * options.variable + * // => 'data' + * + * options.imports + * // => { '_': _, 'jq': $ } + */ + function partialRight(func) { + return createBound(func, slice(arguments, 1), null, indicatorObject); + } + + /** + * Creates a function that, when executed, will only call the `func` + * function at most once per every `wait` milliseconds. If the throttled + * function is invoked more than once during the `wait` timeout, `func` will + * also be called on the trailing edge of the timeout. Subsequent calls to the + * throttled function will return the result of the last `func` call. + * + * @static + * @memberOf _ + * @category Functions + * @param {Function} func The function to throttle. + * @param {Number} wait The number of milliseconds to throttle executions to. + * @returns {Function} Returns the new throttled function. + * @example + * + * var throttled = _.throttle(updatePosition, 100); + * jQuery(window).on('scroll', throttled); + */ + function throttle(func, wait) { + var args, + result, + thisArg, + timeoutId, + lastCalled = 0; + + function trailingCall() { + lastCalled = new Date; + timeoutId = null; + result = func.apply(thisArg, args); + } + return function() { + var now = new Date, + remaining = wait - (now - lastCalled); + + args = arguments; + thisArg = this; + + if (remaining <= 0) { + clearTimeout(timeoutId); + timeoutId = null; + lastCalled = now; + result = func.apply(thisArg, args); + } + else if (!timeoutId) { + timeoutId = setTimeout(trailingCall, remaining); + } + return result; + }; + } + + /** + * Creates a function that passes `value` to the `wrapper` function as its + * first argument. Additional arguments passed to the function are appended + * to those passed to the `wrapper` function. The `wrapper` is executed with + * the `this` binding of the created function. + * + * @static + * @memberOf _ + * @category Functions + * @param {Mixed} value The value to wrap. + * @param {Function} wrapper The wrapper function. + * @returns {Function} Returns the new function. + * @example + * + * var hello = function(name) { return 'hello ' + name; }; + * hello = _.wrap(hello, function(func) { + * return 'before, ' + func('moe') + ', after'; + * }); + * hello(); + * // => 'before, hello moe, after' + */ + function wrap(value, wrapper) { + return function() { + var args = [value]; + push.apply(args, arguments); + return wrapper.apply(this, args); + }; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their + * corresponding HTML entities. + * + * @static + * @memberOf _ + * @category Utilities + * @param {String} string The string to escape. + * @returns {String} Returns the escaped string. + * @example + * + * _.escape('Moe, Larry & Curly'); + * // => 'Moe, Larry & Curly' + */ + function escape(string) { + return string == null ? '' : (string + '').replace(reUnescapedHtml, escapeHtmlChar); + } + + /** + * This function returns the first argument passed to it. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Mixed} value Any value. + * @returns {Mixed} Returns `value`. + * @example + * + * var moe = { 'name': 'moe' }; + * moe === _.identity(moe); + * // => true + */ + function identity(value) { + return value; + } + + /** + * Adds functions properties of `object` to the `lodash` function and chainable + * wrapper. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Object} object The object of function properties to add to `lodash`. + * @example + * + * _.mixin({ + * 'capitalize': function(string) { + * return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase(); + * } + * }); + * + * _.capitalize('moe'); + * // => 'Moe' + * + * _('moe').capitalize(); + * // => 'Moe' + */ + function mixin(object) { + forEach(functions(object), function(methodName) { + var func = lodash[methodName] = object[methodName]; + + lodash.prototype[methodName] = function() { + var args = [this.__wrapped__]; + push.apply(args, arguments); + return new lodash(func.apply(lodash, args)); + }; + }); + } + + /** + * Reverts the '_' variable to its previous value and returns a reference to + * the `lodash` function. + * + * @static + * @memberOf _ + * @category Utilities + * @returns {Function} Returns the `lodash` function. + * @example + * + * var lodash = _.noConflict(); + */ + function noConflict() { + window._ = oldDash; + return this; + } + + /** + * Produces a random number between `min` and `max` (inclusive). If only one + * argument is passed, a number between `0` and the given number will be returned. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Number} [min=0] The minimum possible value. + * @param {Number} [max=1] The maximum possible value. + * @returns {Number} Returns a random number. + * @example + * + * _.random(0, 5); + * // => a number between 0 and 5 + * + * _.random(5); + * // => also a number between 0 and 5 + */ + function random(min, max) { + if (min == null && max == null) { + max = 1; + } + min = +min || 0; + if (max == null) { + max = min; + min = 0; + } + return min + floor(nativeRandom() * ((+max || 0) - min + 1)); + } + + /** + * Resolves the value of `property` on `object`. If `property` is a function, + * it will be invoked and its result returned, else the property value is + * returned. If `object` is falsey, then `null` is returned. + * + * @static + * @memberOf _ + * @category Utilities + * @param {Object} object The object to inspect. + * @param {String} property The property to get the value of. + * @returns {Mixed} Returns the resolved value. + * @example + * + * var object = { + * 'cheese': 'crumpets', + * 'stuff': function() { + * return 'nonsense'; + * } + * }; + * + * _.result(object, 'cheese'); + * // => 'crumpets' + * + * _.result(object, 'stuff'); + * // => 'nonsense' + */ + function result(object, property) { + var value = object ? object[property] : undefined; + return isFunction(value) ? object[property]() : value; + } + + /** + * A micro-templating method that handles arbitrary delimiters, preserves + * whitespace, and correctly escapes quotes within interpolated code. + * + * Note: In the development build, `_.template` utilizes sourceURLs for easier + * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl + * + * Note: Lo-Dash may be used in Chrome extensions by either creating a `lodash csp` + * build and using precompiled templates, or loading Lo-Dash in a sandbox. + * + * For more information on precompiling templates see: + * http://lodash.com/#custom-builds + * + * For more information on Chrome extension sandboxes see: + * http://developer.chrome.com/stable/extensions/sandboxingEval.html + * + * @static + * @memberOf _ + * @category Utilities + * @param {String} text The template text. + * @param {Obect} data The data object used to populate the text. + * @param {Object} options The options object. + * escape - The "escape" delimiter regexp. + * evaluate - The "evaluate" delimiter regexp. + * interpolate - The "interpolate" delimiter regexp. + * sourceURL - The sourceURL of the template's compiled source. + * variable - The data object variable name. + * + * @returns {Function|String} Returns a compiled function when no `data` object + * is given, else it returns the interpolated text. + * @example + * + * // using a compiled template + * var compiled = _.template('hello <%= name %>'); + * compiled({ 'name': 'moe' }); + * // => 'hello moe' + * + * var list = '<% _.forEach(people, function(name) { %>
  • <%= name %>
  • <% }); %>'; + * _.template(list, { 'people': ['moe', 'larry'] }); + * // => '
  • moe
  • larry
  • ' + * + * // using the "escape" delimiter to escape HTML in data property values + * _.template('<%- value %>', { 'value': '\n```\n\nUsing [`npm`](http://npmjs.org/):\n\n```bash\nnpm install lodash\n\nnpm install -g lodash\nnpm link lodash\n```\n\nTo avoid potential issues, update `npm` before installing Lo-Dash:\n\n```bash\nnpm install npm -g\n```\n\nIn [Node.js](http://nodejs.org/) and [RingoJS v0.8.0+](http://ringojs.org/):\n\n```js\nvar _ = require('lodash');\n\n// or as a drop-in replacement for Underscore\nvar _ = require('lodash/lodash.underscore');\n```\n\n**Note:** If Lo-Dash is installed globally, run [`npm link lodash`](http://blog.nodejs.org/2011/03/23/npm-1-0-global-vs-local-installation/) in your project’s root directory before requiring it.\n\nIn [RingoJS v0.7.0-](http://ringojs.org/):\n\n```js\nvar _ = require('lodash')._;\n```\n\nIn [Rhino](http://www.mozilla.org/rhino/):\n\n```js\nload('lodash.js');\n```\n\nIn an AMD loader like [RequireJS](http://requirejs.org/):\n\n```js\nrequire({\n 'paths': {\n 'underscore': 'path/to/lodash'\n }\n},\n['underscore'], function(_) {\n console.log(_.VERSION);\n});\n```\n\n## Release Notes\n\n### v1.0.1\n\n * Add support for specifying source map URLs in `-p`/`--source-map` build options\n * Ensured the second argument passed to `_.assign` is not treated as a `callback`\n * Ensured `-p`/`--source-map` build options correctly set the `sourceMappingURL`\n * Made `-p`/`--source-map` build options set source map *“sources”* keys based on the builds performed\n * Made `_.defer` use `setImmediate`, in Node.js, when available\n * Made `_.where` search arrays for values regardless of their index position\n * Removed dead code from `_.template`\n\nThe full changelog is available [here](https://github.com/bestiejs/lodash/wiki/Changelog).\n\n## BestieJS\n\nLo-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.\n\n## Author\n\n* [John-David Dalton](http://allyoucanleet.com/)\n [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](https://twitter.com/jdalton \"Follow @jdalton on Twitter\")\n\n## Contributors\n\n* [Kit Cambridge](http://kitcambridge.github.com/)\n [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge \"Follow @kitcambridge on Twitter\")\n* [Mathias Bynens](http://mathiasbynens.be/)\n [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias \"Follow @mathias on Twitter\")\n", + "readmeFilename": "README.md", + "_id": "lodash@1.0.1", + "_from": "lodash@~1.0.1" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/perf/perf.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/perf/perf.js new file mode 100644 index 0000000..4ff9cf5 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/perf/perf.js @@ -0,0 +1,1724 @@ +(function(window) { + + /** Use a single "load" function */ + var load = typeof require == 'function' ? require : window.load; + + /** The file path of the Lo-Dash file to test */ + var filePath = (function() { + var min = 0; + var result = window.phantom + ? phantom.args + : (window.system + ? (min = 1, system.args) + : (window.process ? (min = 2, process.argv) : (window.arguments || [])) + ); + + var last = result[result.length - 1]; + result = (result.length > min && last != 'test.js') ? last : '../lodash.js'; + + try { + result = require('fs').realpathSync(result); + } catch(e) { } + + return result; + }()); + + /** Load Benchmark.js */ + var Benchmark = + window.Benchmark || ( + Benchmark = load('../vendor/benchmark.js/benchmark.js') || window.Benchmark, + Benchmark.Benchmark || Benchmark + ); + + /** Load Lo-Dash */ + var lodash = + window.lodash || ( + lodash = load(filePath) || window._, + lodash = lodash._ || lodash, + lodash.noConflict() + ); + + /** Load Underscore */ + var _ = + window._ || ( + _ = load('../vendor/underscore/underscore.js') || window._, + _._ || _ + ); + + /** Used to access the Firebug Lite panel (set by `run`) */ + var fbPanel; + + /** Used to score performance */ + var score = { 'a': 0, 'b': 0 }; + + /** Used to queue benchmark suites */ + var suites = []; + + /** The `ui` object */ + var ui = window.ui || { + 'buildPath': basename(filePath, '.js'), + 'otherPath': 'underscore' + }; + + /** The Lo-Dash build basename */ + var buildName = basename(ui.buildPath, '.js'); + + /** The other library basename */ + var otherName = basename(ui.otherPath, '.js'); + + /** Expose functions to the global object */ + window._ = _; + window.Benchmark = Benchmark; + window.lodash = lodash; + + /** Add `console.log()` support for Narwhal and RingoJS */ + if (!window.console && window.print) { + window.console = { 'log': window.print }; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Gets the basename of the given `filePath`. If the file `extension` is passed, + * it will be removed from the basename. + * + * @private + * @param {String} path The file path to inspect. + * @param {String} extension The extension to remove. + * @returns {String} Returns the basename. + */ + function basename(filePath, extension) { + var result = (filePath || '').split(/[\\/]/).pop(); + return arguments.length < 2 + ? result + : result.replace(RegExp(extension.replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&') + '$'), ''); + } + + /** + * Gets the Hz, i.e. operations per second, of `bench` adjusted for the + * margin of error. + * + * @private + * @param {Object} bench The benchmark object. + * @returns {Number} Returns the adjusted Hz. + */ + function getHz(bench) { + var result = 1 / (bench.stats.mean + bench.stats.moe); + return isFinite(result) ? result : 0; + } + + /** + * Logs text to the console. + * + * @private + * @param {String} text The text to log. + */ + function log(text) { + console.log(text + ''); + if (fbPanel) { + // scroll the Firebug Lite panel down + fbPanel.scrollTop = fbPanel.scrollHeight; + } + } + + /** + * Runs all benchmark suites. + * + * @private (@public in the browser) + */ + function run() { + fbPanel = (fbPanel = window.document && document.getElementById('FirebugUI')) && + (fbPanel = (fbPanel = fbPanel.contentWindow || fbPanel.contentDocument).document || fbPanel) && + fbPanel.getElementById('fbPanel1'); + + log('\nSit back and relax, this may take a while.'); + suites[0].run(); + } + + /*--------------------------------------------------------------------------*/ + + lodash.extend(Benchmark.Suite.options, { + 'onStart': function() { + log('\n' + this.name + ':'); + }, + 'onCycle': function(event) { + log(event.target); + }, + 'onComplete': function() { + var formatNumber = Benchmark.formatNumber, + fastest = this.filter('fastest'), + fastestHz = getHz(fastest[0]), + slowest = this.filter('slowest'), + slowestHz = getHz(slowest[0]), + aHz = getHz(this[0]), + bHz = getHz(this[1]); + + if (fastest.length > 1) { + log('It\'s too close to call.'); + aHz = bHz = slowestHz; + } + else { + var percent = ((fastestHz / slowestHz) - 1) * 100; + + log( + fastest[0].name + ' is ' + + formatNumber(percent < 1 ? percent.toFixed(2) : Math.round(percent)) + + '% faster.' + ); + } + // add score adjusted for margin of error + score.a += aHz; + score.b += bHz; + + // remove current suite from queue + suites.shift(); + + if (suites.length) { + // run next suite + suites[0].run(); + } + else { + var fastestTotalHz = Math.max(score.a, score.b), + slowestTotalHz = Math.min(score.a, score.b), + totalPercent = formatNumber(Math.round(((fastestTotalHz / slowestTotalHz) - 1) * 100)), + totalX = fastestTotalHz / slowestTotalHz, + message = 'is ' + totalPercent + '% ' + (totalX == 1 ? '' : '(' + formatNumber(totalX.toFixed(2)) + 'x) ') + 'faster than'; + + // report results + if (score.a >= score.b) { + log('\n' + buildName + ' ' + message + ' ' + otherName + '.'); + } else { + log('\n' + otherName + ' ' + message + ' ' + buildName + '.'); + } + } + } + }); + + /*--------------------------------------------------------------------------*/ + + lodash.extend(Benchmark.options, { + 'async': true, + 'setup': '\ + var window = Function("return this || global")(),\ + _ = window._,\ + lodash = window.lodash,\ + belt = this.name == "Lo-Dash" ? lodash : _;\ + \ + var index,\ + date = new Date,\ + limit = 20,\ + regexp = /x/,\ + object = {},\ + objects = Array(limit),\ + numbers = Array(limit),\ + fourNumbers = [5, 25, 10, 30],\ + nestedNumbers = [1, [2], [3, [[4]]]],\ + twoNumbers = [12, 23];\ + \ + for (index = 0; index < limit; index++) {\ + numbers[index] = index;\ + object["key" + index] = index;\ + objects[index] = { "num": index };\ + }\ + \ + if (typeof bind != "undefined") {\ + var contextObject = { "name": "moe" },\ + ctor = function() {};\ + \ + var func = function(greeting, punctuation) {\ + return greeting + ", " + this.name + (punctuation || ".");\ + };\ + \ + var lodashBoundNormal = lodash.bind(func, contextObject),\ + lodashBoundPartial = lodash.bind(func, contextObject, "hi");\ + \ + var _boundNormal = _.bind(func, contextObject),\ + _boundPartial = _.bind(func, contextObject, "hi");\ + }\ + \ + if (typeof bindAll != "undefined") {\ + var bindAllObjects = Array(this.count),\ + funcNames = belt.functions(lodash);\ + \ + // potentially expensive\n\ + for (index = 0; index < this.count; index++) {\ + bindAllObjects[index] = belt.reduce(funcNames, function(object, funcName) {\ + object[funcName] = lodash[funcName];\ + return object;\ + }, {});\ + }\ + }\ + if (typeof compact != "undefined") {\ + var uncompacted = numbers.slice();\ + uncompacted[2] = false;\ + uncompacted[6] = null;\ + uncompacted[18] = "";\ + }\ + \ + if (typeof countBy != "undefined" || typeof omit != "undefined") {\ + var wordToNumber = {\ + "one": 1,\ + "two": 2,\ + "three": 3,\ + "four": 4,\ + "five": 5,\ + "six": 6,\ + "seven": 7,\ + "eight": 8,\ + "nine": 9,\ + "ten": 10,\ + "eleven": 11,\ + "twelve": 12,\ + "thirteen": 13,\ + "fourteen": 14,\ + "fifteen": 15,\ + "sixteen": 16,\ + "seventeen": 17,\ + "eighteen": 18,\ + "nineteen": 19,\ + "twenty": 20,\ + "twenty-one": 21,\ + "twenty-two": 22,\ + "twenty-three": 23,\ + "twenty-four": 24,\ + "twenty-five": 25,\ + "twenty-six": 26,\ + "twenty-seven": 27,\ + "twenty-eight": 28,\ + "twenty-nine": 29,\ + "thirty": 30,\ + "thirty-one": 31,\ + "thirty-two": 32,\ + "thirty-three": 33,\ + "thirty-four": 34,\ + "thirty-five": 35,\ + "thirty-six": 36,\ + "thirty-seven": 37,\ + "thirty-eight": 38,\ + "thirty-nine": 39,\ + "forty": 40\ + };\ + \ + var words = belt.keys(wordToNumber).slice(0, limit);\ + }\ + \ + if (typeof isEqual != "undefined") {\ + var objectOfPrimitives = {\ + "boolean": true,\ + "number": 1,\ + "string": "a"\ + };\ + \ + var objectOfObjects = {\ + "boolean": new Boolean(true),\ + "number": new Number(1),\ + "string": new String("a")\ + };\ + \ + var object2 = {},\ + objects2 = Array(limit),\ + numbers2 = Array(limit),\ + nestedNumbers2 = [1, [2], [3, [[4]]]],\ + nestedNumbers3 = [1, [2], [5, [[6]]]],\ + simpleObject = { "a": 1 },\ + simpleObject2 = { "a": 2 },\ + simpleObjects = [simpleObject],\ + simpleObjects2 = [simpleObject2],\ + twoNumbers2 = [18, 27];\ + \ + for (index = 0; index < limit; index++) {\ + object2["key" + index] = index;\ + objects2[index] = { "num": index };\ + numbers2[index] = index;\ + }\ + }\ + \ + if (typeof multiArrays != "undefined") {\ + var twentyValues = Array(20),\ + twentyValues2 = Array(20),\ + twentyFiveValues = Array(25),\ + twentyFiveValues2 = Array(25),\ + thirtyValues = Array(30),\ + thirtyValues2 = Array(30),\ + fortyValues = Array(40),\ + fortyValues2 = Array(40),\ + fiftyValues = Array(50),\ + fiftyValues2 = Array(50),\ + seventyFiveValues = Array(75),\ + seventyFiveValues2 = Array(75),\ + hundredValues = Array(100),\ + hundredValues2 = Array(100),\ + lowerChars = "abcdefghijklmnopqrstuvwxyz".split(""),\ + upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");\ + \ + for (index = 0; index < 100; index++) {\ + if (index < 15) {\ + twentyValues[index] = lowerChars[index];\ + twentyValues2[index] = upperChars[index];\ + }\ + if (index < 20) {\ + twentyValues[index] =\ + twentyValues2[index] = index;\ + \ + twentyFiveValues[index] = lowerChars[index];\ + twentyFiveValues2[index] = upperChars[index];\ + }\ + if (index < 25) {\ + twentyFiveValues[index] =\ + twentyFiveValues2[index] = index;\ + \ + thirtyValues[index] =\ + fortyValues[index] =\ + fiftyValues[index] =\ + seventyFiveValues[index] =\ + hundredValues[index] = lowerChars[index];\ + \ + thirtyValues2[index] =\ + fortyValues2[index] =\ + fiftyValues2[index] =\ + seventyFiveValues2[index] =\ + hundredValues2[index] = upperChars[index];\ + }\ + else {\ + if (index < 30) {\ + thirtyValues[index] =\ + thirtyValues2[index] = index;\ + }\ + if (index < 40) {\ + fortyValues[index] =\ + fortyValues2[index] = index;\ + }\ + if (index < 50) {\ + fiftyValues[index] =\ + fiftyValues2[index] = index;\ + }\ + if (index < 75) {\ + seventyFiveValues[index] =\ + seventyFiveValues2[index] = index;\ + }\ + hundredValues[index] =\ + hundredValues2[index] = index;\ + }\ + }\ + }\ + \ + if (typeof template != "undefined") {\ + var tplData = {\ + "header1": "Header1",\ + "header2": "Header2",\ + "header3": "Header3",\ + "header4": "Header4",\ + "header5": "Header5",\ + "header6": "Header6",\ + "list": ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]\ + };\ + \ + var tpl =\ + "
    " +\ + "

    <%= header1 %>

    " +\ + "

    <%= header2 %>

    " +\ + "

    <%= header3 %>

    " +\ + "

    <%= header4 %>

    " +\ + "
    <%= header5 %>
    " +\ + "
    <%= header6 %>
    " +\ + "
      " +\ + "<% for (var index = 0, length = list.length; index < length; index++) { %>" +\ + "
    • <%= list[index] %>
    • " +\ + "<% } %>" +\ + "
    " +\ + "
    ";\ + \ + var tplVerbose =\ + "
    " +\ + "

    <%= data.header1 %>

    " +\ + "

    <%= data.header2 %>

    " +\ + "

    <%= data.header3 %>

    " +\ + "

    <%= data.header4 %>

    " +\ + "
    <%= data.header5 %>
    " +\ + "
    <%= data.header6 %>
    " +\ + "
      " +\ + "<% for (var index = 0, length = data.list.length; index < length; index++) { %>" +\ + "
    • <%= data.list[index] %>
    • " +\ + "<% } %>" +\ + "
    " +\ + "
    ";\ + \ + var settingsObject = { "variable": "data" };\ + \ + var lodashTpl = lodash.template(tpl),\ + lodashTplVerbose = lodash.template(tplVerbose, null, settingsObject);\ + \ + var _tpl = _.template(tpl),\ + _tplVerbose = _.template(tplVerbose, null, settingsObject);\ + }' + }); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.bind` (uses native `Function#bind` if available and inferred fast)') + .add(buildName, { + 'fn': 'lodash.bind(func, { "name": "moe" }, "hi")', + 'teardown': 'function bind(){}' + }) + .add(otherName, { + 'fn': '_.bind(func, { "name": "moe" }, "hi")', + 'teardown': 'function bind(){}' + }) + ); + + suites.push( + Benchmark.Suite('bound call') + .add(buildName, { + 'fn': 'lodashBoundNormal()', + 'teardown': 'function bind(){}' + }) + .add(otherName, { + 'fn': '_boundNormal()', + 'teardown': 'function bind(){}' + }) + ); + + suites.push( + Benchmark.Suite('bound call with arguments') + .add(buildName, { + 'fn': 'lodashBoundNormal("hi", "!")', + 'teardown': 'function bind(){}' + }) + .add(otherName, { + 'fn': '_boundNormal("hi", "!")', + 'teardown': 'function bind(){}' + }) + ); + + suites.push( + Benchmark.Suite('bound and partially applied call (uses native `Function#bind` if available)') + .add(buildName, { + 'fn': 'lodashBoundPartial()', + 'teardown': 'function bind(){}' + }) + .add(otherName, { + 'fn': '_boundPartial()', + 'teardown': 'function bind(){}' + }) + ); + + suites.push( + Benchmark.Suite('bound and partially applied call with arguments (uses native `Function#bind` if available)') + .add(buildName, { + 'fn': 'lodashBoundPartial("!")', + 'teardown': 'function bind(){}' + }) + .add(otherName, { + 'fn': '_boundPartial("!")', + 'teardown': 'function bind(){}' + }) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.bindAll` iterating arguments') + .add(buildName, { + 'fn': 'lodash.bindAll.apply(lodash, [bindAllObjects.pop()].concat(funcNames))', + 'teardown': 'function bindAll(){}' + }) + .add(otherName, { + 'fn': '_.bindAll.apply(_, [bindAllObjects.pop()].concat(funcNames))', + 'teardown': 'function bindAll(){}' + }) + ); + + suites.push( + Benchmark.Suite('`_.bindAll` iterating the `object`') + .add(buildName, { + 'fn': 'lodash.bindAll(bindAllObjects.pop())', + 'teardown': 'function bindAll(){}' + }) + .add(otherName, { + 'fn': '_.bindAll(bindAllObjects.pop())', + 'teardown': 'function bindAll(){}' + }) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.clone` with an object') + .add(buildName, '\ + lodash.clone(object)' + ) + .add(otherName, '\ + _.clone(object)' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.compact`') + .add(buildName, { + 'fn': 'lodash.compact(uncompacted)', + 'teardown': 'function compact(){}' + }) + .add(otherName, { + 'fn': '_.compact(uncompacted)', + 'teardown': 'function compact(){}' + }) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.contains` iterating an array') + .add(buildName, '\ + lodash.contains(numbers, 19)' + ) + .add(otherName, '\ + _.contains(numbers, 19)' + ) + ); + + suites.push( + Benchmark.Suite('`_.contains` iterating an object') + .add(buildName, '\ + lodash.contains(object, 19)' + ) + .add(otherName, '\ + _.contains(object, 19)' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.countBy` with `callback` iterating an array') + .add(buildName, '\ + lodash.countBy(numbers, function(num) { return num >> 1; })' + ) + .add(otherName, '\ + _.countBy(numbers, function(num) { return num >> 1; })' + ) + ); + + suites.push( + Benchmark.Suite('`_.countBy` with `property` name iterating an array') + .add(buildName, { + 'fn': 'lodash.countBy(words, "length")', + 'teardown': 'function countBy(){}' + }) + .add(otherName, { + 'fn': '_.countBy(words, "length")', + 'teardown': 'function countBy(){}' + }) + ); + + suites.push( + Benchmark.Suite('`_.countBy` with `callback` iterating an object') + .add(buildName, { + 'fn': 'lodash.countBy(wordToNumber, function(num) { return num >> 1; })', + 'teardown': 'function countBy(){}' + }) + .add(otherName, { + 'fn': '_.countBy(wordToNumber, function(num) { return num >> 1; })', + 'teardown': 'function countBy(){}' + }) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.defaults`') + .add(buildName, '\ + lodash.defaults({ "key2": 2, "key6": 6, "key18": 18 }, object)' + ) + .add(otherName, '\ + _.defaults({ "key2": 2, "key6": 6, "key18": 18 }, object)' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.difference`') + .add(buildName, '\ + lodash.difference(numbers, twoNumbers, fourNumbers)' + ) + .add(otherName, '\ + _.difference(numbers, twoNumbers, fourNumbers)' + ) + ); + + suites.push( + Benchmark.Suite('`_.difference` iterating 30 elements') + .add(buildName, { + 'fn': 'lodash.difference(thirtyValues, thirtyValues2)', + 'teardown': 'function multiArrays(){}' + }) + .add(otherName, { + 'fn': '_.difference(thirtyValues, thirtyValues2)', + 'teardown': 'function multiArrays(){}' + }) + ); + + suites.push( + Benchmark.Suite('`_.difference` iterating 20 and 40 elements') + .add(buildName, { + 'fn': 'lodash.difference(twentyValues, fortyValues2)', + 'teardown': 'function multiArrays(){}' + }) + .add(otherName, { + 'fn': '_.difference(twentyValues, fortyValues2)', + 'teardown': 'function multiArrays(){}' + }) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.each` iterating an array') + .add(buildName, '\ + var result = [];\ + lodash.each(numbers, function(num) {\ + result.push(num * 2);\ + })' + ) + .add(otherName, '\ + var result = [];\ + _.each(numbers, function(num) {\ + result.push(num * 2);\ + })' + ) + ); + + suites.push( + Benchmark.Suite('`_.each` iterating an array with `thisArg` (slow path)') + .add(buildName, '\ + var result = [];\ + lodash.each(numbers, function(num, index) {\ + result.push(num + this["key" + index]);\ + }, object)' + ) + .add(otherName, '\ + var result = [];\ + _.each(numbers, function(num, index) {\ + result.push(num + this["key" + index]);\ + }, object)' + ) + ); + + suites.push( + Benchmark.Suite('`_.each` iterating an object') + .add(buildName, '\ + var result = [];\ + lodash.each(object, function(num) {\ + result.push(num * 2);\ + })' + ) + .add(otherName, '\ + var result = [];\ + _.each(object, function(num) {\ + result.push(num * 2);\ + })' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.every` iterating an array') + .add(buildName, '\ + lodash.every(numbers, function(num) {\ + return num + "";\ + })' + ) + .add(otherName, '\ + _.every(numbers, function(num) {\ + return num + "";\ + })' + ) + ); + + suites.push( + Benchmark.Suite('`_.every` iterating an object') + .add(buildName, '\ + lodash.every(object, function(num) {\ + return num + "";\ + })' + ) + .add(otherName, '\ + _.every(object, function(num) {\ + return num + "";\ + })' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.extend`') + .add(buildName, '\ + lodash.extend({}, object)' + ) + .add(otherName, '\ + _.extend({}, object)' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.filter` iterating an array') + .add(buildName, '\ + lodash.filter(numbers, function(num) {\ + return num % 2;\ + })' + ) + .add(otherName, '\ + _.filter(numbers, function(num) {\ + return num % 2;\ + })' + ) + ); + + suites.push( + Benchmark.Suite('`_.filter` iterating an array with `thisArg` (slow path)') + .add(buildName, '\ + lodash.filter(numbers, function(num, index) {\ + return this["key" + index] % 2;\ + }, object)' + ) + .add(otherName, '\ + _.filter(numbers, function(num, index) {\ + return this["key" + index] % 2;\ + }, object)' + ) + ); + + suites.push( + Benchmark.Suite('`_.filter` iterating an object') + .add(buildName, '\ + lodash.filter(object, function(num) {\ + return num % 2\ + })' + ) + .add(otherName, '\ + _.filter(object, function(num) {\ + return num % 2\ + })' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.find` iterating an array') + .add(buildName, '\ + lodash.find(numbers, function(num) {\ + return num === 19;\ + })' + ) + .add(otherName, '\ + _.find(numbers, function(num) {\ + return num === 19;\ + })' + ) + ); + + suites.push( + Benchmark.Suite('`_.find` iterating an object') + .add(buildName, '\ + lodash.find(object, function(value, key) {\ + return /\D9$/.test(key);\ + })' + ) + .add(otherName, '\ + _.find(object, function(value, key) {\ + return /\D9$/.test(key);\ + })' + ) + ); + + suites.push( + Benchmark.Suite('`_.find` with `properties`') + .add(buildName, '\ + lodash.find(objects, { "num": 9 });' + ) + .add(otherName, '\ + _.findWhere(objects, { "num": 9 });' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.flatten`') + .add(buildName, '\ + lodash.flatten(nestedNumbers)' + ) + .add(otherName, '\ + _.flatten(nestedNumbers)' + ) + ); + + suites.push( + Benchmark.Suite('`_.flatten` with `shallow`') + .add(buildName, '\ + lodash.flatten(nestedNumbers, true)' + ) + .add(otherName, '\ + _.flatten(nestedNumbers, true)' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.functions`') + .add(buildName, '\ + lodash.functions(lodash)' + ) + .add(otherName, '\ + _.functions(lodash)' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.groupBy` with `callback` iterating an array') + .add(buildName, '\ + lodash.groupBy(numbers, function(num) { return num >> 1; })' + ) + .add(otherName, '\ + _.groupBy(numbers, function(num) { return num >> 1; })' + ) + ); + + suites.push( + Benchmark.Suite('`_.groupBy` with `property` name iterating an array') + .add(buildName, { + 'fn': 'lodash.groupBy(words, "length")', + 'teardown': 'function countBy(){}' + }) + .add(otherName, { + 'fn': '_.groupBy(words, "length")', + 'teardown': 'function countBy(){}' + }) + ); + + suites.push( + Benchmark.Suite('`_.groupBy` with `callback` iterating an object') + .add(buildName, { + 'fn': 'lodash.groupBy(wordToNumber, function(num) { return num >> 1; })', + 'teardown': 'function countBy(){}' + }) + .add(otherName, { + 'fn': '_.groupBy(wordToNumber, function(num) { return num >> 1; })', + 'teardown': 'function countBy(){}' + }) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.indexOf`') + .add(buildName, '\ + lodash.indexOf(numbers, 9)' + ) + .add(otherName, '\ + _.indexOf(numbers, 9)' + ) + ); + + suites.push( + Benchmark.Suite('`_.indexOf` with `isSorted`') + .add(buildName, '\ + lodash.indexOf(numbers, 19, true)' + ) + .add(otherName, '\ + _.indexOf(numbers, 19, true)' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.intersection`') + .add(buildName, '\ + lodash.intersection(numbers, twoNumbers, fourNumbers)' + ) + .add(otherName, '\ + _.intersection(numbers, twoNumbers, fourNumbers)' + ) + ); + + suites.push( + Benchmark.Suite('`_.intersection` iterating 100 elements') + .add(buildName, { + 'fn': 'lodash.intersection(hundredValues, hundredValues2)', + 'teardown': 'function multiArrays(){}' + }) + .add(otherName, { + 'fn': '_.intersection(hundredValues, hundredValues2)', + 'teardown': 'function multiArrays(){}' + }) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.invert`') + .add(buildName, '\ + lodash.invert(object)' + ) + .add(otherName, '\ + _.invert(object)' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.invoke` iterating an array') + .add(buildName, '\ + lodash.invoke(numbers, "toFixed", "2")' + ) + .add(otherName, '\ + _.invoke(numbers, "toFixed", "2")' + ) + ); + + suites.push( + Benchmark.Suite('`_.invoke` with a function for `methodName` iterating an array') + .add(buildName, '\ + lodash.invoke(numbers, String.prototype.split, "")' + ) + .add(otherName, '\ + _.invoke(numbers, String.prototype.split, "")' + ) + ); + + suites.push( + Benchmark.Suite('`_.invoke` iterating an object') + .add(buildName, '\ + lodash.invoke(object, "toFixed", "2")' + ) + .add(otherName, '\ + _.invoke(object, "toFixed", "2")' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.isEqual` comparing primitives and objects (edge case)') + .add(buildName, { + 'fn': 'lodash.isEqual(objectOfPrimitives, objectOfObjects)', + 'teardown': 'function isEqual(){}' + }) + .add(otherName, { + 'fn': '_.isEqual(objectOfPrimitives, objectOfObjects)', + 'teardown': 'function isEqual(){}' + }) + ); + + suites.push( + Benchmark.Suite('`_.isEqual` comparing arrays') + .add(buildName, { + 'fn': '\ + lodash.isEqual(numbers, numbers2);\ + lodash.isEqual(twoNumbers, twoNumbers2);', + 'teardown': 'function isEqual(){}' + }) + .add(otherName, { + 'fn': '\ + _.isEqual(numbers, numbers2);\ + _.isEqual(twoNumbers, twoNumbers2);', + 'teardown': 'function isEqual(){}' + }) + ); + + suites.push( + Benchmark.Suite('`_.isEqual` comparing nested arrays') + .add(buildName, { + 'fn': '\ + lodash.isEqual(nestedNumbers, nestedNumbers2);\ + lodash.isEqual(nestedNumbers2, nestedNumbers3);', + 'teardown': 'function isEqual(){}' + }) + .add(otherName, { + 'fn': '\ + _.isEqual(nestedNumbers, nestedNumbers2);\ + _.isEqual(nestedNumbers2, nestedNumbers3);', + 'teardown': 'function isEqual(){}' + }) + ); + + suites.push( + Benchmark.Suite('`_.isEqual` comparing arrays of objects') + .add(buildName, { + 'fn': '\ + lodash.isEqual(objects, objects2);\ + lodash.isEqual(simpleObjects, simpleObjects2);', + 'teardown': 'function isEqual(){}' + }) + .add(otherName, { + 'fn': '\ + _.isEqual(objects, objects2);\ + _.isEqual(simpleObjects, simpleObjects2);', + 'teardown': 'function isEqual(){}' + }) + ); + + suites.push( + Benchmark.Suite('`_.isEqual` comparing objects') + .add(buildName, { + 'fn': '\ + lodash.isEqual(object, object2);\ + lodash.isEqual(simpleObject, simpleObject2);', + 'teardown': 'function isEqual(){}' + }) + .add(otherName, { + 'fn': '\ + _.isEqual(object, object2);\ + _.isEqual(simpleObject, simpleObject2);', + 'teardown': 'function isEqual(){}' + }) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.isArguments`, `_.isDate`, `_.isFunction`, `_.isNumber`, `_.isRegExp`') + .add(buildName, '\ + lodash.isArguments(arguments);\ + lodash.isArguments(object);\ + lodash.isDate(date);\ + lodash.isDate(object);\ + lodash.isFunction(lodash);\ + lodash.isFunction(object);\ + lodash.isNumber(1);\ + lodash.isNumber(object);\ + lodash.isRegExp(regexp);\ + lodash.isRegExp(object);' + ) + .add(otherName, '\ + _.isArguments(arguments);\ + _.isArguments(object);\ + _.isDate(date);\ + _.isDate(object);\ + _.isFunction(_);\ + _.isFunction(object);\ + _.isNumber(1);\ + _.isNumber(object);\ + _.isRegExp(regexp);\ + _.isRegExp(object);' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.keys` (uses native `Object.keys` if available)') + .add(buildName, '\ + lodash.keys(object)' + ) + .add(otherName, '\ + _.keys(object)' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.lastIndexOf`') + .add(buildName, '\ + lodash.lastIndexOf(numbers, 9)' + ) + .add(otherName, '\ + _.lastIndexOf(numbers, 9)' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.map` iterating an array') + .add(buildName, '\ + lodash.map(objects, function(value) {\ + return value.num;\ + })' + ) + .add(otherName, '\ + _.map(objects, function(value) {\ + return value.num;\ + })' + ) + ); + + suites.push( + Benchmark.Suite('`_.map` with `thisArg` iterating an array (slow path)') + .add(buildName, '\ + lodash.map(objects, function(value, index) {\ + return this["key" + index] + value.num;\ + }, object)' + ) + .add(otherName, '\ + _.map(objects, function(value, index) {\ + return this["key" + index] + value.num;\ + }, object)' + ) + ); + + suites.push( + Benchmark.Suite('`_.map` iterating an object') + .add(buildName, '\ + lodash.map(object, function(value) {\ + return value;\ + })' + ) + .add(otherName, '\ + _.map(object, function(value) {\ + return value;\ + })' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.max`') + .add(buildName, '\ + lodash.max(numbers)' + ) + .add(otherName, '\ + _.max(numbers)' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.min`') + .add(buildName, '\ + lodash.min(numbers)' + ) + .add(otherName, '\ + _.min(numbers)' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.omit` iterating 20 properties, omitting 2 keys') + .add(buildName, '\ + lodash.omit(object, "key6", "key13")' + ) + .add(otherName, '\ + _.omit(object, "key6", "key13")' + ) + ); + + suites.push( + Benchmark.Suite('`_.omit` iterating 40 properties, omitting 20 keys') + .add(buildName, { + 'fn': 'lodash.omit(wordToNumber, words)', + 'teardown': 'function omit(){}' + }) + .add(otherName, { + 'fn': 'result = _.omit(wordToNumber, words)', + 'teardown': 'function omit(){}' + }) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.pairs`') + .add(buildName, '\ + lodash.pairs(object)' + ) + .add(otherName, '\ + _.pairs(object)' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.pick`') + .add(buildName, '\ + lodash.pick(object, "key6", "key13")' + ) + .add(otherName, '\ + _.pick(object, "key6", "key13")' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.pluck`') + .add(buildName, '\ + lodash.pluck(objects, "num")' + ) + .add(otherName, '\ + _.pluck(objects, "num")' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.reduce` iterating an array') + .add(buildName, '\ + lodash.reduce(numbers, function(result, value, index) {\ + result[index] = value;\ + return result;\ + }, {});' + ) + .add(otherName, '\ + _.reduce(numbers, function(result, value, index) {\ + result[index] = value;\ + return result;\ + }, {});' + ) + ); + + suites.push( + Benchmark.Suite('`_.reduce` iterating an object') + .add(buildName, '\ + lodash.reduce(object, function(result, value, key) {\ + result.push([key, value]);\ + return result;\ + }, []);' + ) + .add(otherName, '\ + _.reduce(object, function(result, value, key) {\ + result.push([key, value]);\ + return result;\ + }, []);' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.reduceRight` iterating an array') + .add(buildName, '\ + lodash.reduceRight(numbers, function(result, value, index) {\ + result[index] = value;\ + return result;\ + }, {});' + ) + .add(otherName, '\ + _.reduceRight(numbers, function(result, value, index) {\ + result[index] = value;\ + return result;\ + }, {});' + ) + ); + + suites.push( + Benchmark.Suite('`_.reduceRight` iterating an object') + .add(buildName, '\ + lodash.reduceRight(object, function(result, value, key) {\ + result.push([key, value]);\ + return result;\ + }, []);' + ) + .add(otherName, '\ + _.reduceRight(object, function(result, value, key) {\ + result.push([key, value]);\ + return result;\ + }, []);' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.reject` iterating an array') + .add(buildName, '\ + lodash.reject(numbers, function(num) {\ + return num % 2;\ + })' + ) + .add(otherName, '\ + _.reject(numbers, function(num) {\ + return num % 2;\ + })' + ) + ); + + suites.push( + Benchmark.Suite('`_.reject` iterating an array with `thisArg` (slow path)') + .add(buildName, '\ + lodash.reject(numbers, function(num, index) {\ + return this["key" + index] % 2;\ + }, object)' + ) + .add(otherName, '\ + _.reject(numbers, function(num, index) {\ + return this["key" + index] % 2;\ + }, object)' + ) + ); + + suites.push( + Benchmark.Suite('`_.reject` iterating an object') + .add(buildName, '\ + lodash.reject(object, function(num) {\ + return num % 2\ + })' + ) + .add(otherName, '\ + _.reject(object, function(num) {\ + return num % 2\ + })' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.shuffle`') + .add(buildName, '\ + lodash.shuffle(numbers)' + ) + .add(otherName, '\ + _.shuffle(numbers)' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.size` with an object') + .add(buildName, '\ + lodash.size(object)' + ) + .add(otherName, '\ + _.size(object)' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.some` iterating an array') + .add(buildName, '\ + lodash.some(numbers, function(num) {\ + return num == 19;\ + })' + ) + .add(otherName, '\ + _.some(numbers, function(num) {\ + return num == 19;\ + })' + ) + ); + + suites.push( + Benchmark.Suite('`_.some` with `thisArg` iterating an array (slow path)') + .add(buildName, '\ + lodash.some(objects, function(value, index) {\ + return this["key" + index] == 19;\ + }, object)' + ) + .add(otherName, '\ + _.some(objects, function(value, index) {\ + return this["key" + index] == 19;\ + }, object)' + ) + ); + + suites.push( + Benchmark.Suite('`_.some` iterating an object') + .add(buildName, '\ + lodash.some(object, function(num) {\ + return num == 19;\ + })' + ) + .add(otherName, '\ + _.some(object, function(num) {\ + return num == 19;\ + })' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.sortBy` with `callback`') + .add(buildName, '\ + lodash.sortBy(numbers, function(num) { return Math.sin(num); })' + ) + .add(otherName, '\ + _.sortBy(numbers, function(num) { return Math.sin(num); })' + ) + ); + + suites.push( + Benchmark.Suite('`_.sortBy` with `callback` and `thisArg` (slow path)') + .add(buildName, '\ + lodash.sortBy(numbers, function(num) { return this.sin(num); }, Math)' + ) + .add(otherName, '\ + _.sortBy(numbers, function(num) { return this.sin(num); }, Math)' + ) + ); + + suites.push( + Benchmark.Suite('`_.sortBy` with `property` name') + .add(buildName, { + 'fn': 'lodash.sortBy(words, "length")', + 'teardown': 'function countBy(){}' + }) + .add(otherName, { + 'fn': '_.sortBy(words, "length")', + 'teardown': 'function countBy(){}' + }) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.sortedIndex`') + .add(buildName, '\ + lodash.sortedIndex(numbers, 25)' + ) + .add(otherName, '\ + _.sortedIndex(numbers, 25)' + ) + ); + + suites.push( + Benchmark.Suite('`_.sortedIndex` with `callback`') + .add(buildName, { + 'fn': '\ + lodash.sortedIndex(words, "twenty-five", function(value) {\ + return wordToNumber[value];\ + })', + 'teardown': 'function countBy(){}' + }) + .add(otherName, { + 'fn': '\ + _.sortedIndex(words, "twenty-five", function(value) {\ + return wordToNumber[value];\ + })', + 'teardown': 'function countBy(){}' + }) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.template` (slow path)') + .add(buildName, { + 'fn': 'lodash.template(tpl, tplData)', + 'teardown': 'function template(){}' + }) + .add(otherName, { + 'fn': '_.template(tpl, tplData)', + 'teardown': 'function template(){}' + }) + ); + + suites.push( + Benchmark.Suite('compiled template') + .add(buildName, { + 'fn': 'lodashTpl(tplData)', + 'teardown': 'function template(){}' + }) + .add(otherName, { + 'fn': '_tpl(tplData)', + 'teardown': 'function template(){}' + }) + ); + + suites.push( + Benchmark.Suite('compiled template without a with-statement') + .add(buildName, { + 'fn': 'lodashTplVerbose(tplData)', + 'teardown': 'function template(){}' + }) + .add(otherName, { + 'fn': '_tplVerbose(tplData)', + 'teardown': 'function template(){}' + }) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.times`') + .add(buildName, '\ + var result = [];\ + lodash.times(limit, function(n) { result.push(n); })' + ) + .add(otherName, '\ + var result = [];\ + _.times(limit, function(n) { result.push(n); })' + ) + ); + + suites.push( + Benchmark.Suite('`_.times` with `thisArg`') + .add(buildName, '\ + var result = [];\ + lodash.times(limit, function(n) { result.push(this.sin(n)); }, Math)' + ) + .add(otherName, '\ + var result = [];\ + _.times(limit, function(n) { result.push(this.sin(n)); }, Math)' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.toArray` with an array (edge case)') + .add(buildName, '\ + lodash.toArray(numbers)' + ) + .add(otherName, '\ + _.toArray(numbers)' + ) + ); + + suites.push( + Benchmark.Suite('`_.toArray` with an object') + .add(buildName, '\ + lodash.toArray(object)' + ) + .add(otherName, '\ + _.toArray(object)' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.union`') + .add(buildName, '\ + lodash.union(numbers, twoNumbers, fourNumbers)' + ) + .add(otherName, '\ + _.union(numbers, twoNumbers, fourNumbers)' + ) + ); + + suites.push( + Benchmark.Suite('`_.union` iterating an array of 75 elements') + .add(buildName, { + 'fn': 'lodash.union(fiftyValues, twentyFiveValues2);', + 'teardown': 'function multiArrays(){}' + }) + .add(otherName, { + 'fn': '_.union(fiftyValues, twentyFiveValues2);', + 'teardown': 'function multiArrays(){}' + }) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.uniq`') + .add(buildName, '\ + lodash.uniq(numbers.concat(twoNumbers, fourNumbers))' + ) + .add(otherName, '\ + _.uniq(numbers.concat(twoNumbers, fourNumbers))' + ) + ); + + suites.push( + Benchmark.Suite('`_.uniq` with `callback`') + .add(buildName, '\ + lodash.uniq(numbers.concat(twoNumbers, fourNumbers), function(num) {\ + return num % 2;\ + });' + ) + .add(otherName, '\ + _.uniq(numbers.concat(twoNumbers, fourNumbers), function(num) {\ + return num % 2;\ + })' + ) + ); + + suites.push( + Benchmark.Suite('`_.uniq` iterating an array of 75 elements') + .add(buildName, { + 'fn': 'lodash.uniq(fiftyValues.concat(twentyFiveValues2));', + 'teardown': 'function multiArrays(){}' + }) + .add(otherName, { + 'fn': '_.uniq(fiftyValues.concat(twentyFiveValues2));', + 'teardown': 'function multiArrays(){}' + }) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.values`') + .add(buildName, '\ + lodash.values(object)' + ) + .add(otherName, '\ + _.values(object)' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.where`') + .add(buildName, '\ + lodash.where(objects, { "num": 9 });' + ) + .add(otherName, '\ + _.where(objects, { "num": 9 });' + ) + ); + + /*--------------------------------------------------------------------------*/ + + suites.push( + Benchmark.Suite('`_.without`') + .add(buildName, '\ + lodash.without(numbers, 9, 12, 14, 15)' + ) + .add(otherName, '\ + _.without(numbers, 9, 12, 14, 15)' + ) + ); + + suites.push( + Benchmark.Suite('`_.without` iterating an array of 30 elements') + .add(buildName, { + 'fn': 'lodash.without.apply(lodash, [thirtyValues].concat(thirtyValues2));', + 'teardown': 'function multiArrays(){}' + }) + .add(otherName, { + 'fn': '_.without.apply(_, [thirtyValues].concat(thirtyValues2));', + 'teardown': 'function multiArrays(){}' + }) + ); + + /*--------------------------------------------------------------------------*/ + + if (Benchmark.platform + '') { + log(Benchmark.platform); + } + + // in the browser, expose `run` to be called later + if (window.document && !window.phantom) { + window.run = run; + } else { + run(); + } +}(typeof global == 'object' && global || this)); diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/a.jst b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/a.jst new file mode 100644 index 0000000..cca541d --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/a.jst @@ -0,0 +1,3 @@ +
      +<% _.forEach(people, function(name) { %>
    • <%- name %>
    • <% }); %> +
    \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/b.jst b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/b.jst new file mode 100644 index 0000000..cad081d --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/b.jst @@ -0,0 +1 @@ +<% print("Hello " + epithet); %>. \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/c.jst b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/c.jst new file mode 100644 index 0000000..f926799 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/c.jst @@ -0,0 +1 @@ +Hello ${ name }! \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/d.tpl b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/d.tpl new file mode 100644 index 0000000..c7a43bc --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/template/d.tpl @@ -0,0 +1 @@ +Hello {{ name }}! \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/test-build.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/test-build.js new file mode 100644 index 0000000..759d98e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/test-build.js @@ -0,0 +1,1324 @@ +#!/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.addEventListener || (global.addEventListener = Function.prototype), + global.QUnit = require('../vendor/qunit/qunit/qunit.js'), + require('../vendor/qunit-clib/qunit-clib.js'), + global.addEventListener === Function.prototype && delete global.addEventListener, + global.QUnit + ); + + /** The time limit for the tests to run (milliseconds) */ + var timeLimit = process.argv.reduce(function(result, value, index) { + if (/--time-limit/.test(value)) { + return parseInt(process.argv[index + 1].replace(/(\d+h)?(\d+m)?(\d+s)?/, function(match, h, m, s) { + return ((parseInt(h) || 0) * 3600000) + + ((parseInt(m) || 0) * 60000) + + ((parseInt(s) || 0) * 1000); + })) || result; + } + return result; + }, 0); + + /** Used to associate aliases with their real names */ + var aliasToRealMap = { + 'all': 'every', + 'any': 'some', + 'collect': 'map', + 'detect': 'find', + 'drop': 'rest', + 'each': 'forEach', + 'extend': 'assign', + '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 = { + 'assign': ['extend'], + '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); }) + .concat('chain') + .sort(); + + /** 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 = [ + 'mixin', + 'tap', + 'value' + ]; + + /** List of "Collections" category methods */ + var collectionsMethods = [ + 'all', + 'any', + 'at', + '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', + 'bindKey', + 'compose', + 'debounce', + 'defer', + 'delay', + 'memoize', + 'once', + 'partial', + 'partialRight', + 'throttle', + 'wrap' + ]; + + /** List of "Objects" category methods */ + var objectsMethods = [ + 'assign', + 'clone', + 'cloneDeep', + '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', + 'chain', + 'clone', + 'contains', + 'countBy', + 'defaults', + 'escape', + 'every', + 'extend', + 'filter', + 'find', + 'first', + 'forEach', + 'groupBy', + 'has', + 'indexOf', + 'initial', + 'invoke', + 'isArray', + 'isEmpty', + 'isEqual', + 'isFunction', + 'isObject', + 'isRegExp', + 'isString', + 'keys', + 'last', + 'lastIndexOf', + 'map', + 'max', + 'min', + 'mixin', + 'once', + 'pick', + 'reduce', + 'reduceRight', + 'reject', + 'rest', + 'result', + 'shuffle', + 'size', + 'some', + 'sortBy', + 'sortedIndex', + 'toArray', + 'uniqueId', + 'value', + 'without' + ]; + + /** List of methods used by Underscore */ + var underscoreMethods = _.without.apply(_, [allMethods].concat([ + 'at', + 'bindKey', + 'cloneDeep', + 'forIn', + 'forOwn', + 'isPlainObject', + 'merge', + 'partialRight' + ])); + + /*--------------------------------------------------------------------------*/ + + /** + * 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', + template = '<%= a %>', + 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 == 'at') { + func(array, 0, 2); + func(object, 'a', 'c'); + } + 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 == 'bindKey') { + func(lodash, 'identity', array, string); + } else if (/^(?:bind|partial(?:Right)?)$/.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 == 'template') { + func(template, object); + func(template, null, { 'imports': object })(object); + } else if (methodName == 'times') { + func(2, noop, object); + } else { + func(string, object); + } + } + } + catch(e) { + console.log(e); + pass = false; + } + ok(pass, '_.' + methodName + ': ' + message); + } + + /*--------------------------------------------------------------------------*/ + + QUnit.module('minified AMD snippet'); + + (function() { + var start = _.once(QUnit.start); + + asyncTest('`lodash`', function() { + build(['-s'], function(data) { + // 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(data.outputPath, '.js'); + + ok(!!defineHasRegExp.exec(data.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(data) { + var basename = path.basename(data.outputPath, '.js'), + context = createContext(); + + var object = { + 'a': { 'people': ['moe', 'larry', 'curly'] }, + 'b': { 'epithet': 'stooge' }, + 'c': { 'name': 'ES6' } + }; + + context._ = _; + vm.runInContext(data.source, context); + + equal(_.templates.a(object.a).replace(/[\r\n]+/g, ''), '
    • moe
    • larry
    • curly
    ', basename); + equal(_.templates.b(object.b), 'Hello stooge.', basename); + equal(_.templates.c(object.c), 'Hello ES6!', basename); + delete _.templates; + start(); + }); + }); + + var commands = [ + '', + 'moduleId=underscore' + ]; + + commands.forEach(function(command) { + var expectedId = /underscore/.test(command) ? 'underscore' : 'lodash'; + + asyncTest('`lodash template=*.jst exports=amd' + (command ? ' ' + command : '') + '`', function() { + var start = _.after(2, _.once(QUnit.start)); + + build(['-s', 'template=' + templatePath + '/*.jst', 'exports=amd'].concat(command || []), function(data) { + var moduleId, + basename = path.basename(data.outputPath, '.js'), + context = createContext(); + + context.define = function(requires, factory) { + factory(_); + moduleId = requires[0]; + }; + + context.define.amd = {}; + vm.runInContext(data.source, context); + + equal(moduleId, expectedId, basename); + ok('a' in _.templates && 'b' in _.templates, basename); + equal(_.templates.a({ 'people': ['moe', 'larry'] }), '
      \n
    • moe
    • larry
    • \n
    ', basename); + + delete _.templates; + start(); + }); + }); + + asyncTest('`lodash settings=...' + (command ? ' ' + command : '') + '`', function() { + var start = _.after(2, _.once(QUnit.start)); + + build(['-s', 'template=' + templatePath + '/*.tpl', 'settings={interpolate:/{{([\\s\\S]+?)}}/}'].concat(command || []), function(data) { + var moduleId, + basename = path.basename(data.outputPath, '.js'), + context = createContext(); + + var object = { + 'd': { 'name': 'Mustache' } + }; + + context.define = function(requires, factory) { + factory(_); + moduleId = requires[0]; + }; + + context.define.amd = {}; + vm.runInContext(data.source, context); + + equal(moduleId, expectedId, basename); + equal(_.templates.d(object.d), 'Hello Mustache!', basename); + delete _.templates; + start(); + }); + }); + }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('independent builds'); + + (function() { + var reCustom = /Custom Build/, + reLicense = /^\/\**\s+\* @license[\s\S]+?\*\/\n/; + + asyncTest('debug only', function() { + var start = _.once(QUnit.start); + build(['-d', '-s'], function(data) { + equal(path.basename(data.outputPath, '.js'), 'lodash'); + start(); + }); + }); + + asyncTest('debug custom', function() { + var start = _.once(QUnit.start); + build(['-d', '-s', 'backbone'], function(data) { + equal(path.basename(data.outputPath, '.js'), 'lodash.custom'); + + var comment = data.source.match(reLicense); + ok(reCustom.test(comment)); + start(); + }); + }); + + asyncTest('minified only', function() { + var start = _.once(QUnit.start); + build(['-m', '-s'], function(data) { + equal(path.basename(data.outputPath, '.js'), 'lodash.min'); + start(); + }); + }); + + asyncTest('minified custom', function() { + var start = _.once(QUnit.start); + build(['-m', '-s', 'backbone'], function(data) { + equal(path.basename(data.outputPath, '.js'), 'lodash.custom.min'); + + var comment = data.source.match(reLicense); + ok(reCustom.test(comment)); + start(); + }); + }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('source maps'); + + (function() { + var mapCommands = [ + '-p', + '-p custom.map', + '--source-map', + '--source-map custom.map' + ]; + + var outputCommands = [ + '', + '-o foo.js', + '-m -o bar.js' + ]; + + mapCommands.forEach(function(mapCommand) { + outputCommands.forEach(function(outputCommand) { + asyncTest('`lodash ' + mapCommand + (outputCommand ? ' ' + outputCommand : '') + '`', function() { + var callback = _.once(function(data) { + var basename = path.basename(data.outputPath, '.js'), + comment = (/(\s*\/\/.*\s*|\s*\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/\s*)$/.exec(data.source) || [])[0], + sources = /foo.js/.test(outputCommand) ? ['foo.js'] : ['lodash' + (outputCommand.length ? '' : '.custom') + '.js'], + sourceMap = JSON.parse(data.sourceMap), + sourceMapURL = (/\w+(?=\.map$)/.exec(mapCommand) || [basename])[0]; + + ok(RegExp('/\\*\\n//@ sourceMappingURL=' + sourceMapURL + '.map\\n\\*/').test(comment), basename); + equal(sourceMap.file, basename + '.js', basename); + deepEqual(sourceMap.sources, sources, basename); + + QUnit.start(); + }); + + outputCommand = outputCommand ? outputCommand.split(' ') : []; + if (outputCommand.indexOf('-m') < 0) { + callback = _.after(2, callback); + } + build(['-s'].concat(mapCommand.split(' '), outputCommand), callback); + }); + }); + }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('strict modifier'); + + (function() { + var object = Object.freeze({ + 'a': _.identity, + 'b': undefined + }); + + var modes = [ + 'non-strict', + 'strict' + ]; + + modes.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(data) { + var basename = path.basename(data.outputPath, '.js'), + context = createContext(); + + vm.runInContext(data.source, context); + var lodash = context._; + + var actual = _.every([ + function() { lodash.bindAll(object); }, + function() { lodash.extend(object, { 'a': 1 }); }, + function() { lodash.defaults(object, { 'b': 2 }); } + ], function(fn) { + var pass = !index; + try { + fn(); + } catch(e) { + pass = !!index; + } + return pass; + }); + + ok(actual, basename); + start(); + }); + }); + }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('underscore chaining methods'); + + (function() { + var commands = [ + 'backbone', + 'underscore' + ]; + + commands.forEach(function(command) { + asyncTest('`lodash ' + command +'`', function() { + var start = _.after(2, _.once(QUnit.start)); + + build(['-s', command], function(data) { + var basename = path.basename(data.outputPath, '.js'), + context = createContext(); + + vm.runInContext(data.source, context); + var lodash = context._; + + ok(lodash.chain(1) instanceof lodash, '_.chain: ' + basename); + ok(lodash(1).chain() instanceof lodash, '_#chain: ' + basename); + + var wrapped = lodash(1); + strictEqual(wrapped.identity(), 1, '_(...) wrapped values are not chainable by default: ' + basename); + equal(String(wrapped) === '1', false, '_#toString should not be implemented: ' + basename); + equal(Number(wrapped) === 1 , false, '_#valueOf should not be implemented: ' + basename); + + wrapped.chain(); + ok(wrapped.has('x') instanceof lodash, '_#has returns wrapped values when chaining: ' + basename); + ok(wrapped.join() instanceof lodash, '_#join returns wrapped values when chaining: ' + basename); + + wrapped = lodash([1, 2, 3]); + ok(wrapped.pop() instanceof lodash, '_#pop returns wrapped values: ' + basename); + ok(wrapped.shift() instanceof lodash, '_#shift returns wrapped values: ' + basename); + deepEqual(wrapped.splice(0, 0).value(), [2], '_#splice returns wrapper: ' + 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(data) { + var last, + array = [{ 'a': 1, 'b': 2 }, { 'a': 2, 'b': 2 }], + basename = path.basename(data.outputPath, '.js'), + context = createContext(); + + vm.runInContext(data.source, context); + var lodash = context._; + + var object = { + 'fn': lodash.bind(function(foo) { + return foo + this.bar; + }, { 'bar': 1 }, 1) + }; + + equal(object.fn(), 2, '_.bind: ' + basename); + + var actual = lodash.clone('a', function() { + return this.a; + }, { 'a': 'A' }); + + equal(actual, 'a', '_.clone should ignore `callback` and `thisArg`: ' + basename); + strictEqual(lodash.clone(array, true)[0], array[0], '_.clone should ignore `deep`: ' + basename); + + strictEqual(lodash.contains({ 'a': 1, 'b': 2 }, 1), true, '_.contains should work with objects: ' + basename); + strictEqual(lodash.contains([1, 2, 3], 1, 2), true, '_.contains should ignore `fromIndex`: ' + basename); + strictEqual(lodash.every([true, false, true]), false, '_.every: ' + basename); + + function Foo() {} + Foo.prototype = { 'a': 1 }; + + actual = lodash.defaults({ 'a': null }, { 'a': 1 }); + strictEqual(actual.a, 1, '_.defaults should overwrite `null` values: ' + basename); + + deepEqual(lodash.defaults({}, new Foo), Foo.prototype, '_.defaults should assign inherited `source` properties: ' + basename); + deepEqual(lodash.extend({}, new Foo), Foo.prototype, '_.extend should assign inherited `source` properties: ' + basename); + + actual = lodash.extend({}, { 'a': 0 }, function(a, b) { + return this[b]; + }, [2]); + + strictEqual(actual.a, 0, '_.extend should ignore `callback` and `thisArg`: ' + basename); + + actual = lodash.find(array, function(value) { + return 'a' in value; + }); + + equal(actual, _.first(array), '_.find: ' + basename); + + actual = lodash.forEach(array, function(value) { + last = value; + return false; + }); + + equal(last, _.last(array), '_.forEach should not exit early: ' + basename); + equal(actual, undefined, '_.forEach should return `undefined`: ' + basename); + + object = { 'length': 0, 'splice': Array.prototype.splice }; + equal(lodash.isEmpty(object), false, '_.isEmpty should return `false` for jQuery/MooTools DOM query collections: ' + basename); + + object = { 'a': 1, 'b': 2, 'c': 3 }; + equal(lodash.isEqual(object, { 'a': 1, 'b': 0, 'c': 3 }), false, '_.isEqual: ' + basename); + + actual = lodash.isEqual('a', 'b', function(a, b) { + return this[a] == this[b]; + }, { 'a': 1, 'b': 1 }); + + strictEqual(actual, false, '_.isEqual should ignore `callback` and `thisArg`: ' + basename); + + equal(lodash.max('abc'), -Infinity, '_.max should return `-Infinity` for strings: ' + basename); + equal(lodash.min('abc'), Infinity, '_.min should return `Infinity` for strings: ' + basename); + + // avoid issues comparing objects with `deepEqual` + object = { 'a': 1, 'b': 2, 'c': 3 }; + actual = lodash.omit(object, function(value) { return value == 3; }); + deepEqual(_.keys(actual).sort(), ['a', 'b', 'c'], '_.omit should not accept a `callback`: ' + basename); + + actual = lodash.pick(object, function(value) { return value != 3; }); + deepEqual(_.keys(actual), [], '_.pick should not accept a `callback`: ' + basename); + + strictEqual(lodash.result(), null, '_.result should return `null` for falsey `object` arguments: ' + basename); + strictEqual(lodash.some([false, true, false]), true, '_.some: ' + basename); + equal(lodash.template('${a}', object), '${a}', '_.template should ignore ES6 delimiters: ' + basename); + equal('imports' in lodash.templateSettings, false, '_.templateSettings should not have an "imports" property: ' + basename); + strictEqual(lodash.uniqueId(0), '1', '_.uniqueId should ignore a prefix of `0`: ' + basename); + + var collection = [{ 'a': { 'b': 1, 'c': 2 } }]; + deepEqual(lodash.where(collection, { 'a': { 'b': 1 } }), [], '_.where performs shallow comparisons: ' + basename); + + collection = [{ 'a': 1 }, { 'a': 1 }]; + deepEqual(lodash.where(collection, { 'a': 1 }, true), collection[0], '_.where supports a `first` argument: ' + basename); + deepEqual(lodash.where(collection, {}, true), null, '_.where should return `null` when passed `first` and falsey `properties`: ' + basename); + + deepEqual(lodash.findWhere(collection, { 'a': 1 }), collection[0], '_.findWhere: ' + basename); + strictEqual(lodash.findWhere(collection, {}), null, '_.findWhere should return `null` for falsey `properties`: ' + basename); + + start(); + }); + }); + + asyncTest('should not have any Lo-Dash-only methods', function() { + var start = _.after(2, _.once(QUnit.start)); + + build(['-s', 'underscore'], function(data) { + var basename = path.basename(data.outputPath, '.js'), + context = createContext(); + + vm.runInContext(data.source, context); + var lodash = context._; + + _.each([ + 'assign', + 'at', + 'bindKey', + 'forIn', + 'forOwn', + 'isPlainObject', + 'merge', + 'partialRight' + ], function(methodName) { + equal(lodash[methodName], undefined, '_.' + methodName + ' should not exist: ' + basename); + }); + + start(); + }); + }); + + asyncTest('`lodash underscore include=findWhere`', function() { + var start = _.after(2, _.once(QUnit.start)); + + build(['-s', 'underscore', 'include=findWhere'], function(data) { + var basename = path.basename(data.outputPath, '.js'), + context = createContext(); + + vm.runInContext(data.source, context); + var lodash = context._; + + var collection = [{ 'a': 1 }, { 'a': 1 }]; + deepEqual(lodash.findWhere(collection, { 'a': 1 }), collection[0], '_.findWhere: ' + basename); + + start(); + }); + }); + + asyncTest('`lodash underscore include=partial`', function() { + var start = _.after(2, _.once(QUnit.start)); + + build(['-s', 'underscore', 'include=partial'], function(data) { + var basename = path.basename(data.outputPath, '.js'), + context = createContext(); + + vm.runInContext(data.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(data) { + var array = [{ 'value': 1 }], + basename = path.basename(data.outputPath, '.js'), + context = createContext(); + + vm.runInContext(data.source, context); + var lodash = context._, + clone = lodash.clone(array, true); + + ok(_.isEqual(array, clone), basename); + notEqual(array[0], clone[0], 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(data) { + var basename = path.basename(data.outputPath, '.js'), + context = createContext(), + pass = false, + source = data.source; + + 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(_.isFunction(context.exports._), basename); + strictEqual(context._, undefined, 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(_.isFunction(context.module.exports), basename); + strictEqual(context._, undefined, basename); + break; + + case 4: + vm.runInContext(source, context); + strictEqual(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(data) { + var basename = path.basename(data.outputPath, '.js'), + context = createContext(); + + context.define = function(func) { + context.lodash = func(); + }; + + try { + vm.runInContext(data.source, context); + } catch(e) { + console.log(e); + } + + var lodash = context.lodash || {}; + ok(_.isString(lodash.VERSION), basename); + start(); + }); + }); + }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('output options'); + + (function() { + var commands = [ + '-o a.js', + '--output a.js' + ]; + + commands.forEach(function(command, index) { + asyncTest('`lodash ' + command +'`', function() { + var counter = -1, + start = _.after(2, _.once(QUnit.start)); + + build(['-s'].concat(command.split(' ')), function(data) { + equal(path.basename(data.outputPath, '.js'), (++counter ? 'a.min' : 'a'), command); + start(); + }); + }); + }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('stdout options'); + + (function() { + var commands = [ + '-c', + '-c -d', + '--stdout', + ]; + + commands.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(['exports=', 'include='].concat(command.split(' ')), function(data) { + process.stdout.write = write; + equal(written, data.source); + equal(arguments.length, 1); + start(); + }); + }); + }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('mobile build'); + + (function() { + asyncTest('`lodash mobile`', function() { + var start = _.after(2, _.once(QUnit.start)); + + build(['-s', 'mobile'], function(data) { + var basename = path.basename(data.outputPath, '.js'), + context = createContext(); + + try { + vm.runInContext(data.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); + strictEqual(lodash.isEqual(circular1, circular2), true, basename); + + var actual = lodash.cloneDeep(circular1); + ok(actual != circular1 && actual.b == actual, basename); + start(); + }); + }); + + asyncTest('`lodash csp`', function() { + var sources = []; + + var check = _.after(2, _.once(function() { + equal(sources[0], sources[1]); + QUnit.start(); + })); + + var callback = function(data) { + // remove copyright header and append source + sources.push(data.source.replace(/^\/\**[\s\S]+?\*\/\n/, '')); + check(); + }; + + build(['-s', '-d', 'csp'], callback); + build(['-s', '-d', 'mobile'], callback); + }); + }()); + + /*--------------------------------------------------------------------------*/ + + QUnit.module('lodash build'); + + (function() { + var commands = [ + 'backbone', + 'csp', + 'legacy', + 'mobile', + 'modern', + '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', + 'backbone legacy category=utilities minus=first,last', + 'legacy include=defer', + 'legacy underscore', + '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(origCommand) { + _.times(4, function(index) { + var command = origCommand; + + if (index == 1) { + if (/legacy|mobile/.test(command)) { + return; + } + command = 'mobile ' + command; + } + if (index == 2) { + if (/legacy|modern/.test(command)) { + return; + } + command = 'modern ' + command; + } + if (index == 3) { + if (/category|legacy|underscore/.test(command)) { + return; + } + command = 'underscore ' + command; + } + asyncTest('`lodash ' + command +'`', function() { + var start = _.after(2, _.once(QUnit.start)); + + build(['--silent'].concat(command.split(' ')), function(data) { + var methodNames, + basename = path.basename(data.outputPath, '.js'), + context = createContext(), + isUnderscore = /backbone|underscore/.test(command), + exposeAssign = !isUnderscore; + + try { + vm.runInContext(data.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 (isUnderscore) { + if (methodNames) { + exposeAssign = methodNames.indexOf('assign') > -1; + } else { + 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))); + + if (!exposeAssign) { + methodNames = _.without(methodNames, 'assign'); + } + var lodash = context._ || {}; + methodNames.forEach(function(methodName) { + testMethod(lodash, methodName, basename); + }); + + start(); + }); + }); + }); + }); + }()); + + /*--------------------------------------------------------------------------*/ + + if (timeLimit > 0) { + setTimeout(function() { + process.exit(QUnit.config.stats.bad ? 1 : 0); + }, timeLimit); + } + // explicitly call `QUnit.start()` for Narwhal, Node.js, Rhino, and RingoJS + if (!global.document) { + QUnit.start(); + } +}()); diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/test.js new file mode 100644 index 0000000..632af43 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/test/test.js @@ -0,0 +1,2920 @@ +;(function(window, undefined) { + 'use strict'; + + /** Use a single "load" function */ + var load = typeof require == 'function' ? require : window.load; + + /** The file path of the Lo-Dash file to test */ + var filePath = (function() { + var min = 0; + var result = window.phantom + ? phantom.args + : (window.system + ? (min = 1, system.args) + : (window.process ? (min = 2, process.argv) : (window.arguments || [])) + ); + + var last = result[result.length - 1]; + result = (result.length > min && last != 'test.js') ? last : '../lodash.js'; + + try { + result = require('fs').realpathSync(result); + } catch(e) { } + + return result; + }()); + + /** The basename of the Lo-Dash file to test */ + var basename = /[\w.-]+$/.exec(filePath)[0]; + + /** The `platform` object to check */ + var platform = + window.platform || + load('../vendor/platform.js/platform.js') || + window.platform; + + /** The unit testing framework */ + var QUnit = + window.QUnit || ( + window.addEventListener || (window.addEventListener = Function.prototype), + window.setTimeout || (window.setTimeout = Function.prototype), + window.QUnit = load('../vendor/qunit/qunit/qunit.js') || window.QUnit, + load('../vendor/qunit-clib/qunit-clib.js'), + window.addEventListener === Function.prototype && delete window.addEventListener, + window.QUnit + ); + + /** The `lodash` function to test */ + var _ = window._ || ( + _ = load(filePath) || window._, + _._ || _ + ); + + /** Used to pass falsey values to methods */ + var falsey = [ + , + '', + 0, + false, + NaN, + null, + undefined + ]; + + /** Shortcut used to make object properties immutable */ + var freeze = Object.freeze; + + /** Used to set property descriptors */ + var setDescriptor = (function(fn) { + try { + var o = {}; + return fn(o, o, o) && fn; + } catch(e) { } + }(Object.defineProperty)); + + /** Shortcut used to convert array-like objects to arrays */ + var slice = [].slice; + + /** Used to check problem JScript properties (a.k.a. the [[DontEnum]] bug) */ + var shadowed = { + 'constructor': 1, + 'hasOwnProperty': 2, + 'isPrototypeOf': 3, + 'propertyIsEnumerable': 4, + 'toLocaleString': 5, + 'toString': 6, + 'valueOf': 7 + }; + + /** Used to check problem JScript properties too */ + var shadowedKeys = [ + 'constructor', + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'toLocaleString', + 'toString', + 'valueOf' + ]; + + /*--------------------------------------------------------------------------*/ + + /** + * Skips a given number of tests with a passing result. + * + * @private + * @param {Number} [count=1] The number of tests to skip. + */ + function skipTest(count) { + count || (count = 1); + while (count--) { + ok(true, 'test skipped'); + } + } + + /*--------------------------------------------------------------------------*/ + + // add object from iframe + (function() { + if (!window.document || window.phantom) { + return; + } + var body = document.body, + iframe = document.createElement('iframe'); + + iframe.frameBorder = iframe.height = iframe.width = 0; + body.appendChild(iframe); + var idoc = (idoc = iframe.contentDocument || iframe.contentWindow).document || idoc; + idoc.write(" +``` + +Optionally, expose Java’s nanosecond timer by adding the `nano` applet to the ``: + +```html + +``` + +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/) + [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter") +* [John-David Dalton](http://allyoucanleet.com/) + [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](https://twitter.com/jdalton "Follow @jdalton on Twitter") + +## Contributors + +* [Kit Cambridge](http://kitcambridge.github.com/) + [![twitter/kitcambridge](http://gravatar.com/avatar/6662a1d02f351b5ef2f8b4d815804661?s=70)](https://twitter.com/kitcambridge "Follow @kitcambridge on Twitter") diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/benchmark.js/benchmark.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/benchmark.js/benchmark.js new file mode 100644 index 0000000..6adf726 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/benchmark.js/benchmark.js @@ -0,0 +1,3960 @@ +/*! + * Benchmark.js v1.0.0 + * Copyright 2010-2013 Mathias Bynens + * Based on JSLitmus.js, copyright Robert Kieffer + * Modified by John-David Dalton + * Available under MIT license + */ +;(function(window, undefined) { + 'use strict'; + + /** Used to assign each benchmark an incrimented id */ + var counter = 0; + + /** Detect DOM document object */ + var doc = isHostType(window, 'document') && document; + + /** Detect free variable `define` */ + var freeDefine = typeof define == 'function' && + typeof define.amd == 'object' && define.amd && define; + + /** Detect free variable `exports` */ + var freeExports = typeof exports == 'object' && exports && + (typeof global == 'object' && global && global == global.global && (window = global), exports); + + /** Detect free variable `require` */ + var freeRequire = typeof require == 'function' && require; + + /** Used to store the `Object` built-in in case it's overwritten later */ + var Object = window.Object; + + /** Used to crawl all properties regardless of enumerability */ + var getAllKeys = Object.getOwnPropertyNames; + + /** Used to get property descriptors */ + var getDescriptor = Object.getOwnPropertyDescriptor; + + /** Used in case an object doesn't have its own method */ + var hasOwnProperty = {}.hasOwnProperty; + + /** Used to check if an object is extensible */ + var isExtensible = Object.isExtensible || function() { return true; }; + + /** Used to access Wade Simmons' Node microtime module */ + var microtimeObject = req('microtime'); + + /** Used to access the browser's high resolution timer */ + var perfObject = isHostType(window, 'performance') && performance; + + /** Used to call the browser's high resolution timer */ + var perfName = perfObject && ( + perfObject.now && 'now' || + perfObject.webkitNow && 'webkitNow' + ); + + /** Used to access Node's high resolution timer */ + var processObject = isHostType(window, 'process') && process; + + /** Used to check if an own property is enumerable */ + var propertyIsEnumerable = {}.propertyIsEnumerable; + + /** Used to set property descriptors */ + var setDescriptor = Object.defineProperty; + + /** Used to resolve a value's internal [[Class]] */ + var toString = {}.toString; + + /** Used to prevent a `removeChild` memory leak in IE < 9 */ + var trash = doc && doc.createElement('div'); + + /** Used to integrity check compiled tests */ + var uid = 'uid' + (+new Date); + + /** Used to avoid infinite recursion when methods call each other */ + var calledBy = {}; + + /** Used to avoid hz of Infinity */ + var divisors = { + '1': 4096, + '2': 512, + '3': 64, + '4': 8, + '5': 0 + }; + + /** + * T-Distribution two-tailed critical values for 95% confidence + * http://www.itl.nist.gov/div898/handbook/eda/section3/eda3672.htm + */ + var tTable = { + '1': 12.706,'2': 4.303, '3': 3.182, '4': 2.776, '5': 2.571, '6': 2.447, + '7': 2.365, '8': 2.306, '9': 2.262, '10': 2.228, '11': 2.201, '12': 2.179, + '13': 2.16, '14': 2.145, '15': 2.131, '16': 2.12, '17': 2.11, '18': 2.101, + '19': 2.093, '20': 2.086, '21': 2.08, '22': 2.074, '23': 2.069, '24': 2.064, + '25': 2.06, '26': 2.056, '27': 2.052, '28': 2.048, '29': 2.045, '30': 2.042, + 'infinity': 1.96 + }; + + /** + * Critical Mann-Whitney U-values for 95% confidence + * http://www.saburchill.com/IBbiology/stats/003.html + */ + var uTable = { + '5': [0, 1, 2], + '6': [1, 2, 3, 5], + '7': [1, 3, 5, 6, 8], + '8': [2, 4, 6, 8, 10, 13], + '9': [2, 4, 7, 10, 12, 15, 17], + '10': [3, 5, 8, 11, 14, 17, 20, 23], + '11': [3, 6, 9, 13, 16, 19, 23, 26, 30], + '12': [4, 7, 11, 14, 18, 22, 26, 29, 33, 37], + '13': [4, 8, 12, 16, 20, 24, 28, 33, 37, 41, 45], + '14': [5, 9, 13, 17, 22, 26, 31, 36, 40, 45, 50, 55], + '15': [5, 10, 14, 19, 24, 29, 34, 39, 44, 49, 54, 59, 64], + '16': [6, 11, 15, 21, 26, 31, 37, 42, 47, 53, 59, 64, 70, 75], + '17': [6, 11, 17, 22, 28, 34, 39, 45, 51, 57, 63, 67, 75, 81, 87], + '18': [7, 12, 18, 24, 30, 36, 42, 48, 55, 61, 67, 74, 80, 86, 93, 99], + '19': [7, 13, 19, 25, 32, 38, 45, 52, 58, 65, 72, 78, 85, 92, 99, 106, 113], + '20': [8, 14, 20, 27, 34, 41, 48, 55, 62, 69, 76, 83, 90, 98, 105, 112, 119, 127], + '21': [8, 15, 22, 29, 36, 43, 50, 58, 65, 73, 80, 88, 96, 103, 111, 119, 126, 134, 142], + '22': [9, 16, 23, 30, 38, 45, 53, 61, 69, 77, 85, 93, 101, 109, 117, 125, 133, 141, 150, 158], + '23': [9, 17, 24, 32, 40, 48, 56, 64, 73, 81, 89, 98, 106, 115, 123, 132, 140, 149, 157, 166, 175], + '24': [10, 17, 25, 33, 42, 50, 59, 67, 76, 85, 94, 102, 111, 120, 129, 138, 147, 156, 165, 174, 183, 192], + '25': [10, 18, 27, 35, 44, 53, 62, 71, 80, 89, 98, 107, 117, 126, 135, 145, 154, 163, 173, 182, 192, 201, 211], + '26': [11, 19, 28, 37, 46, 55, 64, 74, 83, 93, 102, 112, 122, 132, 141, 151, 161, 171, 181, 191, 200, 210, 220, 230], + '27': [11, 20, 29, 38, 48, 57, 67, 77, 87, 97, 107, 118, 125, 138, 147, 158, 168, 178, 188, 199, 209, 219, 230, 240, 250], + '28': [12, 21, 30, 40, 50, 60, 70, 80, 90, 101, 111, 122, 132, 143, 154, 164, 175, 186, 196, 207, 218, 228, 239, 250, 261, 272], + '29': [13, 22, 32, 42, 52, 62, 73, 83, 94, 105, 116, 127, 138, 149, 160, 171, 182, 193, 204, 215, 226, 238, 249, 260, 271, 282, 294], + '30': [13, 23, 33, 43, 54, 65, 76, 87, 98, 109, 120, 131, 143, 154, 166, 177, 189, 200, 212, 223, 235, 247, 258, 270, 282, 293, 305, 317] + }; + + /** + * An object used to flag environments/features. + * + * @static + * @memberOf Benchmark + * @type Object + */ + var support = {}; + + (function() { + + /** + * Detect Adobe AIR. + * + * @memberOf Benchmark.support + * @type Boolean + */ + support.air = isClassOf(window.runtime, 'ScriptBridgingProxyObject'); + + /** + * Detect if `arguments` objects have the correct internal [[Class]] value. + * + * @memberOf Benchmark.support + * @type Boolean + */ + support.argumentsClass = isClassOf(arguments, 'Arguments'); + + /** + * Detect if in a browser environment. + * + * @memberOf Benchmark.support + * @type Boolean + */ + support.browser = doc && isHostType(window, 'navigator'); + + /** + * Detect if strings support accessing characters by index. + * + * @memberOf Benchmark.support + * @type Boolean + */ + support.charByIndex = + // IE 8 supports indexes on string literals but not string objects + ('x'[0] + Object('x')[0]) == 'xx'; + + /** + * Detect if strings have indexes as own properties. + * + * @memberOf Benchmark.support + * @type Boolean + */ + support.charByOwnIndex = + // Narwhal, Rhino, RingoJS, IE 8, and Opera < 10.52 support indexes on + // strings but don't detect them as own properties + support.charByIndex && hasKey('x', '0'); + + /** + * Detect if Java is enabled/exposed. + * + * @memberOf Benchmark.support + * @type Boolean + */ + support.java = isClassOf(window.java, 'JavaPackage'); + + /** + * Detect if the Timers API exists. + * + * @memberOf Benchmark.support + * @type Boolean + */ + support.timeout = isHostType(window, 'setTimeout') && isHostType(window, 'clearTimeout'); + + /** + * Detect if functions support decompilation. + * + * @name decompilation + * @memberOf Benchmark.support + * @type Boolean + */ + try { + // Safari 2.x removes commas in object literals + // from Function#toString results + // http://webk.it/11609 + // Firefox 3.6 and Opera 9.25 strip grouping + // parentheses from Function#toString results + // http://bugzil.la/559438 + support.decompilation = Function( + 'return (' + (function(x) { return { 'x': '' + (1 + x) + '', 'y': 0 }; }) + ')' + )()(0).x === '1'; + } catch(e) { + support.decompilation = false; + } + + /** + * Detect ES5+ property descriptor API. + * + * @name descriptors + * @memberOf Benchmark.support + * @type Boolean + */ + try { + var o = {}; + support.descriptors = (setDescriptor(o, o, o), 'value' in getDescriptor(o, o)); + } catch(e) { + support.descriptors = false; + } + + /** + * Detect ES5+ Object.getOwnPropertyNames(). + * + * @name getAllKeys + * @memberOf Benchmark.support + * @type Boolean + */ + try { + support.getAllKeys = /\bvalueOf\b/.test(getAllKeys(Object.prototype)); + } catch(e) { + support.getAllKeys = false; + } + + /** + * Detect if own properties are iterated before inherited properties (all but IE < 9). + * + * @name iteratesOwnLast + * @memberOf Benchmark.support + * @type Boolean + */ + support.iteratesOwnFirst = (function() { + var props = []; + function ctor() { this.x = 1; } + ctor.prototype = { 'y': 1 }; + for (var prop in new ctor) { props.push(prop); } + return props[0] == 'x'; + }()); + + /** + * Detect if a node's [[Class]] is resolvable (all but IE < 9) + * and that the JS engine errors when attempting to coerce an object to a + * string without a `toString` property value of `typeof` "function". + * + * @name nodeClass + * @memberOf Benchmark.support + * @type Boolean + */ + try { + support.nodeClass = ({ 'toString': 0 } + '', toString.call(doc || 0) != '[object Object]'); + } catch(e) { + support.nodeClass = true; + } + }()); + + /** + * Timer object used by `clock()` and `Deferred#resolve`. + * + * @private + * @type Object + */ + var timer = { + + /** + * The timer namespace object or constructor. + * + * @private + * @memberOf timer + * @type Function|Object + */ + 'ns': Date, + + /** + * Starts the deferred timer. + * + * @private + * @memberOf timer + * @param {Object} deferred The deferred instance. + */ + 'start': null, // lazy defined in `clock()` + + /** + * Stops the deferred timer. + * + * @private + * @memberOf timer + * @param {Object} deferred The deferred instance. + */ + 'stop': null // lazy defined in `clock()` + }; + + /** Shortcut for inverse results */ + var noArgumentsClass = !support.argumentsClass, + noCharByIndex = !support.charByIndex, + noCharByOwnIndex = !support.charByOwnIndex; + + /** Math shortcuts */ + var abs = Math.abs, + floor = Math.floor, + log = Math.log, + max = Math.max, + min = Math.min, + pow = Math.pow, + sqrt = Math.sqrt; + + /*--------------------------------------------------------------------------*/ + + /** + * The Benchmark constructor. + * + * @constructor + * @param {String} name A name to identify the benchmark. + * @param {Function|String} fn The test to benchmark. + * @param {Object} [options={}] Options object. + * @example + * + * // basic usage (the `new` operator is optional) + * var bench = new Benchmark(fn); + * + * // or using a name first + * var bench = new Benchmark('foo', fn); + * + * // or with options + * var bench = new Benchmark('foo', fn, { + * + * // displayed by Benchmark#toString if `name` is not available + * 'id': 'xyz', + * + * // called when the benchmark starts running + * 'onStart': onStart, + * + * // called after each run cycle + * 'onCycle': onCycle, + * + * // called when aborted + * 'onAbort': onAbort, + * + * // called when a test errors + * 'onError': onError, + * + * // called when reset + * 'onReset': onReset, + * + * // called when the benchmark completes running + * 'onComplete': onComplete, + * + * // compiled/called before the test loop + * 'setup': setup, + * + * // compiled/called after the test loop + * 'teardown': teardown + * }); + * + * // or name and options + * var bench = new Benchmark('foo', { + * + * // a flag to indicate the benchmark is deferred + * 'defer': true, + * + * // benchmark test function + * 'fn': function(deferred) { + * // call resolve() when the deferred test is finished + * deferred.resolve(); + * } + * }); + * + * // or options only + * var bench = new Benchmark({ + * + * // benchmark name + * 'name': 'foo', + * + * // benchmark test as a string + * 'fn': '[1,2,3,4].sort()' + * }); + * + * // a test's `this` binding is set to the benchmark instance + * var bench = new Benchmark('foo', function() { + * 'My name is '.concat(this.name); // My name is foo + * }); + */ + function Benchmark(name, fn, options) { + var me = this; + + // allow instance creation without the `new` operator + if (me == null || me.constructor != Benchmark) { + return new Benchmark(name, fn, options); + } + // juggle arguments + if (isClassOf(name, 'Object')) { + // 1 argument (options) + options = name; + } + else if (isClassOf(name, 'Function')) { + // 2 arguments (fn, options) + options = fn; + fn = name; + } + else if (isClassOf(fn, 'Object')) { + // 2 arguments (name, options) + options = fn; + fn = null; + me.name = name; + } + else { + // 3 arguments (name, fn [, options]) + me.name = name; + } + setOptions(me, options); + me.id || (me.id = ++counter); + me.fn == null && (me.fn = fn); + me.stats = deepClone(me.stats); + me.times = deepClone(me.times); + } + + /** + * The Deferred constructor. + * + * @constructor + * @memberOf Benchmark + * @param {Object} clone The cloned benchmark instance. + */ + function Deferred(clone) { + var me = this; + if (me == null || me.constructor != Deferred) { + return new Deferred(clone); + } + me.benchmark = clone; + clock(me); + } + + /** + * The Event constructor. + * + * @constructor + * @memberOf Benchmark + * @param {String|Object} type The event type. + */ + function Event(type) { + var me = this; + return (me == null || me.constructor != Event) + ? new Event(type) + : (type instanceof Event) + ? type + : extend(me, { 'timeStamp': +new Date }, typeof type == 'string' ? { 'type': type } : type); + } + + /** + * The Suite constructor. + * + * @constructor + * @memberOf Benchmark + * @param {String} name A name to identify the suite. + * @param {Object} [options={}] Options object. + * @example + * + * // basic usage (the `new` operator is optional) + * var suite = new Benchmark.Suite; + * + * // or using a name first + * var suite = new Benchmark.Suite('foo'); + * + * // or with options + * var suite = new Benchmark.Suite('foo', { + * + * // called when the suite starts running + * 'onStart': onStart, + * + * // called between running benchmarks + * 'onCycle': onCycle, + * + * // called when aborted + * 'onAbort': onAbort, + * + * // called when a test errors + * 'onError': onError, + * + * // called when reset + * 'onReset': onReset, + * + * // called when the suite completes running + * 'onComplete': onComplete + * }); + */ + function Suite(name, options) { + var me = this; + + // allow instance creation without the `new` operator + if (me == null || me.constructor != Suite) { + return new Suite(name, options); + } + // juggle arguments + if (isClassOf(name, 'Object')) { + // 1 argument (options) + options = name; + } else { + // 2 arguments (name [, options]) + me.name = name; + } + setOptions(me, options); + } + + /*--------------------------------------------------------------------------*/ + + /** + * Note: Some array methods have been implemented in plain JavaScript to avoid + * bugs in IE, Opera, Rhino, and Mobile Safari. + * + * IE compatibility mode and IE < 9 have buggy Array `shift()` and `splice()` + * functions that fail to remove the last element, `object[0]`, of + * array-like-objects even though the `length` property is set to `0`. + * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()` + * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9. + * + * In Opera < 9.50 and some older/beta Mobile Safari versions using `unshift()` + * generically to augment the `arguments` object will pave the value at index 0 + * without incrimenting the other values's indexes. + * https://github.com/documentcloud/underscore/issues/9 + * + * Rhino and environments it powers, like Narwhal and RingoJS, may have + * buggy Array `concat()`, `reverse()`, `shift()`, `slice()`, `splice()` and + * `unshift()` functions that make sparse arrays non-sparse by assigning the + * undefined indexes a value of undefined. + * https://github.com/mozilla/rhino/commit/702abfed3f8ca043b2636efd31c14ba7552603dd + */ + + /** + * Creates an array containing the elements of the host array followed by the + * elements of each argument in order. + * + * @memberOf Benchmark.Suite + * @returns {Array} The new array. + */ + function concat() { + var value, + j = -1, + length = arguments.length, + result = slice.call(this), + index = result.length; + + while (++j < length) { + value = arguments[j]; + if (isClassOf(value, 'Array')) { + for (var k = 0, l = value.length; k < l; k++, index++) { + if (k in value) { + result[index] = value[k]; + } + } + } else { + result[index++] = value; + } + } + return result; + } + + /** + * Utility function used by `shift()`, `splice()`, and `unshift()`. + * + * @private + * @param {Number} start The index to start inserting elements. + * @param {Number} deleteCount The number of elements to delete from the insert point. + * @param {Array} elements The elements to insert. + * @returns {Array} An array of deleted elements. + */ + function insert(start, deleteCount, elements) { + // `result` should have its length set to the `deleteCount` + // see https://bugs.ecmascript.org/show_bug.cgi?id=332 + var deleteEnd = start + deleteCount, + elementCount = elements ? elements.length : 0, + index = start - 1, + length = start + elementCount, + object = this, + result = Array(deleteCount), + tail = slice.call(object, deleteEnd); + + // delete elements from the array + while (++index < deleteEnd) { + if (index in object) { + result[index - start] = object[index]; + delete object[index]; + } + } + // insert elements + index = start - 1; + while (++index < length) { + object[index] = elements[index - start]; + } + // append tail elements + start = index--; + length = max(0, (object.length >>> 0) - deleteCount + elementCount); + while (++index < length) { + if ((index - start) in tail) { + object[index] = tail[index - start]; + } else if (index in object) { + delete object[index]; + } + } + // delete excess elements + deleteCount = deleteCount > elementCount ? deleteCount - elementCount : 0; + while (deleteCount--) { + index = length + deleteCount; + if (index in object) { + delete object[index]; + } + } + object.length = length; + return result; + } + + /** + * Rearrange the host array's elements in reverse order. + * + * @memberOf Benchmark.Suite + * @returns {Array} The reversed array. + */ + function reverse() { + var upperIndex, + value, + index = -1, + object = Object(this), + length = object.length >>> 0, + middle = floor(length / 2); + + if (length > 1) { + while (++index < middle) { + upperIndex = length - index - 1; + value = upperIndex in object ? object[upperIndex] : uid; + if (index in object) { + object[upperIndex] = object[index]; + } else { + delete object[upperIndex]; + } + if (value != uid) { + object[index] = value; + } else { + delete object[index]; + } + } + } + return object; + } + + /** + * Removes the first element of the host array and returns it. + * + * @memberOf Benchmark.Suite + * @returns {Mixed} The first element of the array. + */ + function shift() { + return insert.call(this, 0, 1)[0]; + } + + /** + * Creates an array of the host array's elements from the start index up to, + * but not including, the end index. + * + * @memberOf Benchmark.Suite + * @param {Number} start The starting index. + * @param {Number} end The end index. + * @returns {Array} The new array. + */ + function slice(start, end) { + var index = -1, + object = Object(this), + length = object.length >>> 0, + result = []; + + start = toInteger(start); + start = start < 0 ? max(length + start, 0) : min(start, length); + start--; + end = end == null ? length : toInteger(end); + end = end < 0 ? max(length + end, 0) : min(end, length); + + while ((++index, ++start) < end) { + if (start in object) { + result[index] = object[start]; + } + } + return result; + } + + /** + * Allows removing a range of elements and/or inserting elements into the + * host array. + * + * @memberOf Benchmark.Suite + * @param {Number} start The start index. + * @param {Number} deleteCount The number of elements to delete. + * @param {Mixed} [val1, val2, ...] values to insert at the `start` index. + * @returns {Array} An array of removed elements. + */ + function splice(start, deleteCount) { + var object = Object(this), + length = object.length >>> 0; + + start = toInteger(start); + start = start < 0 ? max(length + start, 0) : min(start, length); + + // support the de-facto SpiderMonkey extension + // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice#Parameters + // https://bugs.ecmascript.org/show_bug.cgi?id=429 + deleteCount = arguments.length == 1 + ? length - start + : min(max(toInteger(deleteCount), 0), length - start); + + return insert.call(object, start, deleteCount, slice.call(arguments, 2)); + } + + /** + * Converts the specified `value` to an integer. + * + * @private + * @param {Mixed} value The value to convert. + * @returns {Number} The resulting integer. + */ + function toInteger(value) { + value = +value; + return value === 0 || !isFinite(value) ? value || 0 : value - (value % 1); + } + + /** + * Appends arguments to the host array. + * + * @memberOf Benchmark.Suite + * @returns {Number} The new length. + */ + function unshift() { + var object = Object(this); + insert.call(object, 0, 0, arguments); + return object.length; + } + + /*--------------------------------------------------------------------------*/ + + /** + * A generic `Function#bind` like method. + * + * @private + * @param {Function} fn The function to be bound to `thisArg`. + * @param {Mixed} thisArg The `this` binding for the given function. + * @returns {Function} The bound function. + */ + function bind(fn, thisArg) { + return function() { fn.apply(thisArg, arguments); }; + } + + /** + * Creates a function from the given arguments string and body. + * + * @private + * @param {String} args The comma separated function arguments. + * @param {String} body The function body. + * @returns {Function} The new function. + */ + function createFunction() { + // lazy define + createFunction = function(args, body) { + var result, + anchor = freeDefine ? define.amd : Benchmark, + prop = uid + 'createFunction'; + + runScript((freeDefine ? 'define.amd.' : 'Benchmark.') + prop + '=function(' + args + '){' + body + '}'); + result = anchor[prop]; + delete anchor[prop]; + return result; + }; + // fix JaegerMonkey bug + // http://bugzil.la/639720 + createFunction = support.browser && (createFunction('', 'return"' + uid + '"') || noop)() == uid ? createFunction : Function; + return createFunction.apply(null, arguments); + } + + /** + * Delay the execution of a function based on the benchmark's `delay` property. + * + * @private + * @param {Object} bench The benchmark instance. + * @param {Object} fn The function to execute. + */ + function delay(bench, fn) { + bench._timerId = setTimeout(fn, bench.delay * 1e3); + } + + /** + * Destroys the given element. + * + * @private + * @param {Element} element The element to destroy. + */ + function destroyElement(element) { + trash.appendChild(element); + trash.innerHTML = ''; + } + + /** + * Iterates over an object's properties, executing the `callback` for each. + * Callbacks may terminate the loop by explicitly returning `false`. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} callback The function executed per own property. + * @param {Object} options The options object. + * @returns {Object} Returns the object iterated over. + */ + function forProps() { + var forShadowed, + skipSeen, + forArgs = true, + shadowed = ['constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf']; + + (function(enumFlag, key) { + // must use a non-native constructor to catch the Safari 2 issue + function Klass() { this.valueOf = 0; }; + Klass.prototype.valueOf = 0; + // check various for-in bugs + for (key in new Klass) { + enumFlag += key == 'valueOf' ? 1 : 0; + } + // check if `arguments` objects have non-enumerable indexes + for (key in arguments) { + key == '0' && (forArgs = false); + } + // Safari 2 iterates over shadowed properties twice + // http://replay.waybackmachine.org/20090428222941/http://tobielangel.com/2007/1/29/for-in-loop-broken-in-safari/ + skipSeen = enumFlag == 2; + // IE < 9 incorrectly makes an object's properties non-enumerable if they have + // the same name as other non-enumerable properties in its prototype chain. + forShadowed = !enumFlag; + }(0)); + + // lazy define + forProps = function(object, callback, options) { + options || (options = {}); + + var result = object; + object = Object(object); + + var ctor, + key, + keys, + skipCtor, + done = !result, + which = options.which, + allFlag = which == 'all', + index = -1, + iteratee = object, + length = object.length, + ownFlag = allFlag || which == 'own', + seen = {}, + skipProto = isClassOf(object, 'Function'), + thisArg = options.bind; + + if (thisArg !== undefined) { + callback = bind(callback, thisArg); + } + // iterate all properties + if (allFlag && support.getAllKeys) { + for (index = 0, keys = getAllKeys(object), length = keys.length; index < length; index++) { + key = keys[index]; + if (callback(object[key], key, object) === false) { + break; + } + } + } + // else iterate only enumerable properties + else { + for (key in object) { + // Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1 + // (if the prototype or a property on the prototype has been set) + // incorrectly set a function's `prototype` property [[Enumerable]] value + // to `true`. Because of this we standardize on skipping the `prototype` + // property of functions regardless of their [[Enumerable]] value. + if ((done = + !(skipProto && key == 'prototype') && + !(skipSeen && (hasKey(seen, key) || !(seen[key] = true))) && + (!ownFlag || ownFlag && hasKey(object, key)) && + callback(object[key], key, object) === false)) { + break; + } + } + // in IE < 9 strings don't support accessing characters by index + if (!done && (forArgs && isArguments(object) || + ((noCharByIndex || noCharByOwnIndex) && isClassOf(object, 'String') && + (iteratee = noCharByIndex ? object.split('') : object)))) { + while (++index < length) { + if ((done = + callback(iteratee[index], String(index), object) === false)) { + break; + } + } + } + if (!done && forShadowed) { + // Because IE < 9 can't set the `[[Enumerable]]` attribute of an existing + // property and the `constructor` property of a prototype defaults to + // non-enumerable, we manually skip the `constructor` property when we + // think we are iterating over a `prototype` object. + ctor = object.constructor; + skipCtor = ctor && ctor.prototype && ctor.prototype.constructor === ctor; + for (index = 0; index < 7; index++) { + key = shadowed[index]; + if (!(skipCtor && key == 'constructor') && + hasKey(object, key) && + callback(object[key], key, object) === false) { + break; + } + } + } + } + return result; + }; + return forProps.apply(null, arguments); + } + + /** + * Gets the name of the first argument from a function's source. + * + * @private + * @param {Function} fn The function. + * @returns {String} The argument name. + */ + function getFirstArgument(fn) { + return (!hasKey(fn, 'toString') && + (/^[\s(]*function[^(]*\(([^\s,)]+)/.exec(fn) || 0)[1]) || ''; + } + + /** + * Computes the geometric mean (log-average) of a sample. + * See http://en.wikipedia.org/wiki/Geometric_mean#Relationship_with_arithmetic_mean_of_logarithms. + * + * @private + * @param {Array} sample The sample. + * @returns {Number} The geometric mean. + */ + function getGeometricMean(sample) { + return pow(Math.E, reduce(sample, function(sum, x) { + return sum + log(x); + }) / sample.length) || 0; + } + + /** + * Computes the arithmetic mean of a sample. + * + * @private + * @param {Array} sample The sample. + * @returns {Number} The mean. + */ + function getMean(sample) { + return (reduce(sample, function(sum, x) { + return sum + x; + }) / sample.length) || 0; + } + + /** + * Gets the source code of a function. + * + * @private + * @param {Function} fn The function. + * @param {String} altSource A string used when a function's source code is unretrievable. + * @returns {String} The function's source code. + */ + function getSource(fn, altSource) { + var result = altSource; + if (isStringable(fn)) { + result = String(fn); + } else if (support.decompilation) { + // escape the `{` for Firefox 1 + result = (/^[^{]+\{([\s\S]*)\}\s*$/.exec(fn) || 0)[1]; + } + // trim string + result = (result || '').replace(/^\s+|\s+$/g, ''); + + // detect strings containing only the "use strict" directive + return /^(?:\/\*+[\w|\W]*?\*\/|\/\/.*?[\n\r\u2028\u2029]|\s)*(["'])use strict\1;?$/.test(result) + ? '' + : result; + } + + /** + * Checks if a value is an `arguments` object. + * + * @private + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the value is an `arguments` object, else `false`. + */ + function isArguments() { + // lazy define + isArguments = function(value) { + return toString.call(value) == '[object Arguments]'; + }; + if (noArgumentsClass) { + isArguments = function(value) { + return hasKey(value, 'callee') && + !(propertyIsEnumerable && propertyIsEnumerable.call(value, 'callee')); + }; + } + return isArguments(arguments[0]); + } + + /** + * Checks if an object is of the specified class. + * + * @private + * @param {Mixed} value The value to check. + * @param {String} name The name of the class. + * @returns {Boolean} Returns `true` if the value is of the specified class, else `false`. + */ + function isClassOf(value, name) { + return value != null && toString.call(value) == '[object ' + name + ']'; + } + + /** + * Host objects can return type values that are different from their actual + * data type. The objects we are concerned with usually return non-primitive + * types of object, function, or unknown. + * + * @private + * @param {Mixed} object The owner of the property. + * @param {String} property The property to check. + * @returns {Boolean} Returns `true` if the property value is a non-primitive, else `false`. + */ + function isHostType(object, property) { + var type = object != null ? typeof object[property] : 'number'; + return !/^(?:boolean|number|string|undefined)$/.test(type) && + (type == 'object' ? !!object[property] : true); + } + + /** + * Checks if a given `value` is an object created by the `Object` constructor + * assuming objects created by the `Object` constructor have no inherited + * enumerable properties and that there are no `Object.prototype` extensions. + * + * @private + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the `value` is a plain `Object` object, else `false`. + */ + function isPlainObject(value) { + // avoid non-objects and false positives for `arguments` objects in IE < 9 + var result = false; + if (!(value && typeof value == 'object') || isArguments(value)) { + return result; + } + // IE < 9 presents DOM nodes as `Object` objects except they have `toString` + // methods that are `typeof` "string" and still can coerce nodes to strings. + // Also check that the constructor is `Object` (i.e. `Object instanceof Object`) + var ctor = value.constructor; + if ((support.nodeClass || !(typeof value.toString != 'function' && typeof (value + '') == 'string')) && + (!isClassOf(ctor, 'Function') || ctor instanceof ctor)) { + // In most environments an object's own properties are iterated before + // its inherited properties. If the last iterated property is an object's + // own property then there are no inherited enumerable properties. + if (support.iteratesOwnFirst) { + forProps(value, function(subValue, subKey) { + result = subKey; + }); + return result === false || hasKey(value, result); + } + // IE < 9 iterates inherited properties before own properties. If the first + // iterated property is an object's own property then there are no inherited + // enumerable properties. + forProps(value, function(subValue, subKey) { + result = !hasKey(value, subKey); + return false; + }); + return result === false; + } + return result; + } + + /** + * Checks if a value can be safely coerced to a string. + * + * @private + * @param {Mixed} value The value to check. + * @returns {Boolean} Returns `true` if the value can be coerced, else `false`. + */ + function isStringable(value) { + return hasKey(value, 'toString') || isClassOf(value, 'String'); + } + + /** + * Wraps a function and passes `this` to the original function as the + * first argument. + * + * @private + * @param {Function} fn The function to be wrapped. + * @returns {Function} The new function. + */ + function methodize(fn) { + return function() { + var args = [this]; + args.push.apply(args, arguments); + return fn.apply(null, args); + }; + } + + /** + * A no-operation function. + * + * @private + */ + function noop() { + // no operation performed + } + + /** + * A wrapper around require() to suppress `module missing` errors. + * + * @private + * @param {String} id The module id. + * @returns {Mixed} The exported module or `null`. + */ + function req(id) { + try { + var result = freeExports && freeRequire(id); + } catch(e) { } + return result || null; + } + + /** + * Runs a snippet of JavaScript via script injection. + * + * @private + * @param {String} code The code to run. + */ + function runScript(code) { + var anchor = freeDefine ? define.amd : Benchmark, + script = doc.createElement('script'), + sibling = doc.getElementsByTagName('script')[0], + parent = sibling.parentNode, + prop = uid + 'runScript', + prefix = '(' + (freeDefine ? 'define.amd.' : 'Benchmark.') + prop + '||function(){})();'; + + // Firefox 2.0.0.2 cannot use script injection as intended because it executes + // asynchronously, but that's OK because script injection is only used to avoid + // the previously commented JaegerMonkey bug. + try { + // remove the inserted script *before* running the code to avoid differences + // in the expected script element count/order of the document. + script.appendChild(doc.createTextNode(prefix + code)); + anchor[prop] = function() { destroyElement(script); }; + } catch(e) { + parent = parent.cloneNode(false); + sibling = null; + script.text = code; + } + parent.insertBefore(script, sibling); + delete anchor[prop]; + } + + /** + * A helper function for setting options/event handlers. + * + * @private + * @param {Object} bench The benchmark instance. + * @param {Object} [options={}] Options object. + */ + function setOptions(bench, options) { + options = extend({}, bench.constructor.options, options); + bench.options = forOwn(options, function(value, key) { + if (value != null) { + // add event listeners + if (/^on[A-Z]/.test(key)) { + forEach(key.split(' '), function(key) { + bench.on(key.slice(2).toLowerCase(), value); + }); + } else if (!hasKey(bench, key)) { + bench[key] = deepClone(value); + } + } + }); + } + + /*--------------------------------------------------------------------------*/ + + /** + * Handles cycling/completing the deferred benchmark. + * + * @memberOf Benchmark.Deferred + */ + function resolve() { + var me = this, + clone = me.benchmark, + bench = clone._original; + + if (bench.aborted) { + // cycle() -> clone cycle/complete event -> compute()'s invoked bench.run() cycle/complete + me.teardown(); + clone.running = false; + cycle(me); + } + else if (++me.cycles < clone.count) { + // continue the test loop + if (support.timeout) { + // use setTimeout to avoid a call stack overflow if called recursively + setTimeout(function() { clone.compiled.call(me, timer); }, 0); + } else { + clone.compiled.call(me, timer); + } + } + else { + timer.stop(me); + me.teardown(); + delay(clone, function() { cycle(me); }); + } + } + + /*--------------------------------------------------------------------------*/ + + /** + * A deep clone utility. + * + * @static + * @memberOf Benchmark + * @param {Mixed} value The value to clone. + * @returns {Mixed} The cloned value. + */ + function deepClone(value) { + var accessor, + circular, + clone, + ctor, + descriptor, + extensible, + key, + length, + markerKey, + parent, + result, + source, + subIndex, + data = { 'value': value }, + index = 0, + marked = [], + queue = { 'length': 0 }, + unmarked = []; + + /** + * An easily detectable decorator for cloned values. + */ + function Marker(object) { + this.raw = object; + } + + /** + * The callback used by `forProps()`. + */ + function forPropsCallback(subValue, subKey) { + // exit early to avoid cloning the marker + if (subValue && subValue.constructor == Marker) { + return; + } + // add objects to the queue + if (subValue === Object(subValue)) { + queue[queue.length++] = { 'key': subKey, 'parent': clone, 'source': value }; + } + // assign non-objects + else { + try { + // will throw an error in strict mode if the property is read-only + clone[subKey] = subValue; + } catch(e) { } + } + } + + /** + * Gets an available marker key for the given object. + */ + function getMarkerKey(object) { + // avoid collisions with existing keys + var result = uid; + while (object[result] && object[result].constructor != Marker) { + result += 1; + } + return result; + } + + do { + key = data.key; + parent = data.parent; + source = data.source; + clone = value = source ? source[key] : data.value; + accessor = circular = descriptor = false; + + // create a basic clone to filter out functions, DOM elements, and + // other non `Object` objects + if (value === Object(value)) { + // use custom deep clone function if available + if (isClassOf(value.deepClone, 'Function')) { + clone = value.deepClone(); + } else { + ctor = value.constructor; + switch (toString.call(value)) { + case '[object Array]': + clone = new ctor(value.length); + break; + + case '[object Boolean]': + clone = new ctor(value == true); + break; + + case '[object Date]': + clone = new ctor(+value); + break; + + case '[object Object]': + isPlainObject(value) && (clone = {}); + break; + + case '[object Number]': + case '[object String]': + clone = new ctor(value); + break; + + case '[object RegExp]': + clone = ctor(value.source, + (value.global ? 'g' : '') + + (value.ignoreCase ? 'i' : '') + + (value.multiline ? 'm' : '')); + } + } + // continue clone if `value` doesn't have an accessor descriptor + // http://es5.github.com/#x8.10.1 + if (clone && clone != value && + !(descriptor = source && support.descriptors && getDescriptor(source, key), + accessor = descriptor && (descriptor.get || descriptor.set))) { + // use an existing clone (circular reference) + if ((extensible = isExtensible(value))) { + markerKey = getMarkerKey(value); + if (value[markerKey]) { + circular = clone = value[markerKey].raw; + } + } else { + // for frozen/sealed objects + for (subIndex = 0, length = unmarked.length; subIndex < length; subIndex++) { + data = unmarked[subIndex]; + if (data.object === value) { + circular = clone = data.clone; + break; + } + } + } + if (!circular) { + // mark object to allow quickly detecting circular references and tie it to its clone + if (extensible) { + value[markerKey] = new Marker(clone); + marked.push({ 'key': markerKey, 'object': value }); + } else { + // for frozen/sealed objects + unmarked.push({ 'clone': clone, 'object': value }); + } + // iterate over object properties + forProps(value, forPropsCallback, { 'which': 'all' }); + } + } + } + if (parent) { + // for custom property descriptors + if (accessor || (descriptor && !(descriptor.configurable && descriptor.enumerable && descriptor.writable))) { + if ('value' in descriptor) { + descriptor.value = clone; + } + setDescriptor(parent, key, descriptor); + } + // for default property descriptors + else { + parent[key] = clone; + } + } else { + result = clone; + } + } while ((data = queue[index++])); + + // remove markers + for (index = 0, length = marked.length; index < length; index++) { + data = marked[index]; + delete data.object[data.key]; + } + return result; + } + + /** + * An iteration utility for arrays and objects. + * Callbacks may terminate the loop by explicitly returning `false`. + * + * @static + * @memberOf Benchmark + * @param {Array|Object} object The object to iterate over. + * @param {Function} callback The function called per iteration. + * @param {Mixed} thisArg The `this` binding for the callback. + * @returns {Array|Object} Returns the object iterated over. + */ + function each(object, callback, thisArg) { + var result = object; + object = Object(object); + + var fn = callback, + index = -1, + length = object.length, + isSnapshot = !!(object.snapshotItem && (length = object.snapshotLength)), + isSplittable = (noCharByIndex || noCharByOwnIndex) && isClassOf(object, 'String'), + isConvertable = isSnapshot || isSplittable || 'item' in object, + origObject = object; + + // in Opera < 10.5 `hasKey(object, 'length')` returns `false` for NodeLists + if (length === length >>> 0) { + if (isConvertable) { + // the third argument of the callback is the original non-array object + callback = function(value, index) { + return fn.call(this, value, index, origObject); + }; + // in IE < 9 strings don't support accessing characters by index + if (isSplittable) { + object = object.split(''); + } else { + object = []; + while (++index < length) { + // in Safari 2 `index in object` is always `false` for NodeLists + object[index] = isSnapshot ? result.snapshotItem(index) : result[index]; + } + } + } + forEach(object, callback, thisArg); + } else { + forOwn(object, callback, thisArg); + } + return result; + } + + /** + * Copies enumerable properties from the source(s) object to the destination object. + * + * @static + * @memberOf Benchmark + * @param {Object} destination The destination object. + * @param {Object} [source={}] The source object. + * @returns {Object} The destination object. + */ + function extend(destination, source) { + // Chrome < 14 incorrectly sets `destination` to `undefined` when we `delete arguments[0]` + // http://code.google.com/p/v8/issues/detail?id=839 + var result = destination; + delete arguments[0]; + + forEach(arguments, function(source) { + forProps(source, function(value, key) { + result[key] = value; + }); + }); + return result; + } + + /** + * A generic `Array#filter` like method. + * + * @static + * @memberOf Benchmark + * @param {Array} array The array to iterate over. + * @param {Function|String} callback The function/alias called per iteration. + * @param {Mixed} thisArg The `this` binding for the callback. + * @returns {Array} A new array of values that passed callback filter. + * @example + * + * // get odd numbers + * Benchmark.filter([1, 2, 3, 4, 5], function(n) { + * return n % 2; + * }); // -> [1, 3, 5]; + * + * // get fastest benchmarks + * Benchmark.filter(benches, 'fastest'); + * + * // get slowest benchmarks + * Benchmark.filter(benches, 'slowest'); + * + * // get benchmarks that completed without erroring + * Benchmark.filter(benches, 'successful'); + */ + function filter(array, callback, thisArg) { + var result; + + if (callback == 'successful') { + // callback to exclude those that are errored, unrun, or have hz of Infinity + callback = function(bench) { return bench.cycles && isFinite(bench.hz); }; + } + else if (callback == 'fastest' || callback == 'slowest') { + // get successful, sort by period + margin of error, and filter fastest/slowest + result = filter(array, 'successful').sort(function(a, b) { + a = a.stats; b = b.stats; + return (a.mean + a.moe > b.mean + b.moe ? 1 : -1) * (callback == 'fastest' ? 1 : -1); + }); + result = filter(result, function(bench) { + return result[0].compare(bench) == 0; + }); + } + return result || reduce(array, function(result, value, index) { + return callback.call(thisArg, value, index, array) ? (result.push(value), result) : result; + }, []); + } + + /** + * A generic `Array#forEach` like method. + * Callbacks may terminate the loop by explicitly returning `false`. + * + * @static + * @memberOf Benchmark + * @param {Array} array The array to iterate over. + * @param {Function} callback The function called per iteration. + * @param {Mixed} thisArg The `this` binding for the callback. + * @returns {Array} Returns the array iterated over. + */ + function forEach(array, callback, thisArg) { + var index = -1, + length = (array = Object(array)).length >>> 0; + + if (thisArg !== undefined) { + callback = bind(callback, thisArg); + } + while (++index < length) { + if (index in array && + callback(array[index], index, array) === false) { + break; + } + } + return array; + } + + /** + * Iterates over an object's own properties, executing the `callback` for each. + * Callbacks may terminate the loop by explicitly returning `false`. + * + * @static + * @memberOf Benchmark + * @param {Object} object The object to iterate over. + * @param {Function} callback The function executed per own property. + * @param {Mixed} thisArg The `this` binding for the callback. + * @returns {Object} Returns the object iterated over. + */ + function forOwn(object, callback, thisArg) { + return forProps(object, callback, { 'bind': thisArg, 'which': 'own' }); + } + + /** + * Converts a number to a more readable comma-separated string representation. + * + * @static + * @memberOf Benchmark + * @param {Number} number The number to convert. + * @returns {String} The more readable string representation. + */ + function formatNumber(number) { + number = String(number).split('.'); + return number[0].replace(/(?=(?:\d{3})+$)(?!\b)/g, ',') + + (number[1] ? '.' + number[1] : ''); + } + + /** + * Checks if an object has the specified key as a direct property. + * + * @static + * @memberOf Benchmark + * @param {Object} object The object to check. + * @param {String} key The key to check for. + * @returns {Boolean} Returns `true` if key is a direct property, else `false`. + */ + function hasKey() { + // lazy define for worst case fallback (not as accurate) + hasKey = function(object, key) { + var parent = object != null && (object.constructor || Object).prototype; + return !!parent && key in Object(object) && !(key in parent && object[key] === parent[key]); + }; + // for modern browsers + if (isClassOf(hasOwnProperty, 'Function')) { + hasKey = function(object, key) { + return object != null && hasOwnProperty.call(object, key); + }; + } + // for Safari 2 + else if ({}.__proto__ == Object.prototype) { + hasKey = function(object, key) { + var result = false; + if (object != null) { + object = Object(object); + object.__proto__ = [object.__proto__, object.__proto__ = null, result = key in object][0]; + } + return result; + }; + } + return hasKey.apply(this, arguments); + } + + /** + * A generic `Array#indexOf` like method. + * + * @static + * @memberOf Benchmark + * @param {Array} array The array to iterate over. + * @param {Mixed} value The value to search for. + * @param {Number} [fromIndex=0] The index to start searching from. + * @returns {Number} The index of the matched value or `-1`. + */ + function indexOf(array, value, fromIndex) { + var index = toInteger(fromIndex), + length = (array = Object(array)).length >>> 0; + + index = (index < 0 ? max(0, length + index) : index) - 1; + while (++index < length) { + if (index in array && value === array[index]) { + return index; + } + } + return -1; + } + + /** + * Modify a string by replacing named tokens with matching object property values. + * + * @static + * @memberOf Benchmark + * @param {String} string The string to modify. + * @param {Object} object The template object. + * @returns {String} The modified string. + */ + function interpolate(string, object) { + forOwn(object, function(value, key) { + // escape regexp special characters in `key` + string = string.replace( + RegExp('#\\{' + key.replace(/([.*+?^${}()|[\]\\])/g, '\\$1') + '\\}', 'g'), + value.replace(/\$/g, '$$$$') + ); + }); + return string; + } + + /** + * Invokes a method on all items in an array. + * + * @static + * @memberOf Benchmark + * @param {Array} benches Array of benchmarks to iterate over. + * @param {String|Object} name The name of the method to invoke OR options object. + * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with. + * @returns {Array} A new array of values returned from each method invoked. + * @example + * + * // invoke `reset` on all benchmarks + * Benchmark.invoke(benches, 'reset'); + * + * // invoke `emit` with arguments + * Benchmark.invoke(benches, 'emit', 'complete', listener); + * + * // invoke `run(true)`, treat benchmarks as a queue, and register invoke callbacks + * Benchmark.invoke(benches, { + * + * // invoke the `run` method + * 'name': 'run', + * + * // pass a single argument + * 'args': true, + * + * // treat as queue, removing benchmarks from front of `benches` until empty + * 'queued': true, + * + * // called before any benchmarks have been invoked. + * 'onStart': onStart, + * + * // called between invoking benchmarks + * 'onCycle': onCycle, + * + * // called after all benchmarks have been invoked. + * 'onComplete': onComplete + * }); + */ + function invoke(benches, name) { + var args, + bench, + queued, + index = -1, + eventProps = { 'currentTarget': benches }, + options = { 'onStart': noop, 'onCycle': noop, 'onComplete': noop }, + result = map(benches, function(bench) { return bench; }); + + /** + * Invokes the method of the current object and if synchronous, fetches the next. + */ + function execute() { + var listeners, + async = isAsync(bench); + + if (async) { + // use `getNext` as the first listener + bench.on('complete', getNext); + listeners = bench.events.complete; + listeners.splice(0, 0, listeners.pop()); + } + // execute method + result[index] = isClassOf(bench && bench[name], 'Function') ? bench[name].apply(bench, args) : undefined; + // if synchronous return true until finished + return !async && getNext(); + } + + /** + * Fetches the next bench or executes `onComplete` callback. + */ + function getNext(event) { + var cycleEvent, + last = bench, + async = isAsync(last); + + if (async) { + last.off('complete', getNext); + last.emit('complete'); + } + // emit "cycle" event + eventProps.type = 'cycle'; + eventProps.target = last; + cycleEvent = Event(eventProps); + options.onCycle.call(benches, cycleEvent); + + // choose next benchmark if not exiting early + if (!cycleEvent.aborted && raiseIndex() !== false) { + bench = queued ? benches[0] : result[index]; + if (isAsync(bench)) { + delay(bench, execute); + } + else if (async) { + // resume execution if previously asynchronous but now synchronous + while (execute()) { } + } + else { + // continue synchronous execution + return true; + } + } else { + // emit "complete" event + eventProps.type = 'complete'; + options.onComplete.call(benches, Event(eventProps)); + } + // When used as a listener `event.aborted = true` will cancel the rest of + // the "complete" listeners because they were already called above and when + // used as part of `getNext` the `return false` will exit the execution while-loop. + if (event) { + event.aborted = true; + } else { + return false; + } + } + + /** + * Checks if invoking `Benchmark#run` with asynchronous cycles. + */ + function isAsync(object) { + // avoid using `instanceof` here because of IE memory leak issues with host objects + var async = args[0] && args[0].async; + return Object(object).constructor == Benchmark && name == 'run' && + ((async == null ? object.options.async : async) && support.timeout || object.defer); + } + + /** + * Raises `index` to the next defined index or returns `false`. + */ + function raiseIndex() { + var length = result.length; + if (queued) { + // if queued remove the previous bench and subsequent skipped non-entries + do { + ++index > 0 && shift.call(benches); + } while ((length = benches.length) && !('0' in benches)); + } + else { + while (++index < length && !(index in result)) { } + } + // if we reached the last index then return `false` + return (queued ? length : index < length) ? index : (index = false); + } + + // juggle arguments + if (isClassOf(name, 'String')) { + // 2 arguments (array, name) + args = slice.call(arguments, 2); + } else { + // 2 arguments (array, options) + options = extend(options, name); + name = options.name; + args = isClassOf(args = 'args' in options ? options.args : [], 'Array') ? args : [args]; + queued = options.queued; + } + + // start iterating over the array + if (raiseIndex() !== false) { + // emit "start" event + bench = result[index]; + eventProps.type = 'start'; + eventProps.target = bench; + options.onStart.call(benches, Event(eventProps)); + + // end early if the suite was aborted in an "onStart" listener + if (benches.aborted && benches.constructor == Suite && name == 'run') { + // emit "cycle" event + eventProps.type = 'cycle'; + options.onCycle.call(benches, Event(eventProps)); + // emit "complete" event + eventProps.type = 'complete'; + options.onComplete.call(benches, Event(eventProps)); + } + // else start + else { + if (isAsync(bench)) { + delay(bench, execute); + } else { + while (execute()) { } + } + } + } + return result; + } + + /** + * Creates a string of joined array values or object key-value pairs. + * + * @static + * @memberOf Benchmark + * @param {Array|Object} object The object to operate on. + * @param {String} [separator1=','] The separator used between key-value pairs. + * @param {String} [separator2=': '] The separator used between keys and values. + * @returns {String} The joined result. + */ + function join(object, separator1, separator2) { + var result = [], + length = (object = Object(object)).length, + arrayLike = length === length >>> 0; + + separator2 || (separator2 = ': '); + each(object, function(value, key) { + result.push(arrayLike ? value : key + separator2 + value); + }); + return result.join(separator1 || ','); + } + + /** + * A generic `Array#map` like method. + * + * @static + * @memberOf Benchmark + * @param {Array} array The array to iterate over. + * @param {Function} callback The function called per iteration. + * @param {Mixed} thisArg The `this` binding for the callback. + * @returns {Array} A new array of values returned by the callback. + */ + function map(array, callback, thisArg) { + return reduce(array, function(result, value, index) { + result[index] = callback.call(thisArg, value, index, array); + return result; + }, Array(Object(array).length >>> 0)); + } + + /** + * Retrieves the value of a specified property from all items in an array. + * + * @static + * @memberOf Benchmark + * @param {Array} array The array to iterate over. + * @param {String} property The property to pluck. + * @returns {Array} A new array of property values. + */ + function pluck(array, property) { + return map(array, function(object) { + return object == null ? undefined : object[property]; + }); + } + + /** + * A generic `Array#reduce` like method. + * + * @static + * @memberOf Benchmark + * @param {Array} array The array to iterate over. + * @param {Function} callback The function called per iteration. + * @param {Mixed} accumulator Initial value of the accumulator. + * @returns {Mixed} The accumulator. + */ + function reduce(array, callback, accumulator) { + var noaccum = arguments.length < 3; + forEach(array, function(value, index) { + accumulator = noaccum ? (noaccum = false, value) : callback(accumulator, value, index, array); + }); + return accumulator; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Aborts all benchmarks in the suite. + * + * @name abort + * @memberOf Benchmark.Suite + * @returns {Object} The suite instance. + */ + function abortSuite() { + var event, + me = this, + resetting = calledBy.resetSuite; + + if (me.running) { + event = Event('abort'); + me.emit(event); + if (!event.cancelled || resetting) { + // avoid infinite recursion + calledBy.abortSuite = true; + me.reset(); + delete calledBy.abortSuite; + + if (!resetting) { + me.aborted = true; + invoke(me, 'abort'); + } + } + } + return me; + } + + /** + * Adds a test to the benchmark suite. + * + * @memberOf Benchmark.Suite + * @param {String} name A name to identify the benchmark. + * @param {Function|String} fn The test to benchmark. + * @param {Object} [options={}] Options object. + * @returns {Object} The benchmark instance. + * @example + * + * // basic usage + * suite.add(fn); + * + * // or using a name first + * suite.add('foo', fn); + * + * // or with options + * suite.add('foo', fn, { + * 'onCycle': onCycle, + * 'onComplete': onComplete + * }); + * + * // or name and options + * suite.add('foo', { + * 'fn': fn, + * 'onCycle': onCycle, + * 'onComplete': onComplete + * }); + * + * // or options only + * suite.add({ + * 'name': 'foo', + * 'fn': fn, + * 'onCycle': onCycle, + * 'onComplete': onComplete + * }); + */ + function add(name, fn, options) { + var me = this, + bench = Benchmark(name, fn, options), + event = Event({ 'type': 'add', 'target': bench }); + + if (me.emit(event), !event.cancelled) { + me.push(bench); + } + return me; + } + + /** + * Creates a new suite with cloned benchmarks. + * + * @name clone + * @memberOf Benchmark.Suite + * @param {Object} options Options object to overwrite cloned options. + * @returns {Object} The new suite instance. + */ + function cloneSuite(options) { + var me = this, + result = new me.constructor(extend({}, me.options, options)); + + // copy own properties + forOwn(me, function(value, key) { + if (!hasKey(result, key)) { + result[key] = value && isClassOf(value.clone, 'Function') + ? value.clone() + : deepClone(value); + } + }); + return result; + } + + /** + * An `Array#filter` like method. + * + * @name filter + * @memberOf Benchmark.Suite + * @param {Function|String} callback The function/alias called per iteration. + * @returns {Object} A new suite of benchmarks that passed callback filter. + */ + function filterSuite(callback) { + var me = this, + result = new me.constructor; + + result.push.apply(result, filter(me, callback)); + return result; + } + + /** + * Resets all benchmarks in the suite. + * + * @name reset + * @memberOf Benchmark.Suite + * @returns {Object} The suite instance. + */ + function resetSuite() { + var event, + me = this, + aborting = calledBy.abortSuite; + + if (me.running && !aborting) { + // no worries, `resetSuite()` is called within `abortSuite()` + calledBy.resetSuite = true; + me.abort(); + delete calledBy.resetSuite; + } + // reset if the state has changed + else if ((me.aborted || me.running) && + (me.emit(event = Event('reset')), !event.cancelled)) { + me.running = false; + if (!aborting) { + invoke(me, 'reset'); + } + } + return me; + } + + /** + * Runs the suite. + * + * @name run + * @memberOf Benchmark.Suite + * @param {Object} [options={}] Options object. + * @returns {Object} The suite instance. + * @example + * + * // basic usage + * suite.run(); + * + * // or with options + * suite.run({ 'async': true, 'queued': true }); + */ + function runSuite(options) { + var me = this; + + me.reset(); + me.running = true; + options || (options = {}); + + invoke(me, { + 'name': 'run', + 'args': options, + 'queued': options.queued, + 'onStart': function(event) { + me.emit(event); + }, + 'onCycle': function(event) { + var bench = event.target; + if (bench.error) { + me.emit({ 'type': 'error', 'target': bench }); + } + me.emit(event); + event.aborted = me.aborted; + }, + 'onComplete': function(event) { + me.score = getGeometricMean(map(me, function(bench) { + return bench.reference / (bench.times.period * 1e6); + })) || 0; + + me.running = false; + me.emit(event); + } + }); + return me; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Executes all registered listeners of the specified event type. + * + * @memberOf Benchmark, Benchmark.Suite + * @param {String|Object} type The event type or object. + * @returns {Mixed} Returns the return value of the last listener executed. + */ + function emit(type) { + var listeners, + me = this, + event = Event(type), + events = me.events, + args = (arguments[0] = event, arguments); + + event.currentTarget || (event.currentTarget = me); + event.target || (event.target = me); + delete event.result; + + if (events && (listeners = hasKey(events, event.type) && events[event.type])) { + forEach(listeners.slice(), function(listener) { + if ((event.result = listener.apply(me, args)) === false) { + event.cancelled = true; + } + return !event.aborted; + }); + } + return event.result; + } + + /** + * Returns an array of event listeners for a given type that can be manipulated + * to add or remove listeners. + * + * @memberOf Benchmark, Benchmark.Suite + * @param {String} type The event type. + * @returns {Array} The listeners array. + */ + function listeners(type) { + var me = this, + events = me.events || (me.events = {}); + + return hasKey(events, type) ? events[type] : (events[type] = []); + } + + /** + * Unregisters a listener for the specified event type(s), + * or unregisters all listeners for the specified event type(s), + * or unregisters all listeners for all event types. + * + * @memberOf Benchmark, Benchmark.Suite + * @param {String} [type] The event type. + * @param {Function} [listener] The function to unregister. + * @returns {Object} The benchmark instance. + * @example + * + * // unregister a listener for an event type + * bench.off('cycle', listener); + * + * // unregister a listener for multiple event types + * bench.off('start cycle', listener); + * + * // unregister all listeners for an event type + * bench.off('cycle'); + * + * // unregister all listeners for multiple event types + * bench.off('start cycle complete'); + * + * // unregister all listeners for all event types + * bench.off(); + */ + function off(type, listener) { + var me = this, + events = me.events; + + events && each(type ? type.split(' ') : events, function(listeners, type) { + var index; + if (typeof listeners == 'string') { + type = listeners; + listeners = hasKey(events, type) && events[type]; + } + if (listeners) { + if (listener) { + index = indexOf(listeners, listener); + if (index > -1) { + listeners.splice(index, 1); + } + } else { + listeners.length = 0; + } + } + }); + return me; + } + + /** + * Registers a listener for the specified event type(s). + * + * @memberOf Benchmark, Benchmark.Suite + * @param {String} type The event type. + * @param {Function} listener The function to register. + * @returns {Object} The benchmark instance. + * @example + * + * // register a listener for an event type + * bench.on('cycle', listener); + * + * // register a listener for multiple event types + * bench.on('start cycle', listener); + */ + function on(type, listener) { + var me = this, + events = me.events || (me.events = {}); + + forEach(type.split(' '), function(type) { + (hasKey(events, type) + ? events[type] + : (events[type] = []) + ).push(listener); + }); + return me; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Aborts the benchmark without recording times. + * + * @memberOf Benchmark + * @returns {Object} The benchmark instance. + */ + function abort() { + var event, + me = this, + resetting = calledBy.reset; + + if (me.running) { + event = Event('abort'); + me.emit(event); + if (!event.cancelled || resetting) { + // avoid infinite recursion + calledBy.abort = true; + me.reset(); + delete calledBy.abort; + + if (support.timeout) { + clearTimeout(me._timerId); + delete me._timerId; + } + if (!resetting) { + me.aborted = true; + me.running = false; + } + } + } + return me; + } + + /** + * Creates a new benchmark using the same test and options. + * + * @memberOf Benchmark + * @param {Object} options Options object to overwrite cloned options. + * @returns {Object} The new benchmark instance. + * @example + * + * var bizarro = bench.clone({ + * 'name': 'doppelganger' + * }); + */ + function clone(options) { + var me = this, + result = new me.constructor(extend({}, me, options)); + + // correct the `options` object + result.options = extend({}, me.options, options); + + // copy own custom properties + forOwn(me, function(value, key) { + if (!hasKey(result, key)) { + result[key] = deepClone(value); + } + }); + return result; + } + + /** + * Determines if a benchmark is faster than another. + * + * @memberOf Benchmark + * @param {Object} other The benchmark to compare. + * @returns {Number} Returns `-1` if slower, `1` if faster, and `0` if indeterminate. + */ + function compare(other) { + var critical, + zStat, + me = this, + sample1 = me.stats.sample, + sample2 = other.stats.sample, + size1 = sample1.length, + size2 = sample2.length, + maxSize = max(size1, size2), + minSize = min(size1, size2), + u1 = getU(sample1, sample2), + u2 = getU(sample2, sample1), + u = min(u1, u2); + + function getScore(xA, sampleB) { + return reduce(sampleB, function(total, xB) { + return total + (xB > xA ? 0 : xB < xA ? 1 : 0.5); + }, 0); + } + + function getU(sampleA, sampleB) { + return reduce(sampleA, function(total, xA) { + return total + getScore(xA, sampleB); + }, 0); + } + + function getZ(u) { + return (u - ((size1 * size2) / 2)) / sqrt((size1 * size2 * (size1 + size2 + 1)) / 12); + } + + // exit early if comparing the same benchmark + if (me == other) { + return 0; + } + // reject the null hyphothesis the two samples come from the + // same population (i.e. have the same median) if... + if (size1 + size2 > 30) { + // ...the z-stat is greater than 1.96 or less than -1.96 + // http://www.statisticslectures.com/topics/mannwhitneyu/ + zStat = getZ(u); + return abs(zStat) > 1.96 ? (zStat > 0 ? -1 : 1) : 0; + } + // ...the U value is less than or equal the critical U value + // http://www.geoib.com/mann-whitney-u-test.html + critical = maxSize < 5 || minSize < 3 ? 0 : uTable[maxSize][minSize - 3]; + return u <= critical ? (u == u1 ? 1 : -1) : 0; + } + + /** + * Reset properties and abort if running. + * + * @memberOf Benchmark + * @returns {Object} The benchmark instance. + */ + function reset() { + var data, + event, + me = this, + index = 0, + changes = { 'length': 0 }, + queue = { 'length': 0 }; + + if (me.running && !calledBy.abort) { + // no worries, `reset()` is called within `abort()` + calledBy.reset = true; + me.abort(); + delete calledBy.reset; + } + else { + // a non-recursive solution to check if properties have changed + // http://www.jslab.dk/articles/non.recursive.preorder.traversal.part4 + data = { 'destination': me, 'source': extend({}, me.constructor.prototype, me.options) }; + do { + forOwn(data.source, function(value, key) { + var changed, + destination = data.destination, + currValue = destination[key]; + + if (value && typeof value == 'object') { + if (isClassOf(value, 'Array')) { + // check if an array value has changed to a non-array value + if (!isClassOf(currValue, 'Array')) { + changed = currValue = []; + } + // or has changed its length + if (currValue.length != value.length) { + changed = currValue = currValue.slice(0, value.length); + currValue.length = value.length; + } + } + // check if an object has changed to a non-object value + else if (!currValue || typeof currValue != 'object') { + changed = currValue = {}; + } + // register a changed object + if (changed) { + changes[changes.length++] = { 'destination': destination, 'key': key, 'value': currValue }; + } + queue[queue.length++] = { 'destination': currValue, 'source': value }; + } + // register a changed primitive + else if (value !== currValue && !(value == null || isClassOf(value, 'Function'))) { + changes[changes.length++] = { 'destination': destination, 'key': key, 'value': value }; + } + }); + } + while ((data = queue[index++])); + + // if changed emit the `reset` event and if it isn't cancelled reset the benchmark + if (changes.length && (me.emit(event = Event('reset')), !event.cancelled)) { + forEach(changes, function(data) { + data.destination[data.key] = data.value; + }); + } + } + return me; + } + + /** + * Displays relevant benchmark information when coerced to a string. + * + * @name toString + * @memberOf Benchmark + * @returns {String} A string representation of the benchmark instance. + */ + function toStringBench() { + var me = this, + error = me.error, + hz = me.hz, + id = me.id, + stats = me.stats, + size = stats.sample.length, + pm = support.java ? '+/-' : '\xb1', + result = me.name || (isNaN(id) ? id : ''); + + if (error) { + result += ': ' + join(error); + } else { + result += ' x ' + formatNumber(hz.toFixed(hz < 100 ? 2 : 0)) + ' ops/sec ' + pm + + stats.rme.toFixed(2) + '% (' + size + ' run' + (size == 1 ? '' : 's') + ' sampled)'; + } + return result; + } + + /*--------------------------------------------------------------------------*/ + + /** + * Clocks the time taken to execute a test per cycle (secs). + * + * @private + * @param {Object} bench The benchmark instance. + * @returns {Number} The time taken. + */ + function clock() { + var applet, + options = Benchmark.options, + template = { 'begin': 's$=new n$', 'end': 'r$=(new n$-s$)/1e3', 'uid': uid }, + timers = [{ 'ns': timer.ns, 'res': max(0.0015, getRes('ms')), 'unit': 'ms' }]; + + // lazy define for hi-res timers + clock = function(clone) { + var deferred; + if (clone instanceof Deferred) { + deferred = clone; + clone = deferred.benchmark; + } + + var bench = clone._original, + fn = bench.fn, + fnArg = deferred ? getFirstArgument(fn) || 'deferred' : '', + stringable = isStringable(fn); + + var source = { + 'setup': getSource(bench.setup, preprocess('m$.setup()')), + 'fn': getSource(fn, preprocess('m$.fn(' + fnArg + ')')), + 'fnArg': fnArg, + 'teardown': getSource(bench.teardown, preprocess('m$.teardown()')) + }; + + var count = bench.count = clone.count, + decompilable = support.decompilation || stringable, + id = bench.id, + isEmpty = !(source.fn || stringable), + name = bench.name || (typeof id == 'number' ? '' : id), + ns = timer.ns, + result = 0; + + // init `minTime` if needed + clone.minTime = bench.minTime || (bench.minTime = bench.options.minTime = options.minTime); + + // repair nanosecond timer + // (some Chrome builds erase the `ns` variable after millions of executions) + if (applet) { + try { + ns.nanoTime(); + } catch(e) { + // use non-element to avoid issues with libs that augment them + ns = timer.ns = new applet.Packages.nano; + } + } + + // Compile in setup/teardown functions and the test loop. + // Create a new compiled test, instead of using the cached `bench.compiled`, + // to avoid potential engine optimizations enabled over the life of the test. + var compiled = bench.compiled = createFunction(preprocess('t$'), interpolate( + preprocess(deferred + ? 'var d$=this,#{fnArg}=d$,m$=d$.benchmark._original,f$=m$.fn,su$=m$.setup,td$=m$.teardown;' + + // when `deferred.cycles` is `0` then... + 'if(!d$.cycles){' + + // set `deferred.fn` + 'd$.fn=function(){var #{fnArg}=d$;if(typeof f$=="function"){try{#{fn}\n}catch(e$){f$(d$)}}else{#{fn}\n}};' + + // set `deferred.teardown` + 'd$.teardown=function(){d$.cycles=0;if(typeof td$=="function"){try{#{teardown}\n}catch(e$){td$()}}else{#{teardown}\n}};' + + // execute the benchmark's `setup` + 'if(typeof su$=="function"){try{#{setup}\n}catch(e$){su$()}}else{#{setup}\n};' + + // start timer + 't$.start(d$);' + + // execute `deferred.fn` and return a dummy object + '}d$.fn();return{}' + + : 'var r$,s$,m$=this,f$=m$.fn,i$=m$.count,n$=t$.ns;#{setup}\n#{begin};' + + 'while(i$--){#{fn}\n}#{end};#{teardown}\nreturn{elapsed:r$,uid:"#{uid}"}'), + source + )); + + try { + if (isEmpty) { + // Firefox may remove dead code from Function#toString results + // http://bugzil.la/536085 + throw new Error('The test "' + name + '" is empty. This may be the result of dead code removal.'); + } + else if (!deferred) { + // pretest to determine if compiled code is exits early, usually by a + // rogue `return` statement, by checking for a return object with the uid + bench.count = 1; + compiled = (compiled.call(bench, timer) || {}).uid == uid && compiled; + bench.count = count; + } + } catch(e) { + compiled = null; + clone.error = e || new Error(String(e)); + bench.count = count; + } + // fallback when a test exits early or errors during pretest + if (decompilable && !compiled && !deferred && !isEmpty) { + compiled = createFunction(preprocess('t$'), interpolate( + preprocess( + (clone.error && !stringable + ? 'var r$,s$,m$=this,f$=m$.fn,i$=m$.count' + : 'function f$(){#{fn}\n}var r$,s$,m$=this,i$=m$.count' + ) + + ',n$=t$.ns;#{setup}\n#{begin};m$.f$=f$;while(i$--){m$.f$()}#{end};' + + 'delete m$.f$;#{teardown}\nreturn{elapsed:r$}' + ), + source + )); + + try { + // pretest one more time to check for errors + bench.count = 1; + compiled.call(bench, timer); + bench.compiled = compiled; + bench.count = count; + delete clone.error; + } + catch(e) { + bench.count = count; + if (clone.error) { + compiled = null; + } else { + bench.compiled = compiled; + clone.error = e || new Error(String(e)); + } + } + } + // assign `compiled` to `clone` before calling in case a deferred benchmark + // immediately calls `deferred.resolve()` + clone.compiled = compiled; + // if no errors run the full test loop + if (!clone.error) { + result = compiled.call(deferred || bench, timer).elapsed; + } + return result; + }; + + /*------------------------------------------------------------------------*/ + + /** + * Gets the current timer's minimum resolution (secs). + */ + function getRes(unit) { + var measured, + begin, + count = 30, + divisor = 1e3, + ns = timer.ns, + sample = []; + + // get average smallest measurable time + while (count--) { + if (unit == 'us') { + divisor = 1e6; + if (ns.stop) { + ns.start(); + while (!(measured = ns.microseconds())) { } + } else if (ns[perfName]) { + divisor = 1e3; + measured = Function('n', 'var r,s=n.' + perfName + '();while(!(r=n.' + perfName + '()-s)){};return r')(ns); + } else { + begin = ns(); + while (!(measured = ns() - begin)) { } + } + } + else if (unit == 'ns') { + divisor = 1e9; + if (ns.nanoTime) { + begin = ns.nanoTime(); + while (!(measured = ns.nanoTime() - begin)) { } + } else { + begin = (begin = ns())[0] + (begin[1] / divisor); + while (!(measured = ((measured = ns())[0] + (measured[1] / divisor)) - begin)) { } + divisor = 1; + } + } + else { + begin = new ns; + while (!(measured = new ns - begin)) { } + } + // check for broken timers (nanoTime may have issues) + // http://alivebutsleepy.srnet.cz/unreliable-system-nanotime/ + if (measured > 0) { + sample.push(measured); + } else { + sample.push(Infinity); + break; + } + } + // convert to seconds + return getMean(sample) / divisor; + } + + /** + * Replaces all occurrences of `$` with a unique number and + * template tokens with content. + */ + function preprocess(code) { + return interpolate(code, template).replace(/\$/g, /\d+/.exec(uid)); + } + + /*------------------------------------------------------------------------*/ + + // detect nanosecond support from a Java applet + each(doc && doc.applets || [], function(element) { + return !(timer.ns = applet = 'nanoTime' in element && element); + }); + + // check type in case Safari returns an object instead of a number + try { + if (typeof timer.ns.nanoTime() == 'number') { + timers.push({ 'ns': timer.ns, 'res': getRes('ns'), 'unit': 'ns' }); + } + } catch(e) { } + + // detect Chrome's microsecond timer: + // enable benchmarking via the --enable-benchmarking command + // line switch in at least Chrome 7 to use chrome.Interval + try { + if ((timer.ns = new (window.chrome || window.chromium).Interval)) { + timers.push({ 'ns': timer.ns, 'res': getRes('us'), 'unit': 'us' }); + } + } catch(e) { } + + // detect `performance.now` microsecond resolution timer + if ((timer.ns = perfName && perfObject)) { + timers.push({ 'ns': timer.ns, 'res': getRes('us'), 'unit': 'us' }); + } + + // detect Node's nanosecond resolution timer available in Node >= 0.8 + if (processObject && typeof (timer.ns = processObject.hrtime) == 'function') { + timers.push({ 'ns': timer.ns, 'res': getRes('ns'), 'unit': 'ns' }); + } + + // detect Wade Simmons' Node microtime module + if (microtimeObject && typeof (timer.ns = microtimeObject.now) == 'function') { + timers.push({ 'ns': timer.ns, 'res': getRes('us'), 'unit': 'us' }); + } + + // pick timer with highest resolution + timer = reduce(timers, function(timer, other) { + return other.res < timer.res ? other : timer; + }); + + // remove unused applet + if (timer.unit != 'ns' && applet) { + applet = destroyElement(applet); + } + // error if there are no working timers + if (timer.res == Infinity) { + throw new Error('Benchmark.js was unable to find a working timer.'); + } + // use API of chosen timer + if (timer.unit == 'ns') { + if (timer.ns.nanoTime) { + extend(template, { + 'begin': 's$=n$.nanoTime()', + 'end': 'r$=(n$.nanoTime()-s$)/1e9' + }); + } else { + extend(template, { + 'begin': 's$=n$()', + 'end': 'r$=n$(s$);r$=r$[0]+(r$[1]/1e9)' + }); + } + } + else if (timer.unit == 'us') { + if (timer.ns.stop) { + extend(template, { + 'begin': 's$=n$.start()', + 'end': 'r$=n$.microseconds()/1e6' + }); + } else if (perfName) { + extend(template, { + 'begin': 's$=n$.' + perfName + '()', + 'end': 'r$=(n$.' + perfName + '()-s$)/1e3' + }); + } else { + extend(template, { + 'begin': 's$=n$()', + 'end': 'r$=(n$()-s$)/1e6' + }); + } + } + + // define `timer` methods + timer.start = createFunction(preprocess('o$'), + preprocess('var n$=this.ns,#{begin};o$.elapsed=0;o$.timeStamp=s$')); + + timer.stop = createFunction(preprocess('o$'), + preprocess('var n$=this.ns,s$=o$.timeStamp,#{end};o$.elapsed=r$')); + + // resolve time span required to achieve a percent uncertainty of at most 1% + // http://spiff.rit.edu/classes/phys273/uncert/uncert.html + options.minTime || (options.minTime = max(timer.res / 2 / 0.01, 0.05)); + return clock.apply(null, arguments); + } + + /*--------------------------------------------------------------------------*/ + + /** + * Computes stats on benchmark results. + * + * @private + * @param {Object} bench The benchmark instance. + * @param {Object} options The options object. + */ + function compute(bench, options) { + options || (options = {}); + + var async = options.async, + elapsed = 0, + initCount = bench.initCount, + minSamples = bench.minSamples, + queue = [], + sample = bench.stats.sample; + + /** + * Adds a clone to the queue. + */ + function enqueue() { + queue.push(bench.clone({ + '_original': bench, + 'events': { + 'abort': [update], + 'cycle': [update], + 'error': [update], + 'start': [update] + } + })); + } + + /** + * Updates the clone/original benchmarks to keep their data in sync. + */ + function update(event) { + var clone = this, + type = event.type; + + if (bench.running) { + if (type == 'start') { + // Note: `clone.minTime` prop is inited in `clock()` + clone.count = bench.initCount; + } + else { + if (type == 'error') { + bench.error = clone.error; + } + if (type == 'abort') { + bench.abort(); + bench.emit('cycle'); + } else { + event.currentTarget = event.target = bench; + bench.emit(event); + } + } + } else if (bench.aborted) { + // clear abort listeners to avoid triggering bench's abort/cycle again + clone.events.abort.length = 0; + clone.abort(); + } + } + + /** + * Determines if more clones should be queued or if cycling should stop. + */ + function evaluate(event) { + var critical, + df, + mean, + moe, + rme, + sd, + sem, + variance, + clone = event.target, + done = bench.aborted, + now = +new Date, + size = sample.push(clone.times.period), + maxedOut = size >= minSamples && (elapsed += now - clone.times.timeStamp) / 1e3 > bench.maxTime, + times = bench.times, + varOf = function(sum, x) { return sum + pow(x - mean, 2); }; + + // exit early for aborted or unclockable tests + if (done || clone.hz == Infinity) { + maxedOut = !(size = sample.length = queue.length = 0); + } + + if (!done) { + // sample mean (estimate of the population mean) + mean = getMean(sample); + // sample variance (estimate of the population variance) + variance = reduce(sample, varOf, 0) / (size - 1) || 0; + // sample standard deviation (estimate of the population standard deviation) + sd = sqrt(variance); + // standard error of the mean (a.k.a. the standard deviation of the sampling distribution of the sample mean) + sem = sd / sqrt(size); + // degrees of freedom + df = size - 1; + // critical value + critical = tTable[Math.round(df) || 1] || tTable.infinity; + // margin of error + moe = sem * critical; + // relative margin of error + rme = (moe / mean) * 100 || 0; + + extend(bench.stats, { + 'deviation': sd, + 'mean': mean, + 'moe': moe, + 'rme': rme, + 'sem': sem, + 'variance': variance + }); + + // Abort the cycle loop when the minimum sample size has been collected + // and the elapsed time exceeds the maximum time allowed per benchmark. + // We don't count cycle delays toward the max time because delays may be + // increased by browsers that clamp timeouts for inactive tabs. + // https://developer.mozilla.org/en/window.setTimeout#Inactive_tabs + if (maxedOut) { + // reset the `initCount` in case the benchmark is rerun + bench.initCount = initCount; + bench.running = false; + done = true; + times.elapsed = (now - times.timeStamp) / 1e3; + } + if (bench.hz != Infinity) { + bench.hz = 1 / mean; + times.cycle = mean * bench.count; + times.period = mean; + } + } + // if time permits, increase sample size to reduce the margin of error + if (queue.length < 2 && !maxedOut) { + enqueue(); + } + // abort the invoke cycle when done + event.aborted = done; + } + + // init queue and begin + enqueue(); + invoke(queue, { + 'name': 'run', + 'args': { 'async': async }, + 'queued': true, + 'onCycle': evaluate, + 'onComplete': function() { bench.emit('complete'); } + }); + } + + /*--------------------------------------------------------------------------*/ + + /** + * Cycles a benchmark until a run `count` can be established. + * + * @private + * @param {Object} clone The cloned benchmark instance. + * @param {Object} options The options object. + */ + function cycle(clone, options) { + options || (options = {}); + + var deferred; + if (clone instanceof Deferred) { + deferred = clone; + clone = clone.benchmark; + } + + var clocked, + cycles, + divisor, + event, + minTime, + period, + async = options.async, + bench = clone._original, + count = clone.count, + times = clone.times; + + // continue, if not aborted between cycles + if (clone.running) { + // `minTime` is set to `Benchmark.options.minTime` in `clock()` + cycles = ++clone.cycles; + clocked = deferred ? deferred.elapsed : clock(clone); + minTime = clone.minTime; + + if (cycles > bench.cycles) { + bench.cycles = cycles; + } + if (clone.error) { + event = Event('error'); + event.message = clone.error; + clone.emit(event); + if (!event.cancelled) { + clone.abort(); + } + } + } + + // continue, if not errored + if (clone.running) { + // time taken to complete last test cycle + bench.times.cycle = times.cycle = clocked; + // seconds per operation + period = bench.times.period = times.period = clocked / count; + // ops per second + bench.hz = clone.hz = 1 / period; + // avoid working our way up to this next time + bench.initCount = clone.initCount = count; + // do we need to do another cycle? + clone.running = clocked < minTime; + + if (clone.running) { + // tests may clock at `0` when `initCount` is a small number, + // to avoid that we set its count to something a bit higher + if (!clocked && (divisor = divisors[clone.cycles]) != null) { + count = floor(4e6 / divisor); + } + // calculate how many more iterations it will take to achive the `minTime` + if (count <= clone.count) { + count += Math.ceil((minTime - clocked) / period); + } + clone.running = count != Infinity; + } + } + // should we exit early? + event = Event('cycle'); + clone.emit(event); + if (event.aborted) { + clone.abort(); + } + // figure out what to do next + if (clone.running) { + // start a new cycle + clone.count = count; + if (deferred) { + clone.compiled.call(deferred, timer); + } else if (async) { + delay(clone, function() { cycle(clone, options); }); + } else { + cycle(clone); + } + } + else { + // fix TraceMonkey bug associated with clock fallbacks + // http://bugzil.la/509069 + if (support.browser) { + runScript(uid + '=1;delete ' + uid); + } + // done + clone.emit('complete'); + } + } + + /*--------------------------------------------------------------------------*/ + + /** + * Runs the benchmark. + * + * @memberOf Benchmark + * @param {Object} [options={}] Options object. + * @returns {Object} The benchmark instance. + * @example + * + * // basic usage + * bench.run(); + * + * // or with options + * bench.run({ 'async': true }); + */ + function run(options) { + var me = this, + event = Event('start'); + + // set `running` to `false` so `reset()` won't call `abort()` + me.running = false; + me.reset(); + me.running = true; + + me.count = me.initCount; + me.times.timeStamp = +new Date; + me.emit(event); + + if (!event.cancelled) { + options = { 'async': ((options = options && options.async) == null ? me.async : options) && support.timeout }; + + // for clones created within `compute()` + if (me._original) { + if (me.defer) { + Deferred(me); + } else { + cycle(me, options); + } + } + // for original benchmarks + else { + compute(me, options); + } + } + return me; + } + + /*--------------------------------------------------------------------------*/ + + // Firefox 1 erroneously defines variable and argument names of functions on + // the function itself as non-configurable properties with `undefined` values. + // The bugginess continues as the `Benchmark` constructor has an argument + // named `options` and Firefox 1 will not assign a value to `Benchmark.options`, + // making it non-writable in the process, unless it is the first property + // assigned by for-in loop of `extend()`. + extend(Benchmark, { + + /** + * The default options copied by benchmark instances. + * + * @static + * @memberOf Benchmark + * @type Object + */ + 'options': { + + /** + * A flag to indicate that benchmark cycles will execute asynchronously + * by default. + * + * @memberOf Benchmark.options + * @type Boolean + */ + 'async': false, + + /** + * A flag to indicate that the benchmark clock is deferred. + * + * @memberOf Benchmark.options + * @type Boolean + */ + 'defer': false, + + /** + * The delay between test cycles (secs). + * @memberOf Benchmark.options + * @type Number + */ + 'delay': 0.005, + + /** + * Displayed by Benchmark#toString when a `name` is not available + * (auto-generated if absent). + * + * @memberOf Benchmark.options + * @type String + */ + 'id': undefined, + + /** + * The default number of times to execute a test on a benchmark's first cycle. + * + * @memberOf Benchmark.options + * @type Number + */ + 'initCount': 1, + + /** + * The maximum time a benchmark is allowed to run before finishing (secs). + * + * Note: Cycle delays aren't counted toward the maximum time. + * + * @memberOf Benchmark.options + * @type Number + */ + 'maxTime': 5, + + /** + * The minimum sample size required to perform statistical analysis. + * + * @memberOf Benchmark.options + * @type Number + */ + 'minSamples': 5, + + /** + * The time needed to reduce the percent uncertainty of measurement to 1% (secs). + * + * @memberOf Benchmark.options + * @type Number + */ + 'minTime': 0, + + /** + * The name of the benchmark. + * + * @memberOf Benchmark.options + * @type String + */ + 'name': undefined, + + /** + * An event listener called when the benchmark is aborted. + * + * @memberOf Benchmark.options + * @type Function + */ + 'onAbort': undefined, + + /** + * An event listener called when the benchmark completes running. + * + * @memberOf Benchmark.options + * @type Function + */ + 'onComplete': undefined, + + /** + * An event listener called after each run cycle. + * + * @memberOf Benchmark.options + * @type Function + */ + 'onCycle': undefined, + + /** + * An event listener called when a test errors. + * + * @memberOf Benchmark.options + * @type Function + */ + 'onError': undefined, + + /** + * An event listener called when the benchmark is reset. + * + * @memberOf Benchmark.options + * @type Function + */ + 'onReset': undefined, + + /** + * An event listener called when the benchmark starts running. + * + * @memberOf Benchmark.options + * @type Function + */ + 'onStart': undefined, + + /** + * The reference time taken to execute the test once (usecs). + * + * @memberOf Benchmark.options + * @type Number + */ + 'reference': 0 + }, + + /** + * Platform object with properties describing things like browser name, + * version, and operating system. + * + * @static + * @memberOf Benchmark + * @type Object + */ + 'platform': req('platform') || window.platform || { + + /** + * The platform description. + * + * @memberOf Benchmark.platform + * @type String + */ + 'description': window.navigator && navigator.userAgent || null, + + /** + * The name of the browser layout engine. + * + * @memberOf Benchmark.platform + * @type String|Null + */ + 'layout': null, + + /** + * The name of the product hosting the browser. + * + * @memberOf Benchmark.platform + * @type String|Null + */ + 'product': null, + + /** + * The name of the browser/environment. + * + * @memberOf Benchmark.platform + * @type String|Null + */ + 'name': null, + + /** + * The name of the product's manufacturer. + * + * @memberOf Benchmark.platform + * @type String|Null + */ + 'manufacturer': null, + + /** + * The name of the operating system. + * + * @memberOf Benchmark.platform + * @type String|Null + */ + 'os': null, + + /** + * The alpha/beta release indicator. + * + * @memberOf Benchmark.platform + * @type String|Null + */ + 'prerelease': null, + + /** + * The browser/environment version. + * + * @memberOf Benchmark.platform + * @type String|Null + */ + 'version': null, + + /** + * Return platform description when the platform object is coerced to a string. + * + * @memberOf Benchmark.platform + * @type Function + * @returns {String} The platform description. + */ + 'toString': function() { + return this.description || ''; + } + }, + + /** + * The semantic version number. + * + * @static + * @memberOf Benchmark + * @type String + */ + 'version': '1.0.0', + + // an object of environment/feature detection flags + 'support': support, + + // clone objects + 'deepClone': deepClone, + + // iteration utility + 'each': each, + + // augment objects + 'extend': extend, + + // generic Array#filter + 'filter': filter, + + // generic Array#forEach + 'forEach': forEach, + + // generic own property iteration utility + 'forOwn': forOwn, + + // converts a number to a comma-separated string + 'formatNumber': formatNumber, + + // generic Object#hasOwnProperty + // (trigger hasKey's lazy define before assigning it to Benchmark) + 'hasKey': (hasKey(Benchmark, ''), hasKey), + + // generic Array#indexOf + 'indexOf': indexOf, + + // template utility + 'interpolate': interpolate, + + // invokes a method on each item in an array + 'invoke': invoke, + + // generic Array#join for arrays and objects + 'join': join, + + // generic Array#map + 'map': map, + + // retrieves a property value from each item in an array + 'pluck': pluck, + + // generic Array#reduce + 'reduce': reduce + }); + + /*--------------------------------------------------------------------------*/ + + extend(Benchmark.prototype, { + + /** + * The number of times a test was executed. + * + * @memberOf Benchmark + * @type Number + */ + 'count': 0, + + /** + * The number of cycles performed while benchmarking. + * + * @memberOf Benchmark + * @type Number + */ + 'cycles': 0, + + /** + * The number of executions per second. + * + * @memberOf Benchmark + * @type Number + */ + 'hz': 0, + + /** + * The compiled test function. + * + * @memberOf Benchmark + * @type Function|String + */ + 'compiled': undefined, + + /** + * The error object if the test failed. + * + * @memberOf Benchmark + * @type Object + */ + 'error': undefined, + + /** + * The test to benchmark. + * + * @memberOf Benchmark + * @type Function|String + */ + 'fn': undefined, + + /** + * A flag to indicate if the benchmark is aborted. + * + * @memberOf Benchmark + * @type Boolean + */ + 'aborted': false, + + /** + * A flag to indicate if the benchmark is running. + * + * @memberOf Benchmark + * @type Boolean + */ + 'running': false, + + /** + * Compiled into the test and executed immediately **before** the test loop. + * + * @memberOf Benchmark + * @type Function|String + * @example + * + * // basic usage + * var bench = Benchmark({ + * 'setup': function() { + * var c = this.count, + * element = document.getElementById('container'); + * while (c--) { + * element.appendChild(document.createElement('div')); + * } + * }, + * 'fn': function() { + * element.removeChild(element.lastChild); + * } + * }); + * + * // compiles to something like: + * var c = this.count, + * element = document.getElementById('container'); + * while (c--) { + * element.appendChild(document.createElement('div')); + * } + * var start = new Date; + * while (count--) { + * element.removeChild(element.lastChild); + * } + * var end = new Date - start; + * + * // or using strings + * var bench = Benchmark({ + * 'setup': '\ + * var a = 0;\n\ + * (function() {\n\ + * (function() {\n\ + * (function() {', + * 'fn': 'a += 1;', + * 'teardown': '\ + * }())\n\ + * }())\n\ + * }())' + * }); + * + * // compiles to something like: + * var a = 0; + * (function() { + * (function() { + * (function() { + * var start = new Date; + * while (count--) { + * a += 1; + * } + * var end = new Date - start; + * }()) + * }()) + * }()) + */ + 'setup': noop, + + /** + * Compiled into the test and executed immediately **after** the test loop. + * + * @memberOf Benchmark + * @type Function|String + */ + 'teardown': noop, + + /** + * An object of stats including mean, margin or error, and standard deviation. + * + * @memberOf Benchmark + * @type Object + */ + 'stats': { + + /** + * The margin of error. + * + * @memberOf Benchmark#stats + * @type Number + */ + 'moe': 0, + + /** + * The relative margin of error (expressed as a percentage of the mean). + * + * @memberOf Benchmark#stats + * @type Number + */ + 'rme': 0, + + /** + * The standard error of the mean. + * + * @memberOf Benchmark#stats + * @type Number + */ + 'sem': 0, + + /** + * The sample standard deviation. + * + * @memberOf Benchmark#stats + * @type Number + */ + 'deviation': 0, + + /** + * The sample arithmetic mean. + * + * @memberOf Benchmark#stats + * @type Number + */ + 'mean': 0, + + /** + * The array of sampled periods. + * + * @memberOf Benchmark#stats + * @type Array + */ + 'sample': [], + + /** + * The sample variance. + * + * @memberOf Benchmark#stats + * @type Number + */ + 'variance': 0 + }, + + /** + * An object of timing data including cycle, elapsed, period, start, and stop. + * + * @memberOf Benchmark + * @type Object + */ + 'times': { + + /** + * The time taken to complete the last cycle (secs). + * + * @memberOf Benchmark#times + * @type Number + */ + 'cycle': 0, + + /** + * The time taken to complete the benchmark (secs). + * + * @memberOf Benchmark#times + * @type Number + */ + 'elapsed': 0, + + /** + * The time taken to execute the test once (secs). + * + * @memberOf Benchmark#times + * @type Number + */ + 'period': 0, + + /** + * A timestamp of when the benchmark started (ms). + * + * @memberOf Benchmark#times + * @type Number + */ + 'timeStamp': 0 + }, + + // aborts benchmark (does not record times) + 'abort': abort, + + // creates a new benchmark using the same test and options + 'clone': clone, + + // compares benchmark's hertz with another + 'compare': compare, + + // executes listeners + 'emit': emit, + + // get listeners + 'listeners': listeners, + + // unregister listeners + 'off': off, + + // register listeners + 'on': on, + + // reset benchmark properties + 'reset': reset, + + // runs the benchmark + 'run': run, + + // pretty print benchmark info + 'toString': toStringBench + }); + + /*--------------------------------------------------------------------------*/ + + extend(Deferred.prototype, { + + /** + * The deferred benchmark instance. + * + * @memberOf Benchmark.Deferred + * @type Object + */ + 'benchmark': null, + + /** + * The number of deferred cycles performed while benchmarking. + * + * @memberOf Benchmark.Deferred + * @type Number + */ + 'cycles': 0, + + /** + * The time taken to complete the deferred benchmark (secs). + * + * @memberOf Benchmark.Deferred + * @type Number + */ + 'elapsed': 0, + + /** + * A timestamp of when the deferred benchmark started (ms). + * + * @memberOf Benchmark.Deferred + * @type Number + */ + 'timeStamp': 0, + + // cycles/completes the deferred benchmark + 'resolve': resolve + }); + + /*--------------------------------------------------------------------------*/ + + extend(Event.prototype, { + + /** + * A flag to indicate if the emitters listener iteration is aborted. + * + * @memberOf Benchmark.Event + * @type Boolean + */ + 'aborted': false, + + /** + * A flag to indicate if the default action is cancelled. + * + * @memberOf Benchmark.Event + * @type Boolean + */ + 'cancelled': false, + + /** + * The object whose listeners are currently being processed. + * + * @memberOf Benchmark.Event + * @type Object + */ + 'currentTarget': undefined, + + /** + * The return value of the last executed listener. + * + * @memberOf Benchmark.Event + * @type Mixed + */ + 'result': undefined, + + /** + * The object to which the event was originally emitted. + * + * @memberOf Benchmark.Event + * @type Object + */ + 'target': undefined, + + /** + * A timestamp of when the event was created (ms). + * + * @memberOf Benchmark.Event + * @type Number + */ + 'timeStamp': 0, + + /** + * The event type. + * + * @memberOf Benchmark.Event + * @type String + */ + 'type': '' + }); + + /*--------------------------------------------------------------------------*/ + + /** + * The default options copied by suite instances. + * + * @static + * @memberOf Benchmark.Suite + * @type Object + */ + Suite.options = { + + /** + * The name of the suite. + * + * @memberOf Benchmark.Suite.options + * @type String + */ + 'name': undefined + }; + + /*--------------------------------------------------------------------------*/ + + extend(Suite.prototype, { + + /** + * The number of benchmarks in the suite. + * + * @memberOf Benchmark.Suite + * @type Number + */ + 'length': 0, + + /** + * A score computed using the normalized result of each benchmark in the suite. + * + * @memberOf Benchmark.Suite + * @type Number + */ + 'score': 0, + + /** + * A flag to indicate if the suite is aborted. + * + * @memberOf Benchmark.Suite + * @type Boolean + */ + 'aborted': false, + + /** + * A flag to indicate if the suite is running. + * + * @memberOf Benchmark.Suite + * @type Boolean + */ + 'running': false, + + /** + * An `Array#forEach` like method. + * Callbacks may terminate the loop by explicitly returning `false`. + * + * @memberOf Benchmark.Suite + * @param {Function} callback The function called per iteration. + * @returns {Object} The suite iterated over. + */ + 'forEach': methodize(forEach), + + /** + * An `Array#indexOf` like method. + * + * @memberOf Benchmark.Suite + * @param {Mixed} value The value to search for. + * @returns {Number} The index of the matched value or `-1`. + */ + 'indexOf': methodize(indexOf), + + /** + * Invokes a method on all benchmarks in the suite. + * + * @memberOf Benchmark.Suite + * @param {String|Object} name The name of the method to invoke OR options object. + * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with. + * @returns {Array} A new array of values returned from each method invoked. + */ + 'invoke': methodize(invoke), + + /** + * Converts the suite of benchmarks to a string. + * + * @memberOf Benchmark.Suite + * @param {String} [separator=','] A string to separate each element of the array. + * @returns {String} The string. + */ + 'join': [].join, + + /** + * An `Array#map` like method. + * + * @memberOf Benchmark.Suite + * @param {Function} callback The function called per iteration. + * @returns {Array} A new array of values returned by the callback. + */ + 'map': methodize(map), + + /** + * Retrieves the value of a specified property from all benchmarks in the suite. + * + * @memberOf Benchmark.Suite + * @param {String} property The property to pluck. + * @returns {Array} A new array of property values. + */ + 'pluck': methodize(pluck), + + /** + * Removes the last benchmark from the suite and returns it. + * + * @memberOf Benchmark.Suite + * @returns {Mixed} The removed benchmark. + */ + 'pop': [].pop, + + /** + * Appends benchmarks to the suite. + * + * @memberOf Benchmark.Suite + * @returns {Number} The suite's new length. + */ + 'push': [].push, + + /** + * Sorts the benchmarks of the suite. + * + * @memberOf Benchmark.Suite + * @param {Function} [compareFn=null] A function that defines the sort order. + * @returns {Object} The sorted suite. + */ + 'sort': [].sort, + + /** + * An `Array#reduce` like method. + * + * @memberOf Benchmark.Suite + * @param {Function} callback The function called per iteration. + * @param {Mixed} accumulator Initial value of the accumulator. + * @returns {Mixed} The accumulator. + */ + 'reduce': methodize(reduce), + + // aborts all benchmarks in the suite + 'abort': abortSuite, + + // adds a benchmark to the suite + 'add': add, + + // creates a new suite with cloned benchmarks + 'clone': cloneSuite, + + // executes listeners of a specified type + 'emit': emit, + + // creates a new suite of filtered benchmarks + 'filter': filterSuite, + + // get listeners + 'listeners': listeners, + + // unregister listeners + 'off': off, + + // register listeners + 'on': on, + + // resets all benchmarks in the suite + 'reset': resetSuite, + + // runs all benchmarks in the suite + 'run': runSuite, + + // array methods + 'concat': concat, + + 'reverse': reverse, + + 'shift': shift, + + 'slice': slice, + + 'splice': splice, + + 'unshift': unshift + }); + + /*--------------------------------------------------------------------------*/ + + // expose Deferred, Event and Suite + extend(Benchmark, { + 'Deferred': Deferred, + 'Event': Event, + 'Suite': Suite + }); + + // expose Benchmark + // some AMD build optimizers, like r.js, check for specific condition patterns like the following: + if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { + // define as an anonymous module so, through path mapping, it can be aliased + define(function() { + return Benchmark; + }); + } + // check for `exports` after `define` in case a build optimizer adds an `exports` object + else if (freeExports) { + // in Node.js or RingoJS v0.8.0+ + if (typeof module == 'object' && module && module.exports == freeExports) { + (module.exports = Benchmark).Benchmark = Benchmark; + } + // in Narwhal or RingoJS v0.7.0- + else { + freeExports.Benchmark = Benchmark; + } + } + // in a browser or Rhino + else { + // use square bracket notation so Closure Compiler won't munge `Benchmark` + // http://code.google.com/closure/compiler/docs/api-tutorial3.html#export + window['Benchmark'] = Benchmark; + } + + // trigger clock's lazy define early to avoid a security error + if (support.air) { + clock({ '_original': { 'fn': noop, 'count': 1, 'options': {} } }); + } +}(this)); diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/platform.js/LICENSE.txt b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/platform.js/LICENSE.txt new file mode 100644 index 0000000..a7501f9 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/platform.js/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright 2011-2013 John-David Dalton + +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. \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/platform.js/README.md b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/platform.js/README.md new file mode 100644 index 0000000..c2f1cb6 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/platform.js/README.md @@ -0,0 +1,98 @@ +# Platform.js v1.0.0 + +A platform detection library that works on nearly all JavaScript platforms1. + +## Disclaimer + +Platform.js is for informational purposes only and **not** intended as a substitution for [feature detection/inference](http://allyoucanleet.com/post/18087210413/feature-testing-costs#screencast2) checks. + +## BestieJS + +Platform.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. + +## Documentation + +The documentation for Platform.js can be viewed here: [/doc/README.md](https://github.com/bestiejs/platform.js/blob/master/doc/README.md#readme) + +For a list of upcoming features, check out our [roadmap](https://github.com/bestiejs/platform.js/wiki/Roadmap). + +## Support + +Platform.js has been tested in at least Adobe AIR 3.1, Chrome 5-21, Firefox 1-14, IE 6-9, Opera 9.25-12, Safari 3-6, Node.js 0.8.6, Narwhal 0.3.2, RingoJS 0.8, and Rhino 1.7RC5. + +## Installation and usage + +In a browser or Adobe AIR: + +```html + +``` + +Via [npm](http://npmjs.org/): + +```bash +npm install platform +``` + +In [Node.js](http://nodejs.org/) and [RingoJS](http://ringojs.org/): + +```js +var platform = require('platform'); +``` + +In [Rhino](http://www.mozilla.org/rhino/): + +```js +load('platform.js'); +``` + +In an AMD loader like [RequireJS](http://requirejs.org/): + +```js +require({ + 'paths': { + 'platform': 'path/to/platform' + } +}, +['platform'], function(platform) { + console.log(platform.name); +}); +``` + +Usage example: + +```js +// on IE10 x86 platform preview running in IE7 compatibility mode on Windows 7 64 bit edition +platform.name; // 'IE' +platform.version; // '10.0' +platform.layout; // 'Trident' +platform.os; // 'Windows Server 2008 R2 / 7 x64' +platform.description; // 'IE 10.0 x86 (platform preview; running in IE 7 mode) on Windows Server 2008 R2 / 7 x64' + +// or on an iPad +platform.name; // 'Safari' +platform.version; // '5.1' +platform.product; // 'iPad' +platform.manufacturer; // 'Apple' +platform.layout; // 'WebKit' +platform.os; // 'iOS 5.0' +platform.description; // 'Safari 5.1 on Apple iPad (iOS 5.0)' + +// or parsing a given UA string +var info = platform.parse('Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7.2; en; rv:2.0) Gecko/20100101 Firefox/4.0 Opera 11.52'); +info.name; // 'Opera' +info.version; // '11.52' +info.layout; // 'Presto' +info.os; // 'Mac OS X 10.7.2' +info.description; // 'Opera 11.52 (identifying as Firefox 4.0) on Mac OS X 10.7.2' +``` + +## Author + +* [John-David Dalton](http://allyoucanleet.com/) + [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](https://twitter.com/jdalton "Follow @jdalton on Twitter") + +## Contributors + +* [Mathias Bynens](http://mathiasbynens.be/) + [![twitter/mathias](http://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter") diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/platform.js/platform.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/platform.js/platform.js new file mode 100644 index 0000000..d643c18 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/platform.js/platform.js @@ -0,0 +1,996 @@ +/*! + * Platform.js v1.0.0 + * Copyright 2010-2013 John-David Dalton + * Available under MIT license + */ +;(function(window) { + 'use strict'; + + /** Backup possible window/global object */ + var oldWin = window; + + /** Detect free variable `exports` */ + var freeExports = typeof exports == 'object' && exports; + + /** Detect free variable `global` */ + var freeGlobal = typeof global == 'object' && global && + (global == global.global ? (window = global) : global); + + /** Opera regexp */ + var reOpera = /Opera/; + + /** Used to resolve a value's internal [[Class]] */ + var toString = {}.toString; + + /** Detect Java environment */ + var java = /Java/.test(getClassOf(window.java)) && window.java; + + /** A character to represent alpha */ + var alpha = java ? 'a' : '\u03b1'; + + /** A character to represent beta */ + var beta = java ? 'b' : '\u03b2'; + + /** Browser document object */ + var doc = window.document || {}; + + /** Used to check for own properties of an object */ + var hasOwnProperty = {}.hasOwnProperty; + + /** Browser navigator object */ + var nav = window.navigator || {}; + + /** + * Detect Opera browser + * http://www.howtocreate.co.uk/operaStuff/operaObject.html + * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini + */ + var opera = window.operamini || window.opera; + + /** Opera [[Class]] */ + var operaClass = reOpera.test(operaClass = getClassOf(opera)) ? operaClass : (opera = null); + + /** Possible global object */ + var thisBinding = this; + + /** Browser user agent string */ + var userAgent = nav.userAgent || ''; + + /*--------------------------------------------------------------------------*/ + + /** + * Capitalizes a string value. + * + * @private + * @param {String} string The string to capitalize. + * @returns {String} The capitalized string. + */ + function capitalize(string) { + string = String(string); + return string.charAt(0).toUpperCase() + string.slice(1); + } + + /** + * An iteration utility for arrays and objects. + * + * @private + * @param {Array|Object} object The object to iterate over. + * @param {Function} callback The function called per iteration. + */ + function each(object, callback) { + var index = -1, + length = object.length; + + if (length == length >>> 0) { + while (++index < length) { + callback(object[index], index, object); + } + } else { + forOwn(object, callback); + } + } + + /** + * Trim and conditionally capitalize string values. + * + * @private + * @param {String} string The string to format. + * @returns {String} The formatted string. + */ + function format(string) { + string = trim(string); + return /^(?:webOS|i(?:OS|P))/.test(string) + ? string + : capitalize(string); + } + + /** + * Iterates over an object's own properties, executing the `callback` for each. + * + * @private + * @param {Object} object The object to iterate over. + * @param {Function} callback The function executed per own property. + */ + function forOwn(object, callback) { + for (var key in object) { + hasKey(object, key) && callback(object[key], key, object); + } + } + + /** + * Gets the internal [[Class]] of a value. + * + * @private + * @param {Mixed} value The value. + * @returns {String} The [[Class]]. + */ + function getClassOf(value) { + return value == null + ? capitalize(value) + : toString.call(value).slice(8, -1); + } + + /** + * Checks if an object has the specified key as a direct property. + * + * @private + * @param {Object} object The object to check. + * @param {String} key The key to check for. + * @returns {Boolean} Returns `true` if key is a direct property, else `false`. + */ + function hasKey() { + // lazy define for others (not as accurate) + hasKey = function(object, key) { + var parent = object != null && (object.constructor || Object).prototype; + return !!parent && key in Object(object) && !(key in parent && object[key] === parent[key]); + }; + // for modern browsers + if (getClassOf(hasOwnProperty) == 'Function') { + hasKey = function(object, key) { + return object != null && hasOwnProperty.call(object, key); + }; + } + // for Safari 2 + else if ({}.__proto__ == Object.prototype) { + hasKey = function(object, key) { + var result = false; + if (object != null) { + object = Object(object); + object.__proto__ = [object.__proto__, object.__proto__ = null, result = key in object][0]; + } + return result; + }; + } + return hasKey.apply(this, arguments); + } + + /** + * Host objects can return type values that are different from their actual + * data type. The objects we are concerned with usually return non-primitive + * types of object, function, or unknown. + * + * @private + * @param {Mixed} object The owner of the property. + * @param {String} property The property to check. + * @returns {Boolean} Returns `true` if the property value is a non-primitive, else `false`. + */ + function isHostType(object, property) { + var type = object != null ? typeof object[property] : 'number'; + return !/^(?:boolean|number|string|undefined)$/.test(type) && + (type == 'object' ? !!object[property] : true); + } + + /** + * Prepares a string for use in a RegExp constructor by making hyphens and + * spaces optional. + * + * @private + * @param {String} string The string to qualify. + * @returns {String} The qualified string. + */ + function qualify(string) { + return String(string).replace(/([ -])(?!$)/g, '$1?'); + } + + /** + * A bare-bones` Array#reduce` like utility function. + * + * @private + * @param {Array} array The array to iterate over. + * @param {Function} callback The function called per iteration. + * @param {Mixed} accumulator Initial value of the accumulator. + * @returns {Mixed} The accumulator. + */ + function reduce(array, callback) { + var accumulator = null; + each(array, function(value, index) { + accumulator = callback(accumulator, value, index, array); + }); + return accumulator; + } + + /** + * Removes leading and trailing whitespace from a string. + * + * @private + * @param {String} string The string to trim. + * @returns {String} The trimmed string. + */ + function trim(string) { + return String(string).replace(/^ +| +$/g, ''); + } + + /*--------------------------------------------------------------------------*/ + + /** + * Creates a new platform object. + * + * @memberOf platform + * @param {String} [ua = navigator.userAgent] The user agent string. + * @returns {Object} A platform object. + */ + function parse(ua) { + + ua || (ua = userAgent); + + /** Temporary variable used over the script's lifetime */ + var data; + + /** The CPU architecture */ + var arch = ua; + + /** Platform description array */ + var description = []; + + /** Platform alpha/beta indicator */ + var prerelease = null; + + /** A flag to indicate that environment features should be used to resolve the platform */ + var useFeatures = ua == userAgent; + + /** The browser/environment version */ + var version = useFeatures && opera && typeof opera.version == 'function' && opera.version(); + + /* Detectable layout engines (order is important) */ + var layout = getLayout([ + { 'label': 'WebKit', 'pattern': 'AppleWebKit' }, + 'iCab', + 'Presto', + 'NetFront', + 'Tasman', + 'Trident', + 'KHTML', + 'Gecko' + ]); + + /* Detectable browser names (order is important) */ + var name = getName([ + 'Adobe AIR', + 'Arora', + 'Avant Browser', + 'Camino', + 'Epiphany', + 'Fennec', + 'Flock', + 'Galeon', + 'GreenBrowser', + 'iCab', + 'Iceweasel', + 'Iron', + 'K-Meleon', + 'Konqueror', + 'Lunascape', + 'Maxthon', + 'Midori', + 'Nook Browser', + 'PhantomJS', + 'Raven', + 'Rekonq', + 'RockMelt', + 'SeaMonkey', + { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, + 'Sleipnir', + 'SlimBrowser', + 'Sunrise', + 'Swiftfox', + 'WebPositive', + 'Opera Mini', + 'Opera', + 'Chrome', + { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' }, + { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' }, + { 'label': 'IE', 'pattern': 'MSIE' }, + 'Safari' + ]); + + /* Detectable products (order is important) */ + var product = getProduct([ + 'BlackBerry', + { 'label': 'Galaxy S', 'pattern': 'GT-I9000' }, + { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' }, + 'Google TV', + 'iPad', + 'iPod', + 'iPhone', + 'Kindle', + { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' }, + 'Nook', + 'PlayBook', + 'PlayStation Vita', + 'TouchPad', + 'Transformer', + 'Xoom' + ]); + + /* Detectable manufacturers */ + var manufacturer = getManufacturer({ + 'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 }, + 'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 }, + 'Asus': { 'Transformer': 1 }, + 'Barnes & Noble': { 'Nook': 1 }, + 'BlackBerry': { 'PlayBook': 1 }, + 'Google': { 'Google TV': 1 }, + 'HP': { 'TouchPad': 1 }, + 'LG': { }, + 'Motorola': { 'Xoom': 1 }, + 'Nokia': { }, + 'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1 }, + 'Sony': { 'PlayStation Vita': 1 } + }); + + /* Detectable OSes (order is important) */ + var os = getOS([ + 'Android', + 'CentOS', + 'Debian', + 'Fedora', + 'FreeBSD', + 'Gentoo', + 'Haiku', + 'Kubuntu', + 'Linux Mint', + 'Red Hat', + 'SuSE', + 'Ubuntu', + 'Xubuntu', + 'Cygwin', + 'Symbian OS', + 'hpwOS', + 'webOS ', + 'webOS', + 'Tablet OS', + 'Linux', + 'Mac OS X', + 'Macintosh', + 'Mac', + 'Windows 98;', + 'Windows ' + ]); + + /*------------------------------------------------------------------------*/ + + /** + * Picks the layout engine from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {String|Null} The detected layout engine. + */ + function getLayout(guesses) { + return reduce(guesses, function(result, guess) { + return result || RegExp('\\b' + ( + guess.pattern || qualify(guess) + ) + '\\b', 'i').exec(ua) && (guess.label || guess); + }); + } + + /** + * Picks the manufacturer from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {String|Null} The detected manufacturer. + */ + function getManufacturer(guesses) { + return reduce(guesses, function(result, value, key) { + // lookup the manufacturer by product or scan the UA for the manufacturer + return result || ( + value[product] || + value[0/*Opera 9.25 fix*/, /^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] || + RegExp('\\b' + (key.pattern || qualify(key)) + '(?:\\b|\\w*\\d)', 'i').exec(ua) + ) && (key.label || key); + }); + } + + /** + * Picks the browser name from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {String|Null} The detected browser name. + */ + function getName(guesses) { + return reduce(guesses, function(result, guess) { + return result || RegExp('\\b' + ( + guess.pattern || qualify(guess) + ) + '\\b', 'i').exec(ua) && (guess.label || guess); + }); + } + + /** + * Picks the OS name from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {String|Null} The detected OS name. + */ + function getOS(guesses) { + return reduce(guesses, function(result, guess) { + var pattern = guess.pattern || qualify(guess); + if (!result && (result = + RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua))) { + // platform tokens defined at + // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx + // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx + data = { + '6.2': '8', + '6.1': 'Server 2008 R2 / 7', + '6.0': 'Server 2008 / Vista', + '5.2': 'Server 2003 / XP 64-bit', + '5.1': 'XP', + '5.01': '2000 SP1', + '5.0': '2000', + '4.0': 'NT', + '4.90': 'ME' + }; + // detect Windows version from platform tokens + if (/^Win/i.test(result) && + (data = data[0/*Opera 9.25 fix*/, /[\d.]+$/.exec(result)])) { + result = 'Windows ' + data; + } + // correct character case and cleanup + result = format(String(result) + .replace(RegExp(pattern, 'i'), guess.label || guess) + .replace(/ ce$/i, ' CE') + .replace(/hpw/i, 'web') + .replace(/Macintosh/, 'Mac OS') + .replace(/_PowerPC/i, ' OS') + .replace(/(OS X) [^ \d]+/i, '$1') + .replace(/\/(\d)/, ' $1') + .replace(/_/g, '.') + .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '') + .replace(/x86\.64/gi, 'x86_64') + .split(' on ')[0]); + } + return result; + }); + } + + /** + * Picks the product name from an array of guesses. + * + * @private + * @param {Array} guesses An array of guesses. + * @returns {String|Null} The detected product name. + */ + function getProduct(guesses) { + return reduce(guesses, function(result, guess) { + var pattern = guess.pattern || qualify(guess); + if (!result && (result = + RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) || + RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua) + )) { + // split by forward slash and append product version if needed + if ((result = String(guess.label || result).split('/'))[1] && !/[\d.]+/.test(result[0])) { + result[0] += ' ' + result[1]; + } + // correct character case and cleanup + guess = guess.label || guess; + result = format(result[0] + .replace(RegExp(pattern, 'i'), guess) + .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ') + .replace(RegExp('(' + guess + ')(\\w)', 'i'), '$1 $2')); + } + return result; + }); + } + + /** + * Resolves the version using an array of UA patterns. + * + * @private + * @param {Array} patterns An array of UA patterns. + * @returns {String|Null} The detected version. + */ + function getVersion(patterns) { + return reduce(patterns, function(result, pattern) { + return result || (RegExp(pattern + + '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null; + }); + } + + /*------------------------------------------------------------------------*/ + + /** + * Returns `platform.description` when the platform object is coerced to a string. + * + * @name toString + * @memberOf platform + * @returns {String} Returns `platform.description` if available, else an empty string. + */ + function toStringPlatform() { + return this.description || ''; + } + + /*------------------------------------------------------------------------*/ + + // convert layout to an array so we can add extra details + layout && (layout = [layout]); + + // detect product names that contain their manufacturer's name + if (manufacturer && !product) { + product = getProduct([manufacturer]); + } + // clean up Google TV + if ((data = /Google TV/.exec(product))) { + product = data[0]; + } + // detect simulators + if (/\bSimulator\b/i.test(ua)) { + product = (product ? product + ' ' : '') + 'Simulator'; + } + // detect iOS + if (/^iP/.test(product)) { + name || (name = 'Safari'); + os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua)) + ? ' ' + data[1].replace(/_/g, '.') + : ''); + } + // detect Kubuntu + else if (name == 'Konqueror' && !/buntu/i.test(os)) { + os = 'Kubuntu'; + } + // detect Android browsers + else if (manufacturer && manufacturer != 'Google' && + /Chrome|Vita/.test(name + ';' + product)) { + name = 'Android Browser'; + os = /Android/.test(os) ? os : 'Android'; + } + // detect false positives for Firefox/Safari + else if (!name || (data = !/\bMinefield\b/i.test(ua) && /Firefox|Safari/.exec(name))) { + // escape the `/` for Firefox 1 + if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) { + // clear name of false positives + name = null; + } + // reassign a generic name + if ((data = product || manufacturer || os) && + (product || manufacturer || /Android|Symbian OS|Tablet OS|webOS/.test(os))) { + name = /[a-z]+(?: Hat)?/i.exec(/Android/.test(os) ? os : data) + ' Browser'; + } + } + // detect non-Opera versions (order is important) + if (!version) { + version = getVersion([ + '(?:Cloud9|CriOS|CrMo|Opera ?Mini|Raven|Silk(?!/[\\d.]+$))', + 'Version', + qualify(name), + '(?:Firefox|Minefield|NetFront)' + ]); + } + // detect stubborn layout engines + if (layout == 'iCab' && parseFloat(version) > 3) { + layout = ['WebKit']; + } else if (data = + /Opera/.test(name) && 'Presto' || + /\b(?:Midori|Nook|Safari)\b/i.test(ua) && 'WebKit' || + !layout && /\bMSIE\b/i.test(ua) && (/^Mac/.test(os) ? 'Tasman' : 'Trident')) { + layout = [data]; + } + // leverage environment features + if (useFeatures) { + // detect server-side environments + // Rhino has a global function while others have a global object + if (isHostType(window, 'global')) { + if (java) { + data = java.lang.System; + arch = data.getProperty('os.arch'); + os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version'); + } + if (typeof exports == 'object' && exports) { + // if `thisBinding` is the [ModuleScope] + if (thisBinding == oldWin && typeof system == 'object' && (data = [system])[0]) { + os || (os = data[0].os || null); + try { + data[1] = require('ringo/engine').version; + version = data[1].join('.'); + name = 'RingoJS'; + } catch(e) { + if (data[0].global == freeGlobal) { + name = 'Narwhal'; + } + } + } else if (typeof process == 'object' && (data = process)) { + name = 'Node.js'; + arch = data.arch; + os = data.platform; + version = /[\d.]+/.exec(data.version)[0]; + } + } else if (getClassOf(window.environment) == 'Environment') { + name = 'Rhino'; + } + } + // detect Adobe AIR + else if (getClassOf(data = window.runtime) == 'ScriptBridgingProxyObject') { + name = 'Adobe AIR'; + os = data.flash.system.Capabilities.os; + } + // detect PhantomJS + else if (getClassOf(data = window.phantom) == 'RuntimeObject') { + name = 'PhantomJS'; + version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch); + } + // detect IE compatibility modes + else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) { + // we're in compatibility mode when the Trident version + 4 doesn't + // equal the document mode + version = [version, doc.documentMode]; + if ((data = +data[1] + 4) != version[1]) { + description.push('IE ' + version[1] + ' mode'); + layout[1] = ''; + version[1] = data; + } + version = name == 'IE' ? String(version[1].toFixed(1)) : version[0]; + } + os = os && format(os); + } + // detect prerelease phases + if (version && (data = + /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) || + /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) || + /\bMinefield\b/i.test(ua) && 'a')) { + prerelease = /b/i.test(data) ? 'beta' : 'alpha'; + version = version.replace(RegExp(data + '\\+?$'), '') + + (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || ''); + } + // rename code name "Fennec" + if (name == 'Fennec') { + name = 'Firefox Mobile'; + } + // obscure Maxthon's unreliable version + else if (name == 'Maxthon' && version) { + version = version.replace(/\.[\d.]+/, '.x'); + } + // detect Silk desktop/accelerated modes + else if (name == 'Silk') { + if (!/Mobi/i.test(ua)) { + os = 'Android'; + description.unshift('desktop mode'); + } + if (/Accelerated *= *true/i.test(ua)) { + description.unshift('accelerated'); + } + } + // detect Windows Phone desktop mode + else if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) { + name += ' Mobile'; + os = 'Windows Phone OS ' + data + '.x'; + description.unshift('desktop mode'); + } + // add mobile postfix + else if ((name == 'IE' || name && !product && !/Browser|Mobi/.test(name)) && + (os == 'Windows CE' || /Mobi/i.test(ua))) { + name += ' Mobile'; + } + // detect IE platform preview + else if (name == 'IE' && useFeatures && typeof external == 'object' && !external) { + description.unshift('platform preview'); + } + // detect BlackBerry OS version + // http://docs.blackberry.com/en/developers/deliverables/18169/HTTP_headers_sent_by_BB_Browser_1234911_11.jsp + else if (/BlackBerry/.test(product) && (data = + (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] || + version)) { + os = 'Device Software ' + data; + version = null; + } + // detect Opera identifying/masking itself as another browser + // http://www.opera.com/support/kb/view/843/ + else if (this != forOwn && ( + (useFeatures && opera) || + (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) || + (name == 'Firefox' && /OS X (?:\d+\.){2,}/.test(os)) || + (name == 'IE' && ( + (os && !/^Win/.test(os) && version > 5.5) || + /Windows XP/.test(os) && version > 8 || + version == 8 && !/Trident/.test(ua) + )) + ) && !reOpera.test(data = parse.call(forOwn, ua.replace(reOpera, '') + ';')) && data.name) { + + // when "indentifying", the UA contains both Opera and the other browser's name + data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : ''); + if (reOpera.test(name)) { + if (/IE/.test(data) && os == 'Mac OS') { + os = null; + } + data = 'identify' + data; + } + // when "masking", the UA contains only the other browser's name + else { + data = 'mask' + data; + if (operaClass) { + name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2')); + } else { + name = 'Opera'; + } + if (/IE/.test(data)) { + os = null; + } + if (!useFeatures) { + version = null; + } + } + layout = ['Presto']; + description.push(data); + } + // detect WebKit Nightly and approximate Chrome/Safari versions + if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) { + // correct build for numeric comparison + // (e.g. "532.5" becomes "532.05") + data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data]; + // nightly builds are postfixed with a `+` + if (name == 'Safari' && data[1].slice(-1) == '+') { + name = 'WebKit Nightly'; + prerelease = 'alpha'; + version = data[1].slice(0, -1); + } + // clear incorrect browser versions + else if (version == data[1] || + version == (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1]) { + version = null; + } + // use the full Chrome version when available + data = [data[0], (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1]]; + + // detect JavaScriptCore + // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi + if (!useFeatures || (/internal|\n/i.test(toString.toString()) && !data[1])) { + layout[1] = 'like Safari'; + data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : '5'); + } else { + layout[1] = 'like Chrome'; + data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : '21'); + } + // add the postfix of ".x" or "+" for approximate versions + layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+'); + // obscure version for some Safari 1-2 releases + if (name == 'Safari' && (!version || parseInt(version) > 45)) { + version = data; + } + } + // detect Opera desktop modes + if (name == 'Opera' && (data = /(?:zbov|zvav)$/.exec(os))) { + name += ' '; + description.unshift('desktop mode'); + if (data == 'zvav') { + name += 'Mini'; + version = null; + } else { + name += 'Mobile'; + } + } + // detect Chrome desktop mode + else if (name == 'Safari' && /Chrome/.exec(layout[1])) { + description.unshift('desktop mode'); + name = 'Chrome Mobile'; + version = null; + + if (/Mac OS X/.test(os)) { + manufacturer = 'Apple'; + os = 'iOS 4.3+'; + } else { + os = null; + } + } + // strip incorrect OS versions + if (version && version.indexOf(data = /[\d.]+$/.exec(os)) == 0 && + ua.indexOf('/' + data + '-') > -1) { + os = trim(os.replace(data, '')); + } + // add layout engine + if (layout && !/Avant|Nook/.test(name) && ( + /Browser|Lunascape|Maxthon/.test(name) || + /^(?:Adobe|Arora|Midori|Phantom|Rekonq|Rock|Sleipnir|Web)/.test(name) && layout[1])) { + // don't add layout details to description if they are falsey + (data = layout[layout.length - 1]) && description.push(data); + } + // combine contextual information + if (description.length) { + description = ['(' + description.join('; ') + ')']; + } + // append manufacturer + if (manufacturer && product && product.indexOf(manufacturer) < 0) { + description.push('on ' + manufacturer); + } + // append product + if (product) { + description.push((/^on /.test(description[description.length -1]) ? '' : 'on ') + product); + } + // parse OS into an object + if (os) { + data = / ([\d.+]+)$/.exec(os); + os = { + 'architecture': 32, + 'family': data ? os.replace(data[0], '') : os, + 'version': data ? data[1] : null, + 'toString': function() { + var version = this.version; + return this.family + (version ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : ''); + } + }; + } + // add browser/OS architecture + if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) { + if (os) { + os.architecture = 64; + os.family = os.family.replace(RegExp(' *' + data), ''); + } + if (name && (/WOW64/i.test(ua) || + (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform)))) { + description.unshift('32-bit'); + } + } + + ua || (ua = null); + + /*------------------------------------------------------------------------*/ + + /** + * The platform object. + * + * @name platform + * @type Object + */ + return { + + /** + * The browser/environment version. + * + * @memberOf platform + * @type String|Null + */ + 'version': name && version && (description.unshift(version), version), + + /** + * The name of the browser/environment. + * + * @memberOf platform + * @type String|Null + */ + 'name': name && (description.unshift(name), name), + + /** + * The name of the operating system. + * + * @memberOf platform + * @type Object + */ + 'os': os + ? (name && + !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product)) && + description.push(product ? '(' + os + ')' : 'on ' + os), os) + : { + + /** + * The CPU architecture the OS is built for. + * + * @memberOf platform.os + * @type Number|Null + */ + 'architecture': null, + + /** + * The family of the OS. + * + * @memberOf platform.os + * @type String|Null + */ + 'family': null, + + /** + * The version of the OS. + * + * @memberOf platform.os + * @type String|Null + */ + 'version': null, + + /** + * Returns the OS string. + * + * @memberOf platform.os + * @returns {String} The OS string. + */ + 'toString': function() { return 'null'; } + }, + + /** + * The platform description. + * + * @memberOf platform + * @type String|Null + */ + 'description': description.length ? description.join(' ') : ua, + + /** + * The name of the browser layout engine. + * + * @memberOf platform + * @type String|Null + */ + 'layout': layout && layout[0], + + /** + * The name of the product's manufacturer. + * + * @memberOf platform + * @type String|Null + */ + 'manufacturer': manufacturer, + + /** + * The alpha/beta release indicator. + * + * @memberOf platform + * @type String|Null + */ + 'prerelease': prerelease, + + /** + * The name of the product hosting the browser. + * + * @memberOf platform + * @type String|Null + */ + 'product': product, + + /** + * The browser's user agent string. + * + * @memberOf platform + * @type String|Null + */ + 'ua': ua, + + // parses a user agent string into a platform object + 'parse': parse, + + // returns the platform description + 'toString': toStringPlatform + }; + } + + /*--------------------------------------------------------------------------*/ + + // expose platform + // some AMD build optimizers, like r.js, check for specific condition patterns like the following: + if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) { + // define as an anonymous module so, through path mapping, it can be aliased + define(function() { + return parse(); + }); + } + // check for `exports` after `define` in case a build optimizer adds an `exports` object + else if (freeExports) { + // in Narwhal, Node.js, or RingoJS + forOwn(parse(), function(value, key) { + freeExports[key] = value; + }); + } + // in a browser or Rhino + else { + // use square bracket notation so Closure Compiler won't munge `platform` + // http://code.google.com/closure/compiler/docs/api-tutorial3.html#export + window['platform'] = parse(); + } +}(this)); diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit-clib/LICENSE.txt b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit-clib/LICENSE.txt new file mode 100644 index 0000000..a7501f9 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit-clib/LICENSE.txt @@ -0,0 +1,20 @@ +Copyright 2011-2013 John-David Dalton + +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. \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit-clib/README.md b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit-clib/README.md new file mode 100644 index 0000000..7c2edfa --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit-clib/README.md @@ -0,0 +1,58 @@ +# QUnit CLIB v1.2.0 +## command-line interface boilerplate + +QUnit CLIB helps extend QUnit's CLI support to many common CLI environments. + +## Screenshot + +![QUnit CLIB brings QUnit to your favorite shell.](http://i.imgur.com/jpu9l.png) + +## Support + +QUnit CLIB has been tested in at least Node.js 0.4.8-0.8.19, Narwhal v0.3.2, PhantomJS 1.8.1, RingoJS v0.9, and Rhino v1.7RC5. + +## Usage + +```js +(function(window) { + + // use a single "load" function + var load = typeof require == 'function' ? require : window.load; + + // load QUnit and CLIB if needed + var QUnit = + window.QUnit || ( + window.addEventListener || (window.addEventListener = Function.prototype), + window.setTimeout || (window.setTimeout = Function.prototype), + window.QUnit = load('path/to/qunit.js') || window.QUnit, + load('path/to/qunit-clib.js'), + window.addEventListener === Function.prototype && delete window.addEventListener, + window.QUnit + ); + + // explicitly call `QUnit.module()` instead of `module()` + // in case we are in a CLI environment + QUnit.module('A Test Module'); + + test('A Test', function() { + // ... + }); + + // must call `QUnit.start()` if using QUnit < 1.3.0 with Node.js or any + // version of QUnit with Narwhal, PhantomJS, Rhino, or RingoJS + if (!window.document) { + QUnit.start(); + } +}(typeof global == 'object' && global || this)); +``` + +## Footnotes + + 1. QUnit v1.3.0 does not work with Narwhal or Ringo < v0.8.0 + + 2. Rhino v1.7RC4 does not support timeout fallbacks `clearTimeout` and `setTimeout` + +## Author + +* [John-David Dalton](http://allyoucanleet.com/) + [![twitter/jdalton](http://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](https://twitter.com/jdalton "Follow @jdalton on Twitter") diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit-clib/qunit-clib.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit-clib/qunit-clib.js new file mode 100644 index 0000000..7174feb --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit-clib/qunit-clib.js @@ -0,0 +1,269 @@ +/*! + * QUnit CLI Boilerplate v1.2.0 + * Copyright 2011-2012 John-David Dalton + * Based on a gist by Jörn Zaefferer + * Available under MIT license + */ +;(function(window) { + 'use strict'; + + /** + * Timeout fallbacks based on the work of Andrea Giammarchi and Weston C. + * https://github.com/WebReflection/wru/blob/master/src/rhinoTimers.js + * http://stackoverflow.com/questions/2261705/how-to-run-a-javascript-function-asynchronously-without-using-settimeout + */ + (function() { + + /** + * Schedules timer-based callbacks. + * + * @private + * @param {Function|String} fn The function to call. + * @oaram {Number} delay The number of milliseconds to delay the `fn` call. + * @param [arg1, arg2, ...] Arguments to invoke `fn` with. + * @param {Boolean} repeated A flag to specify whether `fn` is called repeatedly. + * @returns {Number} The the ID of the timeout. + */ + function schedule(fn, delay, args, repeated) { + // Rhino 1.7RC4 will error assigning `task` below + // https://bugzilla.mozilla.org/show_bug.cgi?id=775566 + var task = ids[++counter] = new JavaAdapter(java.util.TimerTask, { + 'run': function() { + fn.apply(window, args); + } + }); + // support non-functions + if (typeof fn != 'function') { + fn = (function(code) { + code = String(code); + return function() { eval(code); }; + }(fn)); + } + // used by setInterval + if (repeated) { + timer.schedule(task, delay, delay); + } + // used by setTimeout + else { + timer.schedule(task, delay); + } + return counter; + } + + /** + * Clears the delay set by `setInterval` or `setTimeout`. + * + * @memberOf window + * @param {Number} id The ID of the timeout to be cleared. + */ + function clearTimer(id) { + if (ids[id]) { + ids[id].cancel(); + timer.purge(); + delete ids[id]; + } + } + + /** + * Executes a code snippet or function repeatedly, with a delay between each call. + * + * @memberOf window + * @param {Function|String} fn The function to call or string to evaluate. + * @oaram {Number} delay The number of milliseconds to delay each `fn` call. + * @param [arg1, arg2, ...] Arguments to invoke `fn` with. + * @returns {Number} The the ID of the timeout. + */ + function setInterval(fn, delay) { + return schedule(fn, delay, slice.call(arguments, 2), true); + } + + /** + * Executes a code snippet or a function after specified delay. + * + * @memberOf window + * @param {Function|String} fn The function to call or string to evaluate. + * @oaram {Number} delay The number of milliseconds to delay the `fn` call. + * @param [arg1, arg2, ...] Arguments to invoke `fn` with. + * @returns {Number} The the ID of the timeout. + */ + function setTimeout(fn, delay) { + return schedule(fn, delay, slice.call(arguments, 2)); + } + + try { + var counter = 0, + ids = {}, + slice = Array.prototype.slice, + timer = new java.util.Timer; + + window.clearInterval = + window.clearTimeout = clearTimer; + window.setInterval = setInterval; + window.setTimeout = setTimeout; + } catch(e) { } + }()); + + /*--------------------------------------------------------------------------*/ + + (function() { + + /** Used as a horizontal rule in console output */ + var hr = '----------------------------------------'; + + /** Shorten `window.QUnit.QUnit` to `window.QUnit` */ + window.QUnit && (QUnit = QUnit.QUnit || QUnit); + + /** + * A logging callback triggered when all testing is completed. + * + * @memberOf QUnit + * @param {Object} details An object with properties `failed`, `passed`, `runtime`, and `total`. + */ + QUnit.done(function() { + var ran; + return function(details) { + // stop `asyncTest()` from erroneously calling `done()` twice in + // environments w/o timeouts + if (ran) { + return; + } + ran = true; + + console.log(hr); + console.log(' PASS: ' + details.passed + ' FAIL: ' + details.failed + ' TOTAL: ' + details.total); + console.log(' Finished in ' + details.runtime + ' milliseconds.'); + console.log(hr); + + // exit out of Rhino + try { + quit(); + } catch(e) { } + + // exit out of Node.js or PhantomJS + try { + var process = window.process || window.phantom; + if (details.failed) { + console.error('Error: ' + details.failed + ' of ' + details.total + ' tests failed.'); + process.exit(1); + } else { + process.exit(0); + } + } catch(e) { } + }; + }()); + + /** + * A logging callback triggered after every assertion. + * + * @memberOf QUnit + * @param {Object} details An object with properties `actual`, `expected`, `message`, and `result`. + */ + QUnit.log(function(details) { + var expected = details.expected, + result = details.result, + type = typeof expected != 'undefined' ? 'EQ' : 'OK'; + + var assertion = [ + result ? 'PASS' : 'FAIL', + type, + details.message || 'ok' + ]; + + if (!result && type == 'EQ') { + assertion.push('Expected: ' + expected + ', Actual: ' + details.actual); + } + QUnit.config.testStats.assertions.push(assertion.join(' | ')); + }); + + /** + * A logging callback triggered at the start of every test module. + * + * @memberOf QUnit + * @param {Object} details An object with property `name`. + */ + QUnit.moduleStart(function(details) { + console.log(hr); + console.log(details.name); + console.log(hr); + }); + + /** + * Converts an object into a string representation. + * + * @memberOf QUnit + * @type Function + * @param {Object} object The object to stringify. + * @returns {String} The result string. + */ + QUnit.jsDump.parsers.object = (function() { + var func = QUnit.jsDump.parsers.object; + return function(object) { + // fork to support Rhino's error objects + if (typeof object.rhinoException == 'object') { + return object.name + + ' { message: "' + object.message + + '", fileName: "' + object.fileName + + '", lineNumber: ' + object.lineNumber + ' }'; + } + return func(object); + }; + }()); + + /** + * A logging callback triggered after a test is completed. + * + * @memberOf QUnit + * @param {Object} details An object with properties `failed`, `name`, `passed`, and `total`. + */ + QUnit.testDone(function(details) { + var assertions = QUnit.config.testStats.assertions, + testName = details.name; + + if (details.failed > 0) { + console.log(' FAIL - '+ testName); + assertions.forEach(function(value) { + console.log(' ' + value); + }); + } + else { + console.log(' PASS - ' + testName); + } + assertions.length = 0; + }); + + /** + * An object used to hold information about the current running test. + * + * @memberOf QUnit.config + * @type Object + */ + QUnit.config.testStats = { + + /** + * An array of test summaries (pipe separated). + * + * @memberOf QUnit.config.testStats + * @type Array + */ + 'assertions': [] + }; + }()); + + /*--------------------------------------------------------------------------*/ + + // expose shortcuts + // exclude `module` because some environments have it as a built-in object + ('asyncTest deepEqual equal equals expect notDeepEqual notEqual notStrictEqual ' + + 'ok raises same start stop strictEqual test throws').replace(/\S+/g, function(methodName) { + window[methodName] = QUnit[methodName]; + }); + + // add `console.log()` support for Narwhal, Rhino, and RingoJS + if (!window.console && window.print) { + window.console = { 'log': window.print }; + } + // must call `QUnit.start()` in the test file if using QUnit < 1.3.0 with + // Node.js or any version of QUnit with Narwhal, PhantomJS, Rhino, or RingoJS + QUnit.init(); + +}(typeof global == 'object' && global || this)); diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit/README.md b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit/README.md new file mode 100644 index 0000000..6ab73f5 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit/README.md @@ -0,0 +1,62 @@ +[QUnit](http://qunitjs.com) - A JavaScript Unit Testing framework. +================================ + +QUnit is a powerful, easy-to-use, JavaScript test suite. It's used by the jQuery +project to test its code and plugins but is capable of testing any generic +JavaScript code (and even capable of testing JavaScript code on the server-side). + +QUnit is especially useful for regression testing: Whenever a bug is reported, +write a test that asserts the existence of that particular bug. Then fix it and +commit both. Every time you work on the code again, run the tests. If the bug +comes up again - a regression - you'll spot it immediately and know how to fix +it, because you know what code you just changed. + +Having good unit test coverage makes safe refactoring easy and cheap. You can +run the tests after each small refactoring step and always know what change +broke something. + +QUnit is similar to other unit testing frameworks like JUnit, but makes use of +the features JavaScript provides and helps with testing code in the browser, e.g. +with its stop/start facilities for testing asynchronous code. + +If you are interested in helping developing QUnit, you are in the right place. +For related discussions, visit the +[QUnit and Testing forum](http://forum.jquery.com/qunit-and-testing). + +Development +----------- + +To submit patches, fork the repository, create a branch for the change. Then implement +the change, run `grunt` to lint and test it, then commit, push and create a pull request. + +Include some background for the change in the commit message and `Fixes #nnn`, referring +to the issue number you're addressing. + +To run `grunt`, you need `node` and `npm`, then `npm install grunt -g`. That gives you a global +grunt binary. For additional grunt tasks, also run `npm install`. + +Releases +-------- + +Install git-extras and run `git changelog` to update History.md. +Update qunit/qunit.js|css and package.json to the release version, commit and +tag, update them again to the next version, commit and push commits and tags +(`git push --tags origin master`). + +Put the 'v' in front of the tag, e.g. `v1.8.0`. Clean up the changelog, removing merge commits +or whitespace cleanups. + +To upload to code.jquery.com (replace $version accordingly), ssh to code.origin.jquery.com: + + cp qunit/qunit.js /var/www/html/code.jquery.com/qunit/qunit-$version.js + cp qunit/qunit.css /var/www/html/code.jquery.com/qunit/qunit-$version.css + +Then update /var/www/html/code.jquery.com/index.html and purge it with: + + curl -s http://code.origin.jquery.com/?reload + +Update web-base-template to link to those files for qunitjs.com. + +Publish to npm via + + npm publish diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit/qunit/qunit.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit/qunit/qunit.js new file mode 100644 index 0000000..302545f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/qunit/qunit/qunit.js @@ -0,0 +1,2152 @@ +/** + * QUnit v1.11.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 + */ + +(function( window ) { + +var QUnit, + assert, + config, + onErrorFnPrev, + testId = 0, + fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""), + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + // Keep a local reference to Date (GH-283) + Date = window.Date, + defined = { + setTimeout: typeof window.setTimeout !== "undefined", + sessionStorage: (function() { + var x = "qunit-test-string"; + try { + sessionStorage.setItem( x, x ); + sessionStorage.removeItem( x ); + return true; + } catch( e ) { + return false; + } + }()) + }, + /** + * Provides a normalized error string, correcting an issue + * with IE 7 (and prior) where Error.prototype.toString is + * not properly implemented + * + * Based on http://es5.github.com/#x15.11.4.4 + * + * @param {String|Error} error + * @return {String} error message + */ + errorString = function( error ) { + var name, message, + errorString = error.toString(); + if ( errorString.substring( 0, 7 ) === "[object" ) { + name = error.name ? error.name.toString() : "Error"; + message = error.message ? error.message.toString() : ""; + if ( name && message ) { + return name + ": " + message; + } else if ( name ) { + return name; + } else if ( message ) { + return message; + } else { + return "Error"; + } + } else { + return errorString; + } + }, + /** + * Makes a clone of an object using only Array or Object as base, + * and copies over the own enumerable properties. + * + * @param {Object} obj + * @return {Object} New object with only the own properties (recursively). + */ + objectValues = function( obj ) { + // Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392. + /*jshint newcap: false */ + var key, val, + vals = QUnit.is( "array", obj ) ? [] : {}; + for ( key in obj ) { + if ( hasOwn.call( obj, key ) ) { + val = obj[key]; + vals[key] = val === Object(val) ? objectValues(val) : val; + } + } + return vals; + }; + +function Test( settings ) { + extend( this, settings ); + this.assertions = []; + this.testNumber = ++Test.count; +} + +Test.count = 0; + +Test.prototype = { + init: function() { + var a, b, li, + tests = id( "qunit-tests" ); + + if ( tests ) { + b = document.createElement( "strong" ); + b.innerHTML = this.nameHtml; + + // `a` initialized at top of scope + a = document.createElement( "a" ); + a.innerHTML = "Rerun"; + a.href = QUnit.url({ testNumber: this.testNumber }); + + li = document.createElement( "li" ); + li.appendChild( b ); + li.appendChild( a ); + li.className = "running"; + li.id = this.id = "qunit-test-output" + testId++; + + tests.appendChild( li ); + } + }, + setup: function() { + if ( this.module !== config.previousModule ) { + if ( config.previousModule ) { + runLoggingCallbacks( "moduleDone", QUnit, { + name: config.previousModule, + failed: config.moduleStats.bad, + passed: config.moduleStats.all - config.moduleStats.bad, + total: config.moduleStats.all + }); + } + config.previousModule = this.module; + config.moduleStats = { all: 0, bad: 0 }; + runLoggingCallbacks( "moduleStart", QUnit, { + name: this.module + }); + } else if ( config.autorun ) { + runLoggingCallbacks( "moduleStart", QUnit, { + name: this.module + }); + } + + config.current = this; + + this.testEnvironment = extend({ + setup: function() {}, + teardown: function() {} + }, this.moduleTestEnvironment ); + + this.started = +new Date(); + runLoggingCallbacks( "testStart", QUnit, { + name: this.testName, + module: this.module + }); + + // allow utility functions to access the current test environment + // TODO why?? + QUnit.current_testEnvironment = this.testEnvironment; + + if ( !config.pollution ) { + saveGlobal(); + } + if ( config.notrycatch ) { + this.testEnvironment.setup.call( this.testEnvironment ); + return; + } + try { + this.testEnvironment.setup.call( this.testEnvironment ); + } catch( e ) { + QUnit.pushFailure( "Setup failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) ); + } + }, + run: function() { + config.current = this; + + var running = id( "qunit-testresult" ); + + if ( running ) { + running.innerHTML = "Running:
    " + this.nameHtml; + } + + if ( this.async ) { + QUnit.stop(); + } + + this.callbackStarted = +new Date(); + + if ( config.notrycatch ) { + this.callback.call( this.testEnvironment, QUnit.assert ); + this.callbackRuntime = +new Date() - this.callbackStarted; + return; + } + + try { + this.callback.call( this.testEnvironment, QUnit.assert ); + this.callbackRuntime = +new Date() - this.callbackStarted; + } catch( e ) { + this.callbackRuntime = +new Date() - this.callbackStarted; + + QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) ); + // else next test will carry the responsibility + saveGlobal(); + + // Restart the tests if they're blocking + if ( config.blocking ) { + QUnit.start(); + } + } + }, + teardown: function() { + config.current = this; + if ( config.notrycatch ) { + if ( typeof this.callbackRuntime === "undefined" ) { + this.callbackRuntime = +new Date() - this.callbackStarted; + } + this.testEnvironment.teardown.call( this.testEnvironment ); + return; + } else { + try { + this.testEnvironment.teardown.call( this.testEnvironment ); + } catch( e ) { + QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) ); + } + } + checkPollution(); + }, + finish: function() { + config.current = this; + if ( config.requireExpects && this.expected === null ) { + QUnit.pushFailure( "Expected number of assertions to be defined, but expect() was not called.", this.stack ); + } else if ( this.expected !== null && this.expected !== this.assertions.length ) { + QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack ); + } else if ( this.expected === null && !this.assertions.length ) { + QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack ); + } + + var i, assertion, a, b, time, li, ol, + test = this, + good = 0, + bad = 0, + tests = id( "qunit-tests" ); + + this.runtime = +new Date() - this.started; + config.stats.all += this.assertions.length; + config.moduleStats.all += this.assertions.length; + + if ( tests ) { + ol = document.createElement( "ol" ); + ol.className = "qunit-assert-list"; + + for ( i = 0; i < this.assertions.length; i++ ) { + assertion = this.assertions[i]; + + li = document.createElement( "li" ); + li.className = assertion.result ? "pass" : "fail"; + li.innerHTML = assertion.message || ( assertion.result ? "okay" : "failed" ); + ol.appendChild( li ); + + if ( assertion.result ) { + good++; + } else { + bad++; + config.stats.bad++; + config.moduleStats.bad++; + } + } + + // store result when possible + if ( QUnit.config.reorder && defined.sessionStorage ) { + if ( bad ) { + sessionStorage.setItem( "qunit-test-" + this.module + "-" + this.testName, bad ); + } else { + sessionStorage.removeItem( "qunit-test-" + this.module + "-" + this.testName ); + } + } + + if ( bad === 0 ) { + addClass( ol, "qunit-collapsed" ); + } + + // `b` initialized at top of scope + b = document.createElement( "strong" ); + b.innerHTML = this.nameHtml + " (" + bad + ", " + good + ", " + this.assertions.length + ")"; + + addEvent(b, "click", function() { + var next = b.parentNode.lastChild, + collapsed = hasClass( next, "qunit-collapsed" ); + ( collapsed ? removeClass : addClass )( next, "qunit-collapsed" ); + }); + + addEvent(b, "dblclick", function( e ) { + var target = e && e.target ? e.target : window.event.srcElement; + if ( target.nodeName.toLowerCase() === "span" || target.nodeName.toLowerCase() === "b" ) { + target = target.parentNode; + } + if ( window.location && target.nodeName.toLowerCase() === "strong" ) { + window.location = QUnit.url({ testNumber: test.testNumber }); + } + }); + + // `time` initialized at top of scope + time = document.createElement( "span" ); + time.className = "runtime"; + time.innerHTML = this.runtime + " ms"; + + // `li` initialized at top of scope + li = id( this.id ); + li.className = bad ? "fail" : "pass"; + li.removeChild( li.firstChild ); + a = li.firstChild; + li.appendChild( b ); + li.appendChild( a ); + li.appendChild( time ); + li.appendChild( ol ); + + } else { + for ( i = 0; i < this.assertions.length; i++ ) { + if ( !this.assertions[i].result ) { + bad++; + config.stats.bad++; + config.moduleStats.bad++; + } + } + } + + runLoggingCallbacks( "testDone", QUnit, { + name: this.testName, + module: this.module, + failed: bad, + passed: this.assertions.length - bad, + total: this.assertions.length, + duration: this.runtime + }); + + QUnit.reset(); + + config.current = undefined; + }, + + queue: function() { + var bad, + test = this; + + synchronize(function() { + test.init(); + }); + function run() { + // each of these can by async + synchronize(function() { + test.setup(); + }); + synchronize(function() { + test.run(); + }); + synchronize(function() { + test.teardown(); + }); + synchronize(function() { + test.finish(); + }); + } + + // `bad` initialized at top of scope + // defer when previous test run passed, if storage is available + bad = QUnit.config.reorder && defined.sessionStorage && + +sessionStorage.getItem( "qunit-test-" + this.module + "-" + this.testName ); + + if ( bad ) { + run(); + } else { + synchronize( run, true ); + } + } +}; + +// Root QUnit object. +// `QUnit` initialized at top of scope +QUnit = { + + // call on start of module test to prepend name to all tests + module: function( name, testEnvironment ) { + config.currentModule = name; + config.currentModuleTestEnvironment = testEnvironment; + config.modules[name] = true; + }, + + asyncTest: function( testName, expected, callback ) { + if ( arguments.length === 2 ) { + callback = expected; + expected = null; + } + + QUnit.test( testName, expected, callback, true ); + }, + + test: function( testName, expected, callback, async ) { + var test, + nameHtml = "" + escapeText( testName ) + ""; + + if ( arguments.length === 2 ) { + callback = expected; + expected = null; + } + + if ( config.currentModule ) { + nameHtml = "" + escapeText( config.currentModule ) + ": " + nameHtml; + } + + test = new Test({ + nameHtml: nameHtml, + testName: testName, + expected: expected, + async: async, + callback: callback, + module: config.currentModule, + moduleTestEnvironment: config.currentModuleTestEnvironment, + stack: sourceFromStacktrace( 2 ) + }); + + if ( !validTest( test ) ) { + return; + } + + test.queue(); + }, + + // Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through. + expect: function( asserts ) { + if (arguments.length === 1) { + config.current.expected = asserts; + } else { + return config.current.expected; + } + }, + + start: function( count ) { + // QUnit hasn't been initialized yet. + // Note: RequireJS (et al) may delay onLoad + if ( config.semaphore === undefined ) { + QUnit.begin(function() { + // This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first + setTimeout(function() { + QUnit.start( count ); + }); + }); + return; + } + + config.semaphore -= count || 1; + // don't start until equal number of stop-calls + if ( config.semaphore > 0 ) { + return; + } + // ignore if start is called more often then stop + if ( config.semaphore < 0 ) { + config.semaphore = 0; + QUnit.pushFailure( "Called start() while already started (QUnit.config.semaphore was 0 already)", null, sourceFromStacktrace(2) ); + return; + } + // A slight delay, to avoid any current callbacks + if ( defined.setTimeout ) { + window.setTimeout(function() { + if ( config.semaphore > 0 ) { + return; + } + if ( config.timeout ) { + clearTimeout( config.timeout ); + } + + config.blocking = false; + process( true ); + }, 13); + } else { + config.blocking = false; + process( true ); + } + }, + + stop: function( count ) { + config.semaphore += count || 1; + config.blocking = true; + + if ( config.testTimeout && defined.setTimeout ) { + clearTimeout( config.timeout ); + config.timeout = window.setTimeout(function() { + QUnit.ok( false, "Test timed out" ); + config.semaphore = 1; + QUnit.start(); + }, config.testTimeout ); + } + } +}; + +// `assert` initialized at top of scope +// Asssert helpers +// All of these must either call QUnit.push() or manually do: +// - runLoggingCallbacks( "log", .. ); +// - config.current.assertions.push({ .. }); +// We attach it to the QUnit object *after* we expose the public API, +// otherwise `assert` will become a global variable in browsers (#341). +assert = { + /** + * Asserts rough true-ish result. + * @name ok + * @function + * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" ); + */ + ok: function( result, msg ) { + if ( !config.current ) { + throw new Error( "ok() assertion outside test context, was " + sourceFromStacktrace(2) ); + } + result = !!result; + + var source, + details = { + module: config.current.module, + name: config.current.testName, + result: result, + message: msg + }; + + msg = escapeText( msg || (result ? "okay" : "failed" ) ); + msg = "" + msg + ""; + + if ( !result ) { + source = sourceFromStacktrace( 2 ); + if ( source ) { + details.source = source; + msg += "
    Source:
    " + escapeText( source ) + "
    "; + } + } + runLoggingCallbacks( "log", QUnit, details ); + config.current.assertions.push({ + result: result, + message: msg + }); + }, + + /** + * Assert that the first two arguments are equal, with an optional message. + * Prints out both actual and expected values. + * @name equal + * @function + * @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" ); + */ + equal: function( actual, expected, message ) { + /*jshint eqeqeq:false */ + QUnit.push( expected == actual, actual, expected, message ); + }, + + /** + * @name notEqual + * @function + */ + notEqual: function( actual, expected, message ) { + /*jshint eqeqeq:false */ + QUnit.push( expected != actual, actual, expected, message ); + }, + + /** + * @name propEqual + * @function + */ + propEqual: function( actual, expected, message ) { + actual = objectValues(actual); + expected = objectValues(expected); + QUnit.push( QUnit.equiv(actual, expected), actual, expected, message ); + }, + + /** + * @name notPropEqual + * @function + */ + notPropEqual: function( actual, expected, message ) { + actual = objectValues(actual); + expected = objectValues(expected); + QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message ); + }, + + /** + * @name deepEqual + * @function + */ + deepEqual: function( actual, expected, message ) { + QUnit.push( QUnit.equiv(actual, expected), actual, expected, message ); + }, + + /** + * @name notDeepEqual + * @function + */ + notDeepEqual: function( actual, expected, message ) { + QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message ); + }, + + /** + * @name strictEqual + * @function + */ + strictEqual: function( actual, expected, message ) { + QUnit.push( expected === actual, actual, expected, message ); + }, + + /** + * @name notStrictEqual + * @function + */ + notStrictEqual: function( actual, expected, message ) { + QUnit.push( expected !== actual, actual, expected, message ); + }, + + "throws": function( block, expected, message ) { + var actual, + expectedOutput = expected, + ok = false; + + // 'expected' is optional + if ( typeof expected === "string" ) { + message = expected; + expected = null; + } + + config.current.ignoreGlobalErrors = true; + try { + block.call( config.current.testEnvironment ); + } catch (e) { + actual = e; + } + config.current.ignoreGlobalErrors = false; + + if ( actual ) { + // we don't want to validate thrown error + if ( !expected ) { + ok = true; + expectedOutput = null; + // expected is a regexp + } else if ( QUnit.objectType( expected ) === "regexp" ) { + ok = expected.test( errorString( actual ) ); + // expected is a constructor + } else if ( actual instanceof expected ) { + ok = true; + // expected is a validation function which returns true is validation passed + } else if ( expected.call( {}, actual ) === true ) { + expectedOutput = null; + ok = true; + } + + QUnit.push( ok, actual, expectedOutput, message ); + } else { + QUnit.pushFailure( message, null, 'No exception was thrown.' ); + } + } +}; + +/** + * @deprecate since 1.8.0 + * Kept assertion helpers in root for backwards compatibility. + */ +extend( QUnit, assert ); + +/** + * @deprecated since 1.9.0 + * Kept root "raises()" for backwards compatibility. + * (Note that we don't introduce assert.raises). + */ +QUnit.raises = assert[ "throws" ]; + +/** + * @deprecated since 1.0.0, replaced with error pushes since 1.3.0 + * Kept to avoid TypeErrors for undefined methods. + */ +QUnit.equals = function() { + QUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" ); +}; +QUnit.same = function() { + QUnit.push( false, false, false, "QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead" ); +}; + +// We want access to the constructor's prototype +(function() { + function F() {} + F.prototype = QUnit; + QUnit = new F(); + // Make F QUnit's constructor so that we can add to the prototype later + QUnit.constructor = F; +}()); + +/** + * Config object: Maintain internal state + * Later exposed as QUnit.config + * `config` initialized at top of scope + */ +config = { + // The queue of tests to run + queue: [], + + // block until document ready + blocking: true, + + // when enabled, show only failing tests + // gets persisted through sessionStorage and can be changed in UI via checkbox + hidepassed: false, + + // by default, run previously failed tests first + // very useful in combination with "Hide passed tests" checked + reorder: true, + + // by default, modify document.title when suite is done + altertitle: true, + + // when enabled, all tests must call expect() + requireExpects: false, + + // add checkboxes that are persisted in the query-string + // when enabled, the id is set to `true` as a `QUnit.config` property + urlConfig: [ + { + id: "noglobals", + label: "Check for Globals", + tooltip: "Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings." + }, + { + id: "notrycatch", + label: "No try-catch", + tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings." + } + ], + + // Set of all modules. + modules: {}, + + // logging callback queues + begin: [], + done: [], + log: [], + testStart: [], + testDone: [], + moduleStart: [], + moduleDone: [] +}; + +// Export global variables, unless an 'exports' object exists, +// in that case we assume we're in CommonJS (dealt with on the bottom of the script) +if ( typeof exports === "undefined" ) { + extend( window, QUnit ); + + // Expose QUnit object + window.QUnit = QUnit; +} + +// Initialize more QUnit.config and QUnit.urlParams +(function() { + var i, + location = window.location || { search: "", protocol: "file:" }, + params = location.search.slice( 1 ).split( "&" ), + length = params.length, + urlParams = {}, + current; + + if ( params[ 0 ] ) { + for ( i = 0; i < length; i++ ) { + current = params[ i ].split( "=" ); + current[ 0 ] = decodeURIComponent( current[ 0 ] ); + // allow just a key to turn on a flag, e.g., test.html?noglobals + current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true; + urlParams[ current[ 0 ] ] = current[ 1 ]; + } + } + + QUnit.urlParams = urlParams; + + // String search anywhere in moduleName+testName + config.filter = urlParams.filter; + + // Exact match of the module name + config.module = urlParams.module; + + config.testNumber = parseInt( urlParams.testNumber, 10 ) || null; + + // Figure out if we're running the tests from a server or not + QUnit.isLocal = location.protocol === "file:"; +}()); + +// Extend QUnit object, +// these after set here because they should not be exposed as global functions +extend( QUnit, { + assert: assert, + + config: config, + + // Initialize the configuration options + init: function() { + extend( config, { + stats: { all: 0, bad: 0 }, + moduleStats: { all: 0, bad: 0 }, + started: +new Date(), + updateRate: 1000, + blocking: false, + autostart: true, + autorun: false, + filter: "", + queue: [], + semaphore: 1 + }); + + var tests, banner, result, + qunit = id( "qunit" ); + + if ( qunit ) { + qunit.innerHTML = + "

    " + escapeText( document.title ) + "

    " + + "

    " + + "
    " + + "

    " + + "
      "; + } + + tests = id( "qunit-tests" ); + banner = id( "qunit-banner" ); + result = id( "qunit-testresult" ); + + if ( tests ) { + tests.innerHTML = ""; + } + + if ( banner ) { + banner.className = ""; + } + + if ( result ) { + result.parentNode.removeChild( result ); + } + + if ( tests ) { + result = document.createElement( "p" ); + result.id = "qunit-testresult"; + result.className = "result"; + tests.parentNode.insertBefore( result, tests ); + result.innerHTML = "Running...
       "; + } + }, + + // Resets the test setup. Useful for tests that modify the DOM. + reset: function() { + var fixture = id( "qunit-fixture" ); + if ( fixture ) { + fixture.innerHTML = config.fixture; + } + }, + + // Trigger an event on an element. + // @example triggerEvent( document.body, "click" ); + triggerEvent: function( elem, type, event ) { + if ( document.createEvent ) { + event = document.createEvent( "MouseEvents" ); + event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView, + 0, 0, 0, 0, 0, false, false, false, false, 0, null); + + elem.dispatchEvent( event ); + } else if ( elem.fireEvent ) { + elem.fireEvent( "on" + type ); + } + }, + + // Safe object type checking + is: function( type, obj ) { + return QUnit.objectType( obj ) === type; + }, + + objectType: function( obj ) { + if ( typeof obj === "undefined" ) { + return "undefined"; + // consider: typeof null === object + } + if ( obj === null ) { + return "null"; + } + + var match = toString.call( obj ).match(/^\[object\s(.*)\]$/), + type = match && match[1] || ""; + + switch ( type ) { + case "Number": + if ( isNaN(obj) ) { + return "nan"; + } + return "number"; + case "String": + case "Boolean": + case "Array": + case "Date": + case "RegExp": + case "Function": + return type.toLowerCase(); + } + if ( typeof obj === "object" ) { + return "object"; + } + return undefined; + }, + + push: function( result, actual, expected, message ) { + if ( !config.current ) { + throw new Error( "assertion outside test context, was " + sourceFromStacktrace() ); + } + + var output, source, + details = { + module: config.current.module, + name: config.current.testName, + result: result, + message: message, + actual: actual, + expected: expected + }; + + message = escapeText( message ) || ( result ? "okay" : "failed" ); + message = "" + message + ""; + output = message; + + if ( !result ) { + expected = escapeText( QUnit.jsDump.parse(expected) ); + actual = escapeText( QUnit.jsDump.parse(actual) ); + output += ""; + + if ( actual !== expected ) { + output += ""; + output += ""; + } + + source = sourceFromStacktrace(); + + if ( source ) { + details.source = source; + output += ""; + } + + output += "
      Expected:
      " + expected + "
      Result:
      " + actual + "
      Diff:
      " + QUnit.diff( expected, actual ) + "
      Source:
      " + escapeText( source ) + "
      "; + } + + runLoggingCallbacks( "log", QUnit, details ); + + config.current.assertions.push({ + result: !!result, + message: output + }); + }, + + pushFailure: function( message, source, actual ) { + if ( !config.current ) { + throw new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace(2) ); + } + + var output, + details = { + module: config.current.module, + name: config.current.testName, + result: false, + message: message + }; + + message = escapeText( message ) || "error"; + message = "" + message + ""; + output = message; + + output += ""; + + if ( actual ) { + output += ""; + } + + if ( source ) { + details.source = source; + output += ""; + } + + output += "
      Result:
      " + escapeText( actual ) + "
      Source:
      " + escapeText( source ) + "
      "; + + runLoggingCallbacks( "log", QUnit, details ); + + config.current.assertions.push({ + result: false, + message: output + }); + }, + + url: function( params ) { + params = extend( extend( {}, QUnit.urlParams ), params ); + var key, + querystring = "?"; + + for ( key in params ) { + if ( !hasOwn.call( params, key ) ) { + continue; + } + querystring += encodeURIComponent( key ) + "=" + + encodeURIComponent( params[ key ] ) + "&"; + } + return window.location.protocol + "//" + window.location.host + + window.location.pathname + querystring.slice( 0, -1 ); + }, + + extend: extend, + id: id, + addEvent: addEvent + // load, equiv, jsDump, diff: Attached later +}); + +/** + * @deprecated: Created for backwards compatibility with test runner that set the hook function + * into QUnit.{hook}, instead of invoking it and passing the hook function. + * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here. + * Doing this allows us to tell if the following methods have been overwritten on the actual + * QUnit object. + */ +extend( QUnit.constructor.prototype, { + + // Logging callbacks; all receive a single argument with the listed properties + // run test/logs.html for any related changes + begin: registerLoggingCallback( "begin" ), + + // done: { failed, passed, total, runtime } + done: registerLoggingCallback( "done" ), + + // log: { result, actual, expected, message } + log: registerLoggingCallback( "log" ), + + // testStart: { name } + testStart: registerLoggingCallback( "testStart" ), + + // testDone: { name, failed, passed, total, duration } + testDone: registerLoggingCallback( "testDone" ), + + // moduleStart: { name } + moduleStart: registerLoggingCallback( "moduleStart" ), + + // moduleDone: { name, failed, passed, total } + moduleDone: registerLoggingCallback( "moduleDone" ) +}); + +if ( typeof document === "undefined" || document.readyState === "complete" ) { + config.autorun = true; +} + +QUnit.load = function() { + runLoggingCallbacks( "begin", QUnit, {} ); + + // Initialize the config, saving the execution queue + var banner, filter, i, label, len, main, ol, toolbar, userAgent, val, + urlConfigCheckboxesContainer, urlConfigCheckboxes, moduleFilter, + numModules = 0, + moduleFilterHtml = "", + urlConfigHtml = "", + oldconfig = extend( {}, config ); + + QUnit.init(); + extend(config, oldconfig); + + config.blocking = false; + + len = config.urlConfig.length; + + for ( i = 0; i < len; i++ ) { + val = config.urlConfig[i]; + if ( typeof val === "string" ) { + val = { + id: val, + label: val, + tooltip: "[no tooltip available]" + }; + } + config[ val.id ] = QUnit.urlParams[ val.id ]; + urlConfigHtml += ""; + } + + moduleFilterHtml += ""; + + // `userAgent` initialized at top of scope + userAgent = id( "qunit-userAgent" ); + if ( userAgent ) { + userAgent.innerHTML = navigator.userAgent; + } + + // `banner` initialized at top of scope + banner = id( "qunit-header" ); + if ( banner ) { + banner.innerHTML = "" + banner.innerHTML + " "; + } + + // `toolbar` initialized at top of scope + toolbar = id( "qunit-testrunner-toolbar" ); + if ( toolbar ) { + // `filter` initialized at top of scope + filter = document.createElement( "input" ); + filter.type = "checkbox"; + filter.id = "qunit-filter-pass"; + + addEvent( filter, "click", function() { + var tmp, + ol = document.getElementById( "qunit-tests" ); + + if ( filter.checked ) { + ol.className = ol.className + " hidepass"; + } else { + tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " "; + ol.className = tmp.replace( / hidepass /, " " ); + } + if ( defined.sessionStorage ) { + if (filter.checked) { + sessionStorage.setItem( "qunit-filter-passed-tests", "true" ); + } else { + sessionStorage.removeItem( "qunit-filter-passed-tests" ); + } + } + }); + + if ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem( "qunit-filter-passed-tests" ) ) { + filter.checked = true; + // `ol` initialized at top of scope + ol = document.getElementById( "qunit-tests" ); + ol.className = ol.className + " hidepass"; + } + toolbar.appendChild( filter ); + + // `label` initialized at top of scope + label = document.createElement( "label" ); + label.setAttribute( "for", "qunit-filter-pass" ); + label.setAttribute( "title", "Only show tests and assertons that fail. Stored in sessionStorage." ); + label.innerHTML = "Hide passed tests"; + toolbar.appendChild( label ); + + urlConfigCheckboxesContainer = document.createElement("span"); + urlConfigCheckboxesContainer.innerHTML = urlConfigHtml; + urlConfigCheckboxes = urlConfigCheckboxesContainer.getElementsByTagName("input"); + // For oldIE support: + // * Add handlers to the individual elements instead of the container + // * Use "click" instead of "change" + // * Fallback from event.target to event.srcElement + addEvents( urlConfigCheckboxes, "click", function( event ) { + var params = {}, + target = event.target || event.srcElement; + params[ target.name ] = target.checked ? true : undefined; + window.location = QUnit.url( params ); + }); + toolbar.appendChild( urlConfigCheckboxesContainer ); + + if (numModules > 1) { + moduleFilter = document.createElement( 'span' ); + moduleFilter.setAttribute( 'id', 'qunit-modulefilter-container' ); + moduleFilter.innerHTML = moduleFilterHtml; + addEvent( moduleFilter.lastChild, "change", function() { + var selectBox = moduleFilter.getElementsByTagName("select")[0], + selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value); + + window.location = QUnit.url( { module: ( selectedModule === "" ) ? undefined : selectedModule } ); + }); + toolbar.appendChild(moduleFilter); + } + } + + // `main` initialized at top of scope + main = id( "qunit-fixture" ); + if ( main ) { + config.fixture = main.innerHTML; + } + + if ( config.autostart ) { + QUnit.start(); + } +}; + +addEvent( window, "load", QUnit.load ); + +// `onErrorFnPrev` initialized at top of scope +// Preserve other handlers +onErrorFnPrev = window.onerror; + +// Cover uncaught exceptions +// Returning true will surpress the default browser handler, +// returning false will let it run. +window.onerror = function ( error, filePath, linerNr ) { + var ret = false; + if ( onErrorFnPrev ) { + ret = onErrorFnPrev( error, filePath, linerNr ); + } + + // Treat return value as window.onerror itself does, + // Only do our handling if not surpressed. + if ( ret !== true ) { + if ( QUnit.config.current ) { + if ( QUnit.config.current.ignoreGlobalErrors ) { + return true; + } + QUnit.pushFailure( error, filePath + ":" + linerNr ); + } else { + QUnit.test( "global failure", extend( function() { + QUnit.pushFailure( error, filePath + ":" + linerNr ); + }, { validTest: validTest } ) ); + } + return false; + } + + return ret; +}; + +function done() { + config.autorun = true; + + // Log the last module results + if ( config.currentModule ) { + runLoggingCallbacks( "moduleDone", QUnit, { + name: config.currentModule, + failed: config.moduleStats.bad, + passed: config.moduleStats.all - config.moduleStats.bad, + total: config.moduleStats.all + }); + } + + var i, key, + banner = id( "qunit-banner" ), + tests = id( "qunit-tests" ), + runtime = +new Date() - config.started, + passed = config.stats.all - config.stats.bad, + html = [ + "Tests completed in ", + runtime, + " milliseconds.
      ", + "", + passed, + " assertions of ", + config.stats.all, + " passed, ", + config.stats.bad, + " failed." + ].join( "" ); + + if ( banner ) { + banner.className = ( config.stats.bad ? "qunit-fail" : "qunit-pass" ); + } + + if ( tests ) { + id( "qunit-testresult" ).innerHTML = html; + } + + if ( config.altertitle && typeof document !== "undefined" && document.title ) { + // show ✖ for good, ✔ for bad suite result in title + // use escape sequences in case file gets loaded with non-utf-8-charset + document.title = [ + ( config.stats.bad ? "\u2716" : "\u2714" ), + document.title.replace( /^[\u2714\u2716] /i, "" ) + ].join( " " ); + } + + // clear own sessionStorage items if all tests passed + if ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) { + // `key` & `i` initialized at top of scope + for ( i = 0; i < sessionStorage.length; i++ ) { + key = sessionStorage.key( i++ ); + if ( key.indexOf( "qunit-test-" ) === 0 ) { + sessionStorage.removeItem( key ); + } + } + } + + // scroll back to top to show results + if ( window.scrollTo ) { + window.scrollTo(0, 0); + } + + runLoggingCallbacks( "done", QUnit, { + failed: config.stats.bad, + passed: passed, + total: config.stats.all, + runtime: runtime + }); +} + +/** @return Boolean: true if this test should be ran */ +function validTest( test ) { + var include, + filter = config.filter && config.filter.toLowerCase(), + module = config.module && config.module.toLowerCase(), + fullName = (test.module + ": " + test.testName).toLowerCase(); + + // Internally-generated tests are always valid + if ( test.callback && test.callback.validTest === validTest ) { + delete test.callback.validTest; + return true; + } + + if ( config.testNumber ) { + return test.testNumber === config.testNumber; + } + + if ( module && ( !test.module || test.module.toLowerCase() !== module ) ) { + return false; + } + + if ( !filter ) { + return true; + } + + include = filter.charAt( 0 ) !== "!"; + if ( !include ) { + filter = filter.slice( 1 ); + } + + // If the filter matches, we need to honour include + if ( fullName.indexOf( filter ) !== -1 ) { + return include; + } + + // Otherwise, do the opposite + return !include; +} + +// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions) +// Later Safari and IE10 are supposed to support error.stack as well +// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack +function extractStacktrace( e, offset ) { + offset = offset === undefined ? 3 : offset; + + var stack, include, i; + + if ( e.stacktrace ) { + // Opera + return e.stacktrace.split( "\n" )[ offset + 3 ]; + } else if ( e.stack ) { + // Firefox, Chrome + stack = e.stack.split( "\n" ); + if (/^error$/i.test( stack[0] ) ) { + stack.shift(); + } + if ( fileName ) { + include = []; + for ( i = offset; i < stack.length; i++ ) { + if ( stack[ i ].indexOf( fileName ) !== -1 ) { + break; + } + include.push( stack[ i ] ); + } + if ( include.length ) { + return include.join( "\n" ); + } + } + return stack[ offset ]; + } else if ( e.sourceURL ) { + // Safari, PhantomJS + // hopefully one day Safari provides actual stacktraces + // exclude useless self-reference for generated Error objects + if ( /qunit.js$/.test( e.sourceURL ) ) { + return; + } + // for actual exceptions, this is useful + return e.sourceURL + ":" + e.line; + } +} +function sourceFromStacktrace( offset ) { + try { + throw new Error(); + } catch ( e ) { + return extractStacktrace( e, offset ); + } +} + +/** + * Escape text for attribute or text content. + */ +function escapeText( s ) { + if ( !s ) { + return ""; + } + s = s + ""; + // Both single quotes and double quotes (for attributes) + return s.replace( /['"<>&]/g, function( s ) { + switch( s ) { + case '\'': + return '''; + case '"': + return '"'; + case '<': + return '<'; + case '>': + return '>'; + case '&': + return '&'; + } + }); +} + +function synchronize( callback, last ) { + config.queue.push( callback ); + + if ( config.autorun && !config.blocking ) { + process( last ); + } +} + +function process( last ) { + function next() { + process( last ); + } + var start = new Date().getTime(); + config.depth = config.depth ? config.depth + 1 : 1; + + while ( config.queue.length && !config.blocking ) { + if ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) { + config.queue.shift()(); + } else { + window.setTimeout( next, 13 ); + break; + } + } + config.depth--; + if ( last && !config.blocking && !config.queue.length && config.depth === 0 ) { + done(); + } +} + +function saveGlobal() { + config.pollution = []; + + if ( config.noglobals ) { + for ( var key in window ) { + // in Opera sometimes DOM element ids show up here, ignore them + if ( !hasOwn.call( window, key ) || /^qunit-test-output/.test( key ) ) { + continue; + } + config.pollution.push( key ); + } + } +} + +function checkPollution() { + var newGlobals, + deletedGlobals, + old = config.pollution; + + saveGlobal(); + + newGlobals = diff( config.pollution, old ); + if ( newGlobals.length > 0 ) { + QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join(", ") ); + } + + deletedGlobals = diff( old, config.pollution ); + if ( deletedGlobals.length > 0 ) { + QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join(", ") ); + } +} + +// returns a new Array with the elements that are in a but not in b +function diff( a, b ) { + var i, j, + result = a.slice(); + + for ( i = 0; i < result.length; i++ ) { + for ( j = 0; j < b.length; j++ ) { + if ( result[i] === b[j] ) { + result.splice( i, 1 ); + i--; + break; + } + } + } + return result; +} + +function extend( a, b ) { + for ( var prop in b ) { + if ( b[ prop ] === undefined ) { + delete a[ prop ]; + + // Avoid "Member not found" error in IE8 caused by setting window.constructor + } else if ( prop !== "constructor" || a !== window ) { + a[ prop ] = b[ prop ]; + } + } + + return a; +} + +/** + * @param {HTMLElement} elem + * @param {string} type + * @param {Function} fn + */ +function addEvent( elem, type, fn ) { + // Standards-based browsers + if ( elem.addEventListener ) { + elem.addEventListener( type, fn, false ); + // IE + } else { + elem.attachEvent( "on" + type, fn ); + } +} + +/** + * @param {Array|NodeList} elems + * @param {string} type + * @param {Function} fn + */ +function addEvents( elems, type, fn ) { + var i = elems.length; + while ( i-- ) { + addEvent( elems[i], type, fn ); + } +} + +function hasClass( elem, name ) { + return (" " + elem.className + " ").indexOf(" " + name + " ") > -1; +} + +function addClass( elem, name ) { + if ( !hasClass( elem, name ) ) { + elem.className += (elem.className ? " " : "") + name; + } +} + +function removeClass( elem, name ) { + var set = " " + elem.className + " "; + // Class name may appear multiple times + while ( set.indexOf(" " + name + " ") > -1 ) { + set = set.replace(" " + name + " " , " "); + } + // If possible, trim it for prettiness, but not neccecarily + elem.className = window.jQuery ? jQuery.trim( set ) : ( set.trim ? set.trim() : set ); +} + +function id( name ) { + return !!( typeof document !== "undefined" && document && document.getElementById ) && + document.getElementById( name ); +} + +function registerLoggingCallback( key ) { + return function( callback ) { + config[key].push( callback ); + }; +} + +// Supports deprecated method of completely overwriting logging callbacks +function runLoggingCallbacks( key, scope, args ) { + var i, callbacks; + if ( QUnit.hasOwnProperty( key ) ) { + QUnit[ key ].call(scope, args ); + } else { + callbacks = config[ key ]; + for ( i = 0; i < callbacks.length; i++ ) { + callbacks[ i ].call( scope, args ); + } + } +} + +// Test for equality any JavaScript type. +// Author: Philippe Rathé +QUnit.equiv = (function() { + + // Call the o related callback with the given arguments. + function bindCallbacks( o, callbacks, args ) { + var prop = QUnit.objectType( o ); + if ( prop ) { + if ( QUnit.objectType( callbacks[ prop ] ) === "function" ) { + return callbacks[ prop ].apply( callbacks, args ); + } else { + return callbacks[ prop ]; // or undefined + } + } + } + + // the real equiv function + var innerEquiv, + // stack to decide between skip/abort functions + callers = [], + // stack to avoiding loops from circular referencing + parents = [], + + getProto = Object.getPrototypeOf || function ( obj ) { + return obj.__proto__; + }, + callbacks = (function () { + + // for string, boolean, number and null + function useStrictEquality( b, a ) { + /*jshint eqeqeq:false */ + if ( b instanceof a.constructor || a instanceof b.constructor ) { + // to catch short annotaion VS 'new' annotation of a + // declaration + // e.g. var i = 1; + // var j = new Number(1); + return a == b; + } else { + return a === b; + } + } + + return { + "string": useStrictEquality, + "boolean": useStrictEquality, + "number": useStrictEquality, + "null": useStrictEquality, + "undefined": useStrictEquality, + + "nan": function( b ) { + return isNaN( b ); + }, + + "date": function( b, a ) { + return QUnit.objectType( b ) === "date" && a.valueOf() === b.valueOf(); + }, + + "regexp": function( b, a ) { + return QUnit.objectType( b ) === "regexp" && + // the regex itself + a.source === b.source && + // and its modifers + a.global === b.global && + // (gmi) ... + a.ignoreCase === b.ignoreCase && + a.multiline === b.multiline && + a.sticky === b.sticky; + }, + + // - skip when the property is a method of an instance (OOP) + // - abort otherwise, + // initial === would have catch identical references anyway + "function": function() { + var caller = callers[callers.length - 1]; + return caller !== Object && typeof caller !== "undefined"; + }, + + "array": function( b, a ) { + var i, j, len, loop; + + // b could be an object literal here + if ( QUnit.objectType( b ) !== "array" ) { + return false; + } + + len = a.length; + if ( len !== b.length ) { + // safe and faster + return false; + } + + // track reference to avoid circular references + parents.push( a ); + for ( i = 0; i < len; i++ ) { + loop = false; + for ( j = 0; j < parents.length; j++ ) { + if ( parents[j] === a[i] ) { + loop = true;// dont rewalk array + } + } + if ( !loop && !innerEquiv(a[i], b[i]) ) { + parents.pop(); + return false; + } + } + parents.pop(); + return true; + }, + + "object": function( b, a ) { + var i, j, loop, + // Default to true + eq = true, + aProperties = [], + bProperties = []; + + // comparing constructors is more strict than using + // instanceof + if ( a.constructor !== b.constructor ) { + // Allow objects with no prototype to be equivalent to + // objects with Object as their constructor. + if ( !(( getProto(a) === null && getProto(b) === Object.prototype ) || + ( getProto(b) === null && getProto(a) === Object.prototype ) ) ) { + return false; + } + } + + // stack constructor before traversing properties + callers.push( a.constructor ); + // track reference to avoid circular references + parents.push( a ); + + for ( i in a ) { // be strict: don't ensures hasOwnProperty + // and go deep + loop = false; + for ( j = 0; j < parents.length; j++ ) { + if ( parents[j] === a[i] ) { + // don't go down the same path twice + loop = true; + } + } + aProperties.push(i); // collect a's properties + + if (!loop && !innerEquiv( a[i], b[i] ) ) { + eq = false; + break; + } + } + + callers.pop(); // unstack, we are done + parents.pop(); + + for ( i in b ) { + bProperties.push( i ); // collect b's properties + } + + // Ensures identical properties name + return eq && innerEquiv( aProperties.sort(), bProperties.sort() ); + } + }; + }()); + + innerEquiv = function() { // can take multiple arguments + var args = [].slice.apply( arguments ); + if ( args.length < 2 ) { + return true; // end transition + } + + return (function( a, b ) { + if ( a === b ) { + return true; // catch the most you can + } else if ( a === null || b === null || typeof a === "undefined" || + typeof b === "undefined" || + QUnit.objectType(a) !== QUnit.objectType(b) ) { + return false; // don't lose time with error prone cases + } else { + return bindCallbacks(a, callbacks, [ b, a ]); + } + + // apply transition with (1..n) arguments + }( args[0], args[1] ) && arguments.callee.apply( this, args.splice(1, args.length - 1 )) ); + }; + + return innerEquiv; +}()); + +/** + * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | + * http://flesler.blogspot.com Licensed under BSD + * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008 + * + * @projectDescription Advanced and extensible data dumping for Javascript. + * @version 1.0.0 + * @author Ariel Flesler + * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html} + */ +QUnit.jsDump = (function() { + function quote( str ) { + return '"' + str.toString().replace( /"/g, '\\"' ) + '"'; + } + function literal( o ) { + return o + ""; + } + function join( pre, arr, post ) { + var s = jsDump.separator(), + base = jsDump.indent(), + inner = jsDump.indent(1); + if ( arr.join ) { + arr = arr.join( "," + s + inner ); + } + if ( !arr ) { + return pre + post; + } + return [ pre, inner + arr, base + post ].join(s); + } + function array( arr, stack ) { + var i = arr.length, ret = new Array(i); + this.up(); + while ( i-- ) { + ret[i] = this.parse( arr[i] , undefined , stack); + } + this.down(); + return join( "[", ret, "]" ); + } + + var reName = /^function (\w+)/, + jsDump = { + // type is used mostly internally, you can fix a (custom)type in advance + parse: function( obj, type, stack ) { + stack = stack || [ ]; + var inStack, res, + parser = this.parsers[ type || this.typeOf(obj) ]; + + type = typeof parser; + inStack = inArray( obj, stack ); + + if ( inStack !== -1 ) { + return "recursion(" + (inStack - stack.length) + ")"; + } + if ( type === "function" ) { + stack.push( obj ); + res = parser.call( this, obj, stack ); + stack.pop(); + return res; + } + return ( type === "string" ) ? parser : this.parsers.error; + }, + typeOf: function( obj ) { + var type; + if ( obj === null ) { + type = "null"; + } else if ( typeof obj === "undefined" ) { + type = "undefined"; + } else if ( QUnit.is( "regexp", obj) ) { + type = "regexp"; + } else if ( QUnit.is( "date", obj) ) { + type = "date"; + } else if ( QUnit.is( "function", obj) ) { + type = "function"; + } else if ( typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined" ) { + type = "window"; + } else if ( obj.nodeType === 9 ) { + type = "document"; + } else if ( obj.nodeType ) { + type = "node"; + } else if ( + // native arrays + toString.call( obj ) === "[object Array]" || + // NodeList objects + ( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === "undefined" ) ) ) + ) { + type = "array"; + } else if ( obj.constructor === Error.prototype.constructor ) { + type = "error"; + } else { + type = typeof obj; + } + return type; + }, + separator: function() { + return this.multiline ? this.HTML ? "
      " : "\n" : this.HTML ? " " : " "; + }, + // extra can be a number, shortcut for increasing-calling-decreasing + indent: function( extra ) { + if ( !this.multiline ) { + return ""; + } + var chr = this.indentChar; + if ( this.HTML ) { + chr = chr.replace( /\t/g, " " ).replace( / /g, " " ); + } + return new Array( this._depth_ + (extra||0) ).join(chr); + }, + up: function( a ) { + this._depth_ += a || 1; + }, + down: function( a ) { + this._depth_ -= a || 1; + }, + setParser: function( name, parser ) { + this.parsers[name] = parser; + }, + // The next 3 are exposed so you can use them + quote: quote, + literal: literal, + join: join, + // + _depth_: 1, + // This is the list of parsers, to modify them, use jsDump.setParser + parsers: { + window: "[Window]", + document: "[Document]", + error: function(error) { + return "Error(\"" + error.message + "\")"; + }, + unknown: "[Unknown]", + "null": "null", + "undefined": "undefined", + "function": function( fn ) { + var ret = "function", + // functions never have name in IE + name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1]; + + if ( name ) { + ret += " " + name; + } + ret += "( "; + + ret = [ ret, QUnit.jsDump.parse( fn, "functionArgs" ), "){" ].join( "" ); + return join( ret, QUnit.jsDump.parse(fn,"functionCode" ), "}" ); + }, + array: array, + nodelist: array, + "arguments": array, + object: function( map, stack ) { + var ret = [ ], keys, key, val, i; + QUnit.jsDump.up(); + keys = []; + for ( key in map ) { + keys.push( key ); + } + keys.sort(); + for ( i = 0; i < keys.length; i++ ) { + key = keys[ i ]; + val = map[ key ]; + ret.push( QUnit.jsDump.parse( key, "key" ) + ": " + QUnit.jsDump.parse( val, undefined, stack ) ); + } + QUnit.jsDump.down(); + return join( "{", ret, "}" ); + }, + node: function( node ) { + var len, i, val, + open = QUnit.jsDump.HTML ? "<" : "<", + close = QUnit.jsDump.HTML ? ">" : ">", + tag = node.nodeName.toLowerCase(), + ret = open + tag, + attrs = node.attributes; + + if ( attrs ) { + for ( i = 0, len = attrs.length; i < len; i++ ) { + val = attrs[i].nodeValue; + // IE6 includes all attributes in .attributes, even ones not explicitly set. + // Those have values like undefined, null, 0, false, "" or "inherit". + if ( val && val !== "inherit" ) { + ret += " " + attrs[i].nodeName + "=" + QUnit.jsDump.parse( val, "attribute" ); + } + } + } + ret += close; + + // Show content of TextNode or CDATASection + if ( node.nodeType === 3 || node.nodeType === 4 ) { + ret += node.nodeValue; + } + + return ret + open + "/" + tag + close; + }, + // function calls it internally, it's the arguments part of the function + functionArgs: function( fn ) { + var args, + l = fn.length; + + if ( !l ) { + return ""; + } + + args = new Array(l); + while ( l-- ) { + // 97 is 'a' + args[l] = String.fromCharCode(97+l); + } + return " " + args.join( ", " ) + " "; + }, + // object calls it internally, the key part of an item in a map + key: quote, + // function calls it internally, it's the content of the function + functionCode: "[code]", + // node calls it internally, it's an html attribute value + attribute: quote, + string: quote, + date: quote, + regexp: literal, + number: literal, + "boolean": literal + }, + // if true, entities are escaped ( <, >, \t, space and \n ) + HTML: false, + // indentation unit + indentChar: " ", + // if true, items in a collection, are separated by a \n, else just a space. + multiline: true + }; + + return jsDump; +}()); + +// from jquery.js +function inArray( elem, array ) { + if ( array.indexOf ) { + return array.indexOf( elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; +} + +/* + * Javascript Diff Algorithm + * By John Resig (http://ejohn.org/) + * Modified by Chu Alan "sprite" + * + * Released under the MIT license. + * + * More Info: + * http://ejohn.org/projects/javascript-diff-algorithm/ + * + * Usage: QUnit.diff(expected, actual) + * + * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the quick brown fox jumped jumps over" + */ +QUnit.diff = (function() { + /*jshint eqeqeq:false, eqnull:true */ + function diff( o, n ) { + var i, + ns = {}, + os = {}; + + for ( i = 0; i < n.length; i++ ) { + if ( !hasOwn.call( ns, n[i] ) ) { + ns[ n[i] ] = { + rows: [], + o: null + }; + } + ns[ n[i] ].rows.push( i ); + } + + for ( i = 0; i < o.length; i++ ) { + if ( !hasOwn.call( os, o[i] ) ) { + os[ o[i] ] = { + rows: [], + n: null + }; + } + os[ o[i] ].rows.push( i ); + } + + for ( i in ns ) { + if ( !hasOwn.call( ns, i ) ) { + continue; + } + if ( ns[i].rows.length === 1 && hasOwn.call( os, i ) && os[i].rows.length === 1 ) { + n[ ns[i].rows[0] ] = { + text: n[ ns[i].rows[0] ], + row: os[i].rows[0] + }; + o[ os[i].rows[0] ] = { + text: o[ os[i].rows[0] ], + row: ns[i].rows[0] + }; + } + } + + for ( i = 0; i < n.length - 1; i++ ) { + if ( n[i].text != null && n[ i + 1 ].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null && + n[ i + 1 ] == o[ n[i].row + 1 ] ) { + + n[ i + 1 ] = { + text: n[ i + 1 ], + row: n[i].row + 1 + }; + o[ n[i].row + 1 ] = { + text: o[ n[i].row + 1 ], + row: i + 1 + }; + } + } + + for ( i = n.length - 1; i > 0; i-- ) { + if ( n[i].text != null && n[ i - 1 ].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null && + n[ i - 1 ] == o[ n[i].row - 1 ]) { + + n[ i - 1 ] = { + text: n[ i - 1 ], + row: n[i].row - 1 + }; + o[ n[i].row - 1 ] = { + text: o[ n[i].row - 1 ], + row: i - 1 + }; + } + } + + return { + o: o, + n: n + }; + } + + return function( o, n ) { + o = o.replace( /\s+$/, "" ); + n = n.replace( /\s+$/, "" ); + + var i, pre, + str = "", + out = diff( o === "" ? [] : o.split(/\s+/), n === "" ? [] : n.split(/\s+/) ), + oSpace = o.match(/\s+/g), + nSpace = n.match(/\s+/g); + + if ( oSpace == null ) { + oSpace = [ " " ]; + } + else { + oSpace.push( " " ); + } + + if ( nSpace == null ) { + nSpace = [ " " ]; + } + else { + nSpace.push( " " ); + } + + if ( out.n.length === 0 ) { + for ( i = 0; i < out.o.length; i++ ) { + str += "" + out.o[i] + oSpace[i] + ""; + } + } + else { + if ( out.n[0].text == null ) { + for ( n = 0; n < out.o.length && out.o[n].text == null; n++ ) { + str += "" + out.o[n] + oSpace[n] + ""; + } + } + + for ( i = 0; i < out.n.length; i++ ) { + if (out.n[i].text == null) { + str += "" + out.n[i] + nSpace[i] + ""; + } + else { + // `pre` initialized at top of scope + pre = ""; + + for ( n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) { + pre += "" + out.o[n] + oSpace[n] + ""; + } + str += " " + out.n[i].text + nSpace[i] + pre; + } + } + } + + return str; + }; +}()); + +// for CommonJS enviroments, export everything +if ( typeof exports !== "undefined" ) { + extend( exports, QUnit ); +} + +// get at whatever the global object is, like window in browsers +}( (function() {return this;}.call()) )); diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/README.md b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/README.md new file mode 100644 index 0000000..7cfe3bb --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/README.md @@ -0,0 +1,50 @@ +# node-tar + +Tar for Node.js. + +## Goals of this project + +1. Be able to parse and reasonably extract the contents of any tar file + created by any program that creates tar files, period. + + At least, this includes every version of: + + * bsdtar + * gnutar + * solaris posix tar + * Joerg Schilling's star ("Schilly tar") + +2. Create tar files that can be extracted by any of the following tar + programs: + + * bsdtar/libarchive version 2.6.2 + * gnutar 1.15 and above + * SunOS Posix tar + * Joerg Schilling's star ("Schilly tar") + +3. 100% test coverage. Speed is important. Correctness is slightly + more important. + +4. Create the kind of tar interface that Node users would want to use. + +5. Satisfy npm's needs for a portable tar implementation with a + JavaScript interface. + +6. No excuses. No complaining. No tolerance for failure. + +## But isn't there already a tar.js? + +Yes, there are a few. This one is going to be better, and it will be +fanatically maintained, because npm will depend on it. + +That's why I need to write it from scratch. Creating and extracting +tarballs is such a large part of what npm does, I simply can't have it +be a black box any longer. + +## Didn't you have something already? Where'd it go? + +It's in the "old" folder. It's not functional. Don't use it. + +It was a useful exploration to learn the issues involved, but like most +software of any reasonable complexity, node-tar won't be useful until +it's been written at least 3 times. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/buffer-entry.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/buffer-entry.js new file mode 100644 index 0000000..c7b5a6e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/buffer-entry.js @@ -0,0 +1,30 @@ +// just like the Entry class, but it buffers the contents +// +// XXX It would be good to set a maximum BufferEntry filesize, +// since it eats up memory. In normal operation, +// these are only for long filenames or link names, which are +// rarely very big. + +module.exports = BufferEntry + +var inherits = require("../vendor/inherits/inherits.js") + , Entry = require("./entry.js") + +function BufferEntry () { + Entry.apply(this, arguments) + this._buffer = new Buffer(this.props.size) + this._offset = 0 + this.body = "" + this.on("end", function () { + this.body = this._buffer.toString().slice(0, -1) + }) +} + +// collect the bytes as they come in. +BufferEntry.prototype.write = function (c) { + c.copy(this._buffer, this._offset) + this._offset += c.length + Entry.prototype.write.call(this, c) +} + +inherits(BufferEntry, Entry) diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/entry-writer.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/entry-writer.js new file mode 100644 index 0000000..9d6a9b7 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/entry-writer.js @@ -0,0 +1,169 @@ +module.exports = EntryWriter + +var tar = require("../tar.js") + , TarHeader = require("./header.js") + , Entry = require("./entry.js") + , inherits = require("../vendor/inherits/inherits.js") + , BlockStream = require("../vendor/block-stream/block-stream.js") + , ExtendedHeaderWriter + , Stream = require("stream").Stream + , EOF = {} + +inherits(EntryWriter, Stream) + +function EntryWriter (props) { + var me = this + + if (!(me instanceof EntryWriter)) { + return new EntryWriter(props) + } + + Stream.apply(this) + + me.writable = true + me.readable = true + + me._stream = new BlockStream(512) + + me._stream.on("data", function (c) { + me.emit("data", c) + }) + + me._stream.on("drain", function () { + me.emit("drain") + }) + + me._stream.on("end", function () { + me.emit("end") + me.emit("close") + }) + + me.props = props + if (props.type === "Directory") { + props.size = 0 + } + props.ustar = "ustar\0" + props.ustarver = "00" + me.path = props.path + + me._buffer = [] + me._didHeader = false + me._meta = false + + me.on("pipe", function () { + me._process() + }) +} + +EntryWriter.prototype.write = function (c) { + // console.error(".. ew write") + if (this._ended) return this.emit("error", new Error("write after end")) + this._buffer.push(c) + this._process() + this._needDrain = this._buffer.length > 0 + return !this._needDrain +} + +EntryWriter.prototype.end = function (c) { + // console.error(".. ew end") + if (c) this._buffer.push(c) + this._buffer.push(EOF) + this._ended = true + this._process() + this._needDrain = this._buffer.length > 0 +} + +EntryWriter.prototype.pause = function () { + // console.error(".. ew pause") + this._paused = true + this.emit("pause") +} + +EntryWriter.prototype.resume = function () { + // console.error(".. ew resume") + this._paused = false + this.emit("resume") + this._process() +} + +EntryWriter.prototype.add = function (entry) { + // console.error(".. ew add") + if (!this.parent) return this.emit("error", new Error("no parent")) + + // make sure that the _header and such is emitted, and clear out + // the _currentEntry link on the parent. + if (!this._ended) this.end() + + return this.parent.add(entry) +} + +EntryWriter.prototype._header = function () { + // console.error(".. ew header") + if (this._didHeader) return + this._didHeader = true + + var headerBlock = TarHeader.encode(this.props) + + if (this.props.needExtended && !this._meta) { + var me = this + + ExtendedHeaderWriter = ExtendedHeaderWriter || + require("./extended-header-writer.js") + + ExtendedHeaderWriter(this.props) + .on("data", function (c) { + me.emit("data", c) + }) + .on("error", function (er) { + me.emit("error", er) + }) + .end() + } + + // console.error(".. .. ew headerBlock emitting") + this.emit("data", headerBlock) + this.emit("header") +} + +EntryWriter.prototype._process = function () { + // console.error(".. .. ew process") + if (!this._didHeader && !this._meta) { + this._header() + } + + if (this._paused || this._processing) { + // console.error(".. .. .. paused=%j, processing=%j", this._paused, this._processing) + return + } + + this._processing = true + + var buf = this._buffer + for (var i = 0; i < buf.length; i ++) { + // console.error(".. .. .. i=%d", i) + + var c = buf[i] + + if (c === EOF) this._stream.end() + else this._stream.write(c) + + if (this._paused) { + // console.error(".. .. .. paused mid-emission") + this._processing = false + if (i < buf.length) { + this._needDrain = true + this._buffer = buf.slice(i + 1) + } + return + } + } + + // console.error(".. .. .. emitted") + this._buffer.length = 0 + this._processing = false + + // console.error(".. .. .. emitting drain") + this.emit("drain") +} + +EntryWriter.prototype.destroy = function () {} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/entry.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/entry.js new file mode 100644 index 0000000..9d5b8bc --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/entry.js @@ -0,0 +1,212 @@ +// A passthrough read/write stream that sets its properties +// based on a header, extendedHeader, and globalHeader +// +// Can be either a file system object of some sort, or +// a pax/ustar metadata entry. + +module.exports = Entry + +var TarHeader = require("./header.js") + , tar = require("../tar") + , assert = require("assert").ok + , Stream = require("stream").Stream + , inherits = require("../vendor/inherits/inherits.js") + , fstream = require("../vendor/fstream/fstream.js").Abstract + +function Entry (header, extended, global) { + Stream.call(this) + this.readable = true + this.writable = true + + this._needDrain = false + this._paused = false + this._reading = false + this._ending = false + this._ended = false + this._remaining = 0 + this._queue = [] + this._index = 0 + this._queueLen = 0 + + this._read = this._read.bind(this) + + this.props = {} + this._header = header + this._extended = extended || {} + + // globals can change throughout the course of + // a file parse operation. Freeze it at its current state. + this._global = {} + var me = this + Object.keys(global || {}).forEach(function (g) { + me._global[g] = global[g] + }) + + this._setProps() +} + +inherits(Entry, Stream, +{ write: function (c) { + if (this._ending) this.error("write() after end()", null, true) + if (this._remaining === 0) { + this.error("invalid bytes past eof") + } + + // often we'll get a bunch of \0 at the end of the last write, + // since chunks will always be 512 bytes when reading a tarball. + if (c.length > this._remaining) { + c = c.slice(0, this._remaining) + } + this._remaining -= c.length + + // put it on the stack. + var ql = this._queueLen + this._queue.push(c) + this._queueLen ++ + + this._read() + + // either paused, or buffered + if (this._paused || ql > 0) { + this._needDrain = true + return false + } + + return true + } + +, end: function (c) { + if (c) this.write(c) + this._ending = true + this._read() + } + +, pause: function () { + this._paused = true + this.emit("pause") + } + +, resume: function () { + // console.error(" Tar Entry resume", this.path) + this.emit("resume") + this._paused = false + this._read() + return this._queueLen - this._index > 1 + } + + // This is bound to the instance +, _read: function () { + // console.error(" Tar Entry _read", this.path) + + if (this._paused || this._reading || this._ended) return + + // set this flag so that event handlers don't inadvertently + // get multiple _read() calls running. + this._reading = true + + // have any data to emit? + if (this._index < this._queueLen) { + var chunk = this._queue[this._index ++] + this.emit("data", chunk) + } + + // check if we're drained + if (this._index >= this._queueLen) { + this._queue.length = this._queueLen = this._index = 0 + if (this._needDrain) { + this._needDrain = false + this.emit("drain") + } + if (this._ending) { + this._ended = true + this.emit("end") + } + } + + // if the queue gets too big, then pluck off whatever we can. + // this should be fairly rare. + var mql = this._maxQueueLen + if (this._queueLen > mql && this._index > 0) { + mql = Math.min(this._index, mql) + this._index -= mql + this._queueLen -= mql + this._queue = this._queue.slice(mql) + } + + this._reading = false + } + +, _setProps: function () { + // props = extended->global->header->{} + var header = this._header + , extended = this._extended + , global = this._global + , props = this.props + + // first get the values from the normal header. + var fields = tar.fields + for (var f = 0; fields[f] !== null; f ++) { + var field = fields[f] + , val = header[field] + if (typeof val !== "undefined") props[field] = val + } + + // next, the global header for this file. + // numeric values, etc, will have already been parsed. + ;[global, extended].forEach(function (p) { + Object.keys(p).forEach(function (f) { + if (typeof p[f] !== "undefined") props[f] = p[f] + }) + }) + + // no nulls allowed in path or linkpath + ;["path", "linkpath"].forEach(function (p) { + if (props.hasOwnProperty(p)) { + props[p] = props[p].split("\0")[0] + } + }) + + + // set date fields to be a proper date + ;["mtime", "ctime", "atime"].forEach(function (p) { + if (props.hasOwnProperty(p)) { + props[p] = new Date(props[p] * 1000) + } + }) + + // set the type so that we know what kind of file to create + var type + switch (tar.types[props.type]) { + case "OldFile": + case "ContiguousFile": + type = "File" + break + + case "GNUDumpDir": + type = "Directory" + break + + case undefined: + type = "Unknown" + break + + case "Link": + case "SymbolicLink": + case "CharacterDevice": + case "BlockDevice": + case "Directory": + case "FIFO": + default: + type = tar.types[props.type] + } + + this.type = type + this.path = props.path + this.size = props.size + + // size is special, since it signals when the file needs to end. + this._remaining = props.size + } +, warn: fstream.warn +, error: fstream.error +}) diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/extended-header-writer.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/extended-header-writer.js new file mode 100644 index 0000000..10a7d8f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/extended-header-writer.js @@ -0,0 +1,192 @@ + +module.exports = ExtendedHeaderWriter + +var inherits = require("../vendor/inherits/inherits.js") + , EntryWriter = require("./entry-writer.js") + +inherits(ExtendedHeaderWriter, EntryWriter) + +var tar = require("../tar.js") + , path = require("path") + , inherits = require("../vendor/inherits/inherits.js") + , TarHeader = require("./header.js") + +// props is the props of the thing we need to write an +// extended header for. +// Don't be shy with it. Just encode everything. +function ExtendedHeaderWriter (props) { + // console.error(">> ehw ctor") + var me = this + + if (!(me instanceof ExtendedHeaderWriter)) { + return new ExtendedHeaderWriter(props) + } + + me.fields = props + + var p = + { path : ("PaxHeader" + path.join("/", props.path || "")) + .replace(/\\/g, "/").substr(0, 100) + , mode : props.mode || 0666 + , uid : props.uid || 0 + , gid : props.gid || 0 + , size : 0 // will be set later + , mtime : props.mtime || Date.now() / 1000 + , type : "x" + , linkpath : "" + , ustar : "ustar\0" + , ustarver : "00" + , uname : props.uname || "" + , gname : props.gname || "" + , devmaj : props.devmaj || 0 + , devmin : props.devmin || 0 + } + + + EntryWriter.call(me, p) + // console.error(">> ehw props", me.props) + me.props = p + + me._meta = true +} + +ExtendedHeaderWriter.prototype.end = function () { + // console.error(">> ehw end") + var me = this + + if (me._ended) return + me._ended = true + + me._encodeFields() + + if (me.props.size === 0) { + // nothing to write! + me._ready = true + me._stream.end() + return + } + + me._stream.write(TarHeader.encode(me.props)) + me.body.forEach(function (l) { + me._stream.write(l) + }) + me._ready = true + + // console.error(">> ehw _process calling end()", me.props) + this._stream.end() +} + +ExtendedHeaderWriter.prototype._encodeFields = function () { + // console.error(">> ehw _encodeFields") + this.body = [] + if (this.fields.prefix) { + this.fields.path = this.fields.prefix + "/" + this.fields.path + this.fields.prefix = "" + } + encodeFields(this.fields, "", this.body, this.fields.noProprietary) + var me = this + this.body.forEach(function (l) { + me.props.size += l.length + }) +} + +function encodeFields (fields, prefix, body, nop) { + // console.error(">> >> ehw encodeFields") + // "%d %s=%s\n", , , + // The length is a decimal number, and includes itself and the \n + // Numeric values are decimal strings. + + Object.keys(fields).forEach(function (k) { + var val = fields[k] + , numeric = tar.numeric[k] + + if (prefix) k = prefix + "." + k + + // already including NODETAR.type, don't need File=true also + if (k === fields.type && val === true) return + + switch (k) { + // don't include anything that's always handled just fine + // in the normal header, or only meaningful in the context + // of nodetar + case "mode": + case "cksum": + case "ustar": + case "ustarver": + case "prefix": + case "basename": + case "dirname": + case "needExtended": + case "block": + case "filter": + return + + case "rdev": + if (val === 0) return + break + + case "nlink": + case "dev": // Truly a hero among men, Creator of Star! + case "ino": // Speak his name with reverent awe! It is: + k = "SCHILY." + k + break + + default: break + } + + if (val && typeof val === "object" && + !Buffer.isBuffer(val)) encodeFields(val, k, body, nop) + else if (val === null || val === undefined) return + else body.push.apply(body, encodeField(k, val, nop)) + }) + + return body +} + +function encodeField (k, v, nop) { + // lowercase keys must be valid, otherwise prefix with + // "NODETAR." + if (k.charAt(0) === k.charAt(0).toLowerCase()) { + var m = k.split(".")[0] + if (!tar.knownExtended[m]) k = "NODETAR." + k + } + + // no proprietary + if (nop && k.charAt(0) !== k.charAt(0).toLowerCase()) { + return [] + } + + if (typeof val === "number") val = val.toString(10) + + var s = new Buffer(" " + k + "=" + v + "\n") + , digits = Math.floor(Math.log(s.length) / Math.log(10)) + 1 + + // console.error("1 s=%j digits=%j s.length=%d", s.toString(), digits, s.length) + + // if adding that many digits will make it go over that length, + // then add one to it. For example, if the string is: + // " foo=bar\n" + // then that's 9 characters. With the "9", that bumps the length + // up to 10. However, this is invalid: + // "10 foo=bar\n" + // but, since that's actually 11 characters, since 10 adds another + // character to the length, and the length includes the number + // itself. In that case, just bump it up again. + if (s.length + digits >= Math.pow(10, digits)) digits += 1 + // console.error("2 s=%j digits=%j s.length=%d", s.toString(), digits, s.length) + + var len = digits + s.length + // console.error("3 s=%j digits=%j s.length=%d len=%d", s.toString(), digits, s.length, len) + var lenBuf = new Buffer("" + len) + if (lenBuf.length + s.length !== len) { + throw new Error("Bad length calculation\n"+ + "len="+len+"\n"+ + "lenBuf="+JSON.stringify(lenBuf.toString())+"\n"+ + "lenBuf.length="+lenBuf.length+"\n"+ + "digits="+digits+"\n"+ + "s="+JSON.stringify(s.toString())+"\n"+ + "s.length="+s.length) + } + + return [lenBuf, s] +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/extended-header.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/extended-header.js new file mode 100644 index 0000000..63b79ec --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/extended-header.js @@ -0,0 +1,139 @@ +// An Entry consisting of: +// +// "%d %s=%s\n", , , +// +// The length is a decimal number, and includes itself and the \n +// \0 does not terminate anything. Only the length terminates the string. +// Numeric values are decimal strings. + +module.exports = ExtendedHeader + +var Entry = require("./entry.js") + , inherits = require("../vendor/inherits/inherits.js") + , tar = require("../tar.js") + , numeric = tar.numeric + , keyTrans = { "SCHILY.dev": "dev" + , "SCHILY.ino": "ino" + , "SCHILY.nlink": "nlink" } + +function ExtendedHeader () { + Entry.apply(this, arguments) + this.on("data", this._parse) + this.fields = {} + this._position = 0 + this._fieldPos = 0 + this._state = SIZE + this._sizeBuf = [] + this._keyBuf = [] + this._valBuf = [] + this._size = -1 + this._key = "" +} + +inherits(ExtendedHeader, Entry, { _parse: parse }) + +var s = 0 + , states = ExtendedHeader.states = {} + , SIZE = states.SIZE = s++ + , KEY = states.KEY = s++ + , VAL = states.VAL = s++ + , ERR = states.ERR = s++ + +Object.keys(states).forEach(function (s) { + states[states[s]] = states[s] +}) + +states[s] = null + +// char code values for comparison +var _0 = "0".charCodeAt(0) + , _9 = "9".charCodeAt(0) + , point = ".".charCodeAt(0) + , a = "a".charCodeAt(0) + , Z = "Z".charCodeAt(0) + , a = "a".charCodeAt(0) + , z = "z".charCodeAt(0) + , space = " ".charCodeAt(0) + , eq = "=".charCodeAt(0) + , cr = "\n".charCodeAt(0) + +function parse (c) { + if (this._state === ERR) return + + for ( var i = 0, l = c.length + ; i < l + ; this._position++, this._fieldPos++, i++) { + // console.error("top of loop, size="+this._size) + + var b = c[i] + + if (this._size >= 0 && this._fieldPos > this._size) { + error(this, "field exceeds length="+this._size) + return + } + + switch (this._state) { + case ERR: return + + case SIZE: + // console.error("parsing size, b=%d, rest=%j", b, c.slice(i).toString()) + if (b === space) { + this._state = KEY + // this._fieldPos = this._sizeBuf.length + this._size = parseInt(new Buffer(this._sizeBuf).toString(), 10) + this._sizeBuf.length = 0 + continue + } + if (b < _0 || b > _9) { + error(this, "expected [" + _0 + ".." + _9 + "], got " + b) + return + } + this._sizeBuf.push(b) + continue + + case KEY: + // can be any char except =, not > size. + if (b === eq) { + this._state = VAL + this._key = new Buffer(this._keyBuf).toString() + if (keyTrans[this._key]) this._key = keyTrans[this._key] + this._keyBuf.length = 0 + continue + } + this._keyBuf.push(b) + continue + + case VAL: + // field must end with cr + if (this._fieldPos === this._size - 1) { + // console.error("finished with "+this._key) + if (b !== cr) { + error(this, "expected \\n at end of field") + return + } + var val = new Buffer(this._valBuf).toString() + if (numeric[this._key]) { + val = parseFloat(val) + } + this.fields[this._key] = val + + this._valBuf.length = 0 + this._state = SIZE + this._size = -1 + this._fieldPos = -1 + continue + } + this._valBuf.push(b) + continue + } + } +} + +function error (me, msg) { + msg = "invalid header: " + msg + + "\nposition=" + me._position + + "\nfield position=" + me._fieldPos + + me.error(msg) + me.state = ERR +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/extract.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/extract.js new file mode 100644 index 0000000..bffc033 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/extract.js @@ -0,0 +1,78 @@ +// give it a tarball and a path, and it'll dump the contents + +module.exports = Extract + +var tar = require("../tar.js") + , fstream = require("../vendor/fstream/fstream.js") + , inherits = require("../vendor/inherits/inherits.js") + , path = require("path") + +function Extract (opts) { + if (!(this instanceof Extract)) return new Extract(opts) + tar.Parse.apply(this) + + // have to dump into a directory + opts.type = "Directory" + opts.Directory = true + + if (typeof opts !== "object") { + opts = { path: opts } + } + + // better to drop in cwd? seems more standard. + opts.path = opts.path || path.resolve("node-tar-extract") + opts.type = "Directory" + opts.Directory = true + + // similar to --strip or --strip-components + opts.strip = +opts.strip + if (!opts.strip || opts.strip <= 0) opts.strip = 0 + + this._fst = fstream.Writer(opts) + + this.pause() + var me = this + + // Hardlinks in tarballs are relative to the root + // of the tarball. So, they need to be resolved against + // the target directory in order to be created properly. + me.on("entry", function (entry) { + // if there's a "strip" argument, then strip off that many + // path components. + if (opts.strip) { + var p = entry.path.split("/").slice(opts.strip).join("/") + entry.path = entry.props.path = p + if (entry.linkpath) { + var lp = entry.linkpath.split("/").slice(opts.strip).join("/") + entry.linkpath = entry.props.linkpath = lp + } + } + if (entry.type !== "Link") return + entry.linkpath = entry.props.linkpath = + path.join(opts.path, path.join("/", entry.props.linkpath)) + }) + + this._fst.on("ready", function () { + me.pipe(me._fst, { end: false }) + me.resume() + }) + + // this._fst.on("end", function () { + // console.error("\nEEEE Extract End", me._fst.path) + // }) + + this._fst.on("close", function () { + // console.error("\nEEEE Extract End", me._fst.path) + me.emit("end") + me.emit("close") + }) +} + +inherits(Extract, tar.Parse) + +Extract.prototype._streamEnd = function () { + var me = this + if (!me._ended) me.error("unexpected eof") + me._fst.end() + // my .end() is coming later. +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/global-header-writer.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/global-header-writer.js new file mode 100644 index 0000000..99ff257 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/global-header-writer.js @@ -0,0 +1,14 @@ +module.exports = GlobalHeaderWriter + +var ExtendedHeaderWriter = require("./extended-header-writer.js") + , inherits = require("../vendor/inherits/inherits.js") + +inherits(GlobalHeaderWriter, ExtendedHeaderWriter) + +function GlobalHeaderWriter (props) { + if (!(this instanceof GlobalHeaderWriter)) { + return new GlobalHeaderWriter(props) + } + ExtendedHeaderWriter.call(this, props) + this.props.type = "g" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/header.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/header.js new file mode 100644 index 0000000..05b237c --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/header.js @@ -0,0 +1,385 @@ +// parse a 512-byte header block to a data object, or vice-versa +// If the data won't fit nicely in a simple header, then generate +// the appropriate extended header file, and return that. + +module.exports = TarHeader + +var tar = require("../tar.js") + , fields = tar.fields + , fieldOffs = tar.fieldOffs + , fieldEnds = tar.fieldEnds + , fieldSize = tar.fieldSize + , numeric = tar.numeric + , assert = require("assert").ok + , space = " ".charCodeAt(0) + , slash = "/".charCodeAt(0) + , bslash = process.platform === "win32" ? "\\".charCodeAt(0) : null + +function TarHeader (block) { + if (!(this instanceof TarHeader)) return new TarHeader(block) + if (block) this.decode(block) +} + +TarHeader.prototype = + { decode : decode + , encode: encode + , calcSum: calcSum + , checkSum: checkSum + } + +TarHeader.parseNumeric = parseNumeric +TarHeader.encode = encode +TarHeader.decode = decode + +// note that this will only do the normal ustar header, not any kind +// of extended posix header file. If something doesn't fit comfortably, +// then it will set obj.needExtended = true, and set the block to +// the closest approximation. +function encode (obj) { + if (!obj && !(this instanceof TarHeader)) throw new Error( + "encode must be called on a TarHeader, or supplied an object") + + obj = obj || this + var block = obj.block = new Buffer(512) + + // if the object has a "prefix", then that's actually an extension of + // the path field. + if (obj.prefix) { + // console.error("%% header encoding, got a prefix", obj.prefix) + obj.path = obj.prefix + "/" + obj.path + // console.error("%% header encoding, prefixed path", obj.path) + obj.prefix = "" + } + + obj.needExtended = false + + if (obj.mode) { + if (typeof obj.mode === "string") obj.mode = parseInt(obj.mode, 8) + obj.mode = obj.mode & 0777 + } + + for (var f = 0; fields[f] !== null; f ++) { + var field = fields[f] + , off = fieldOffs[f] + , end = fieldEnds[f] + , ret + + switch (field) { + case "cksum": + // special, done below, after all the others + break + + case "prefix": + // special, this is an extension of the "path" field. + // console.error("%% header encoding, skip prefix later") + break + + case "type": + // convert from long name to a single char. + var type = obj.type || "0" + if (type.length > 1) { + type = tar.types[obj.type] + if (!type) type = "0" + } + writeText(block, off, end, type) + break + + case "path": + // uses the "prefix" field if > 100 bytes, but <= 255 + var pathLen = Buffer.byteLength(obj.path) + , pathFSize = fieldSize[fields.path] + , prefFSize = fieldSize[fields.prefix] + + // paths between 100 and 255 should use the prefix field. + // longer than 255 + if (pathLen > pathFSize && + pathLen <= pathFSize + prefFSize) { + // need to find a slash somewhere in the middle so that + // path and prefix both fit in their respective fields + var searchStart = pathLen - 1 - pathFSize + , searchEnd = prefFSize + , found = false + , pathBuf = new Buffer(obj.path) + + for ( var s = searchStart + ; (s <= searchEnd) + ; s ++ ) { + if (pathBuf[s] === slash || pathBuf[s] === bslash) { + found = s + break + } + } + + if (found !== false) { + prefix = pathBuf.slice(0, found).toString("utf8") + path = pathBuf.slice(found + 1).toString("utf8") + + ret = writeText(block, off, end, path) + off = fieldOffs[fields.prefix] + end = fieldEnds[fields.prefix] + // console.error("%% header writing prefix", off, end, prefix) + ret = writeText(block, off, end, prefix) || ret + break + } + } + + // paths less than 100 chars don't need a prefix + // and paths longer than 255 need an extended header and will fail + // on old implementations no matter what we do here. + // Null out the prefix, and fallthrough to default. + // console.error("%% header writing no prefix") + var poff = fieldOffs[fields.prefix] + , pend = fieldEnds[fields.prefix] + writeText(block, poff, pend, "") + // fallthrough + + // all other fields are numeric or text + default: + ret = numeric[field] + ? writeNumeric(block, off, end, obj[field]) + : writeText(block, off, end, obj[field] || "") + break + } + obj.needExtended = obj.needExtended || ret + } + + var off = fieldOffs[fields.cksum] + , end = fieldEnds[fields.cksum] + + writeNumeric(block, off, end, calcSum.call(this, block)) + + return block +} + +// if it's a negative number, or greater than will fit, +// then use write256. +var MAXNUM = { 12: 077777777777 + , 11: 07777777777 + , 8 : 07777777 + , 7 : 0777777 } +function writeNumeric (block, off, end, num) { + var writeLen = end - off + , maxNum = MAXNUM[writeLen] || 0 + + num = num || 0 + // console.error(" numeric", num) + + if (num instanceof Date || + Object.prototype.toString.call(num) === "[object Date]") { + num = num.getTime() / 1000 + } + + if (num > maxNum || num < 0) { + write256(block, off, end, num) + // need an extended header if negative or too big. + return true + } + + // god, tar is so annoying + // if the string is small enough, you should put a space + // between the octal string and the \0, but if it doesn't + // fit, then don't. + var numStr = Math.floor(num).toString(8) + if (num < MAXNUM[writeLen - 1]) numStr += " " + + // pad with "0" chars + if (numStr.length < writeLen) { + numStr = (new Array(writeLen - numStr.length).join("0")) + numStr + } + + if (numStr.length !== writeLen - 1) { + throw new Error("invalid length: " + JSON.stringify(numStr) + "\n" + + "expected: "+writeLen) + } + block.write(numStr, off, writeLen, "utf8") + block[end - 1] = 0 +} + +function write256 (block, off, end, num) { + var buf = block.slice(off, end) + var positive = num >= 0 + buf[0] = positive ? 0x80 : 0xFF + + // get the number as a base-256 tuple + if (!positive) num *= -1 + var tuple = [] + do { + var n = num % 256 + tuple.push(n) + num = (num - n) / 256 + } while (num) + + var bytes = tuple.length + + var fill = buf.length - bytes + for (var i = 1; i < fill; i ++) { + buf[i] = positive ? 0 : 0xFF + } + + // tuple is a base256 number, with [0] as the *least* significant byte + // if it's negative, then we need to flip all the bits once we hit the + // first non-zero bit. The 2's-complement is (0x100 - n), and the 1's- + // complement is (0xFF - n). + var zero = true + for (i = bytes; i > 0; i --) { + var byte = tuple[bytes - i] + if (positive) buf[fill + i] = byte + else if (zero && byte === 0) buf[fill + i] = 0 + else if (zero) { + zero = false + buf[fill + i] = 0x100 - byte + } else buf[fill + i] = 0xFF - byte + } +} + +function writeText (block, off, end, str) { + // strings are written as utf8, then padded with \0 + var strLen = Buffer.byteLength(str) + , writeLen = Math.min(strLen, end - off) + // non-ascii fields need extended headers + // long fields get truncated + , needExtended = strLen !== str.length || strLen > writeLen + + // write the string, and null-pad + if (writeLen > 0) block.write(str, off, writeLen, "utf8") + for (var i = off + writeLen; i < end; i ++) block[i] = 0 + + return needExtended +} + +function calcSum (block) { + block = block || this.block + assert(Buffer.isBuffer(block) && block.length === 512) + + if (!block) throw new Error("Need block to checksum") + + // now figure out what it would be if the cksum was " " + var sum = 0 + , start = fieldOffs[fields.cksum] + , end = fieldEnds[fields.cksum] + + for (var i = 0; i < fieldOffs[fields.cksum]; i ++) { + sum += block[i] + } + + for (var i = start; i < end; i ++) { + sum += space + } + + for (var i = end; i < 512; i ++) { + sum += block[i] + } + + return sum +} + + +function checkSum (block) { + var sum = calcSum.call(this, block) + block = block || this.block + + var cksum = block.slice(fieldOffs[fields.cksum], fieldEnds[fields.cksum]) + cksum = parseNumeric(cksum) + + return cksum === sum +} + +function decode (block) { + block = block || this.block + assert(Buffer.isBuffer(block) && block.length === 512) + + this.block = block + this.cksumValid = this.checkSum() + + var prefix = null + + // slice off each field. + for (var f = 0; fields[f] !== null; f ++) { + var field = fields[f] + , val = block.slice(fieldOffs[f], fieldEnds[f]) + + switch (field) { + case "ustar": + // if not ustar, then everything after that is just padding. + if (val.toString() !== "ustar\0") { + this.ustar = false + return + } else { + // console.error("ustar:", val, val.toString()) + this.ustar = val.toString() + } + break + + // prefix is special, since it might signal the xstar header + case "prefix": + var atime = parseNumeric(val.slice(131, 131 + 12)) + , ctime = parseNumeric(val.slice(131 + 12, 131 + 12 + 12)) + if ((val[130] === 0 || val[130] === space) && + typeof atime === "number" && + typeof ctime === "number" && + val[131 + 12] === space && + val[131 + 12 + 12] === space) { + this.atime = atime + this.ctime = ctime + val = val.slice(0, 130) + } + prefix = val.toString("utf8").replace(/\0+$/, "") + // console.error("%% header reading prefix", prefix) + break + + // all other fields are null-padding text + // or a number. + default: + if (numeric[field]) { + this[field] = parseNumeric(val) + } else { + this[field] = val.toString("utf8").replace(/\0+$/, "") + } + break + } + } + + // if we got a prefix, then prepend it to the path. + if (prefix) { + this.path = prefix + "/" + this.path + // console.error("%% header got a prefix", this.path) + } +} + +function parse256 (buf) { + // first byte MUST be either 80 or FF + // 80 for positive, FF for 2's comp + var positive + if (buf[0] === 0x80) positive = true + else if (buf[0] === 0xFF) positive = false + else return null + + // build up a base-256 tuple from the least sig to the highest + var zero = false + , tuple = [] + for (var i = buf.length - 1; i > 0; i --) { + var byte = buf[i] + if (positive) tuple.push(byte) + else if (zero && byte === 0) tuple.push(0) + else if (zero) { + zero = false + tuple.push(0x100 - byte) + } else tuple.push(0xFF - byte) + } + + for (var sum = 0, i = 0, l = tuple.length; i < l; i ++) { + sum += tuple[i] * Math.pow(256, i) + } + + return positive ? sum : -1 * sum +} + +function parseNumeric (f) { + if (f[0] & 0x80) return parse256(f) + + var str = f.toString("utf8").split("\0")[0].trim() + , res = parseInt(str, 8) + + return isNaN(res) ? null : res +} + diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/pack.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/pack.js new file mode 100644 index 0000000..11b11fb --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/pack.js @@ -0,0 +1,226 @@ +// pipe in an fstream, and it'll make a tarball. +// key-value pair argument is global extended header props. + +module.exports = Pack + +var EntryWriter = require("./entry-writer.js") + , Stream = require("stream").Stream + , path = require("path") + , inherits = require("../vendor/inherits/inherits.js") + , GlobalHeaderWriter = require("./global-header-writer.js") + , collect = require("../vendor/fstream/fstream.js").collect + , eof = new Buffer(512) + +for (var i = 0; i < 512; i ++) eof[i] = 0 + +inherits(Pack, Stream) + +function Pack (props) { + // console.error("-- p ctor") + var me = this + if (!(me instanceof Pack)) return new Pack(props) + + if (props) me._noProprietary = props.noProprietary + else me._noProprietary = false + + me._global = props + + me.readable = true + me.writable = true + me._buffer = [] + // console.error("-- -- set current to null in ctor") + me._currentEntry = null + me._processing = false + + me._pipeRoot = null + me.on("pipe", function (src) { + if (src.root === me._pipeRoot) return + me._pipeRoot = src + src.on("end", function () { + me._pipeRoot = null + }) + me.add(src) + }) +} + +Pack.prototype.addGlobal = function (props) { + // console.error("-- p addGlobal") + if (this._didGlobal) return + this._didGlobal = true + + var me = this + GlobalHeaderWriter(props) + .on("data", function (c) { + me.emit("data", c) + }) + .end() +} + +Pack.prototype.add = function (stream) { + if (this._global && !this._didGlobal) this.addGlobal(this._global) + + if (this._ended) return this.emit("error", new Error("add after end")) + + collect(stream) + this._buffer.push(stream) + this._process() + this._needDrain = this._buffer.length > 0 + return !this._needDrain +} + +Pack.prototype.pause = function () { + this._paused = true + if (this._currentEntry) this._currentEntry.pause() + this.emit("pause") +} + +Pack.prototype.resume = function () { + this._paused = false + if (this._currentEntry) this._currentEntry.resume() + this.emit("resume") + this._process() +} + +Pack.prototype.end = function () { + this._ended = true + this._buffer.push(eof) + this._process() +} + +Pack.prototype._process = function () { + var me = this + if (me._paused || me._processing) { + return + } + + var entry = me._buffer.shift() + + if (!entry) { + if (me._needDrain) { + me.emit("drain") + } + return + } + + if (entry.ready === false) { + // console.error("-- entry is not ready", entry) + me._buffer.unshift(entry) + entry.on("ready", function () { + // console.error("-- -- ready!", entry) + me._process() + }) + return + } + + me._processing = true + + if (entry === eof) { + // need 2 ending null blocks. + me.emit("data", eof) + me.emit("data", eof) + me.emit("end") + me.emit("close") + return + } + + // Change the path to be relative to the root dir that was + // added to the tarball. + // + // XXX This should be more like how -C works, so you can + // explicitly set a root dir, and also explicitly set a pathname + // in the tarball to use. That way we can skip a lot of extra + // work when resolving symlinks for bundled dependencies in npm. + + var root = path.dirname((entry.root || entry).path) + var wprops = {} + + Object.keys(entry.props).forEach(function (k) { + wprops[k] = entry.props[k] + }) + + if (me._noProprietary) wprops.noProprietary = true + + wprops.path = path.relative(root, entry.path) + + // actually not a matter of opinion or taste. + if (process.platform === "win32") { + wprops.path = wprops.path.replace(/\\/g, "/") + } + + switch (wprops.type) { + // sockets not supported + case "Socket": + return + + case "Directory": + wprops.path += "/" + wprops.size = 0 + break + case "Link": + var lp = path.resolve(path.dirname(entry.path), entry.linkpath) + wprops.linkpath = path.relative(root, lp) || "." + wprops.size = 0 + break + case "SymbolicLink": + var lp = path.resolve(path.dirname(entry.path), entry.linkpath) + wprops.linkpath = path.relative(path.dirname(entry.path), lp) || "." + wprops.size = 0 + break + } + + // console.error("-- new writer", wprops) + // if (!wprops.type) { + // // console.error("-- no type?", entry.constructor.name, entry) + // } + + // console.error("-- -- set current to new writer", wprops.path) + var writer = me._currentEntry = EntryWriter(wprops) + + writer.parent = me + + // writer.on("end", function () { + // // console.error("-- -- writer end", writer.path) + // }) + + writer.on("data", function (c) { + me.emit("data", c) + }) + + writer.on("header", function () { + Buffer.prototype.toJSON = function () { + return this.toString().split(/\0/).join(".") + } + // console.error("-- -- writer header %j", writer.props) + if (writer.props.size === 0) nextEntry() + }) + writer.on("close", nextEntry) + + var ended = false + function nextEntry () { + if (ended) return + ended = true + + // console.error("-- -- writer close", writer.path) + // console.error("-- -- set current to null", wprops.path) + me._currentEntry = null + me._processing = false + me._process() + } + + writer.on("error", function (er) { + // console.error("-- -- writer error", writer.path) + me.emit("error", er) + }) + + // if it's the root, then there's no need to add its entries, + // or data, since they'll be added directly. + if (entry === me._pipeRoot) { + // console.error("-- is the root, don't auto-add") + writer.add = null + } + + entry.pipe(writer) +} + +Pack.prototype.destroy = function () {} +Pack.prototype.write = function () {} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/parse.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/parse.js new file mode 100644 index 0000000..3f71a92 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/lib/parse.js @@ -0,0 +1,270 @@ + +// A writable stream. +// It emits "entry" events, which provide a readable stream that has +// header info attached. + +module.exports = Parse.create = Parse + +var stream = require("stream") + , Stream = stream.Stream + , BlockStream = require("../vendor/block-stream/block-stream.js") + , tar = require("../tar.js") + , TarHeader = require("./header.js") + , Entry = require("./entry.js") + , BufferEntry = require("./buffer-entry.js") + , ExtendedHeader = require("./extended-header.js") + , assert = require("assert").ok + , inherits = require("../vendor/inherits/inherits.js") + , fstream = require("../vendor/fstream/fstream.js") + +// reading a tar is a lot like reading a directory +// However, we're actually not going to run the ctor, +// since it does a stat and various other stuff. +// This inheritance gives us the pause/resume/pipe +// behavior that is desired. +inherits(Parse, fstream.Reader) + +function Parse () { + var me = this + if (!(me instanceof Parse)) return new Parse() + + // doesn't apply fstream.Reader ctor? + // no, becasue we don't want to stat/etc, we just + // want to get the entry/add logic from .pipe() + Stream.apply(me) + + me.writable = true + me.readable = true + me._stream = new BlockStream(512) + me.position = 0 + + me._stream.on("error", function (e) { + me.emit("error", e) + }) + + me._stream.on("data", function (c) { + me._process(c) + }) + + me._stream.on("end", function () { + me._streamEnd() + }) + + me._stream.on("drain", function () { + me.emit("drain") + }) +} + +// overridden in Extract class, since it needs to +// wait for its DirWriter part to finish before +// emitting "end" +Parse.prototype._streamEnd = function () { + var me = this + if (!me._ended) me.error("unexpected eof") + me.emit("end") +} + +// a tar reader is actually a filter, not just a readable stream. +// So, you should pipe a tarball stream into it, and it needs these +// write/end methods to do that. +Parse.prototype.write = function (c) { + if (this._ended) { + // gnutar puts a LOT of nulls at the end. + // you can keep writing these things forever. + // Just ignore them. + for (var i = 0, l = c.length; i > l; i ++) { + if (c[i] !== 0) return this.error("write() after end()") + } + return + } + return this._stream.write(c) +} + +Parse.prototype.end = function (c) { + this._ended = true + return this._stream.end(c) +} + +// don't need to do anything, since we're just +// proxying the data up from the _stream. +// Just need to override the parent's "Not Implemented" +// error-thrower. +Parse.prototype._read = function () {} + +Parse.prototype._process = function (c) { + assert(c && c.length === 512, "block size should be 512") + + // one of three cases. + // 1. A new header + // 2. A part of a file/extended header + // 3. One of two or more EOF null blocks + + if (this._entry) { + var entry = this._entry + entry.write(c) + if (entry._remaining === 0) { + entry.end() + this._entry = null + } + } else { + // either zeroes or a header + var zero = true + for (var i = 0; i < 512 && zero; i ++) { + zero = c[i] === 0 + } + + // eof is *at least* 2 blocks of nulls, and then the end of the + // file. you can put blocks of nulls between entries anywhere, + // so appending one tarball to another is technically valid. + // ending without the eof null blocks is not allowed, however. + if (zero) { + this._ended = this._eofStarted + this._eofStarted = true + } else { + this._ended = this._eofStarted = false + this._startEntry(c) + } + + } + + this.position += 512 +} + +// take a header chunk, start the right kind of entry. +Parse.prototype._startEntry = function (c) { + var header = new TarHeader(c) + , self = this + , entry + , ev + , EntryType + , onend + , meta = false + + if (null === header.size || !header.cksumValid) { + var e = new Error("invalid tar file") + e.header = header + e.tar_file_offset = this.position + e.tar_block = this.position / 512 + this.emit("error", e) + } + + switch (tar.types[header.type]) { + case "File": + case "OldFile": + case "Link": + case "SymbolicLink": + case "CharacterDevice": + case "BlockDevice": + case "Directory": + case "FIFO": + case "ContiguousFile": + case "GNUDumpDir": + // start a file. + // pass in any extended headers + // These ones consumers are typically most interested in. + EntryType = Entry + ev = "entry" + break + + case "GlobalExtendedHeader": + // extended headers that apply to the rest of the tarball + EntryType = ExtendedHeader + onend = function () { + self._global = self._global || {} + Object.keys(entry.fields).forEach(function (k) { + self._global[k] = entry.fields[k] + }) + } + ev = "globalExtendedHeader" + meta = true + break + + case "ExtendedHeader": + case "OldExtendedHeader": + // extended headers that apply to the next entry + EntryType = ExtendedHeader + onend = function () { + self._extended = entry.fields + } + ev = "extendedHeader" + meta = true + break + + case "NextFileHasLongLinkpath": + // set linkpath= in extended header + EntryType = BufferEntry + onend = function () { + self._extended = self._extended || {} + self._extended.linkpath = entry.body + } + ev = "longLinkpath" + meta = true + break + + case "NextFileHasLongPath": + case "OldGnuLongPath": + // set path= in file-extended header + EntryType = BufferEntry + onend = function () { + self._extended = self._extended || {} + self._extended.path = entry.body + } + ev = "longPath" + meta = true + break + + default: + // all the rest we skip, but still set the _entry + // member, so that we can skip over their data appropriately. + // emit an event to say that this is an ignored entry type? + EntryType = Entry + ev = "ignoredEntry" + break + } + + var global, extended + if (meta) { + global = extended = null + } else { + var global = this._global + var extended = this._extended + + // extendedHeader only applies to one entry, so once we start + // an entry, it's over. + this._extended = null + } + entry = new EntryType(header, extended, global) + entry.meta = meta + + // only proxy data events of normal files. + if (!meta) { + entry.on("data", function (c) { + me.emit("data", c) + }) + } + + if (onend) entry.on("end", onend) + + this._entry = entry + var me = this + + entry.on("pause", function () { + me.pause() + }) + + entry.on("resume", function () { + me.resume() + }) + + if (this.listeners("*").length) { + this.emit("*", ev, entry) + } + + this.emit(ev, entry) + + // Zero-byte entry. End immediately. + if (entry.props.size === 0) { + entry.end() + this._entry = null + } +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/tar.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/tar.js new file mode 100644 index 0000000..b9dbca4 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/tar.js @@ -0,0 +1,172 @@ +// field paths that every tar file must have. +// header is padded to 512 bytes. +var f = 0 + , fields = {} + , path = fields.path = f++ + , mode = fields.mode = f++ + , uid = fields.uid = f++ + , gid = fields.gid = f++ + , size = fields.size = f++ + , mtime = fields.mtime = f++ + , cksum = fields.cksum = f++ + , type = fields.type = f++ + , linkpath = fields.linkpath = f++ + , headerSize = 512 + , blockSize = 512 + , fieldSize = [] + +fieldSize[path] = 100 +fieldSize[mode] = 8 +fieldSize[uid] = 8 +fieldSize[gid] = 8 +fieldSize[size] = 12 +fieldSize[mtime] = 12 +fieldSize[cksum] = 8 +fieldSize[type] = 1 +fieldSize[linkpath] = 100 + +// "ustar\0" may introduce another bunch of headers. +// these are optional, and will be nulled out if not present. + +var ustar = fields.ustar = f++ + , ustarver = fields.ustarver = f++ + , uname = fields.uname = f++ + , gname = fields.gname = f++ + , devmaj = fields.devmaj = f++ + , devmin = fields.devmin = f++ + , prefix = fields.prefix = f++ + , fill = fields.fill = f++ + +// terminate fields. +fields[f] = null + +fieldSize[ustar] = 6 +fieldSize[ustarver] = 2 +fieldSize[uname] = 32 +fieldSize[gname] = 32 +fieldSize[devmaj] = 8 +fieldSize[devmin] = 8 +fieldSize[prefix] = 155 +fieldSize[fill] = 12 + +// nb: prefix field may in fact be 130 bytes of prefix, +// a null char, 12 bytes for atime, 12 bytes for ctime. +// +// To recognize this format: +// 1. prefix[130] === ' ' or '\0' +// 2. atime and ctime are octal numeric values +// 3. atime and ctime have ' ' in their last byte + +var fieldEnds = {} + , fieldOffs = {} + , fe = 0 +for (var i = 0; i < f; i ++) { + fieldOffs[i] = fe + fieldEnds[i] = (fe += fieldSize[i]) +} + +// build a translation table of field paths. +Object.keys(fields).forEach(function (f) { + if (fields[f] !== null) fields[fields[f]] = f +}) + +// different values of the 'type' field +// paths match the values of Stats.isX() functions, where appropriate +var types = + { 0: "File" + , "\0": "OldFile" // like 0 + , 1: "Link" + , 2: "SymbolicLink" + , 3: "CharacterDevice" + , 4: "BlockDevice" + , 5: "Directory" + , 6: "FIFO" + , 7: "ContiguousFile" // like 0 + // posix headers + , g: "GlobalExtendedHeader" // k=v for the rest of the archive + , x: "ExtendedHeader" // k=v for the next file + // vendor-specific stuff + , A: "SolarisACL" // skip + , D: "GNUDumpDir" // like 5, but with data, which should be skipped + , I: "Inode" // metadata only, skip + , K: "NextFileHasLongLinkpath" // data = link path of next file + , L: "NextFileHasLongPath" // data = path of next file + , M: "ContinuationFile" // skip + , N: "OldGnuLongPath" // like L + , S: "SparseFile" // skip + , V: "TapeVolumeHeader" // skip + , X: "OldExtendedHeader" // like x + } + +Object.keys(types).forEach(function (t) { + types[types[t]] = types[types[t]] || t +}) + +// values for the mode field +var modes = + { suid: 04000 // set uid on extraction + , sgid: 02000 // set gid on extraction + , svtx: 01000 // set restricted deletion flag on dirs on extraction + , uread: 0400 + , uwrite: 0200 + , uexec: 0100 + , gread: 040 + , gwrite: 020 + , gexec: 010 + , oread: 4 + , owrite: 2 + , oexec: 1 + , all: 07777 + } + +var numeric = + { mode: true + , uid: true + , gid: true + , size: true + , mtime: true + , devmaj: true + , devmin: true + , cksum: true + , atime: true + , ctime: true + , dev: true + , ino: true + , nlink: true + } + +Object.keys(modes).forEach(function (t) { + modes[modes[t]] = modes[modes[t]] || t +}) + +var knownExtended = + { atime: true + , charset: true + , comment: true + , ctime: true + , gid: true + , gname: true + , linkpath: true + , mtime: true + , path: true + , realtime: true + , security: true + , size: true + , uid: true + , uname: true } + + +exports.fields = fields +exports.fieldSize = fieldSize +exports.fieldOffs = fieldOffs +exports.fieldEnds = fieldEnds +exports.types = types +exports.modes = modes +exports.numeric = numeric +exports.headerSize = headerSize +exports.blockSize = blockSize +exports.knownExtended = knownExtended + +exports.Pack = require("./lib/pack.js") +exports.Parse = require("./lib/parse.js") +exports.Extract = require("./lib/extract.js") diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/block-stream/LICENCE b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/block-stream/LICENCE new file mode 100644 index 0000000..74489e2 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/block-stream/LICENCE @@ -0,0 +1,25 @@ +Copyright (c) Isaac Z. Schlueter +All rights reserved. + +The BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. + +THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/block-stream/README.md b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/block-stream/README.md new file mode 100644 index 0000000..c16e9c4 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/block-stream/README.md @@ -0,0 +1,14 @@ +# block-stream + +A stream of blocks. + +Write data into it, and it'll output data in buffer blocks the size you +specify, padding with zeroes if necessary. + +```javascript +var block = new BlockStream(512) +fs.createReadStream("some-file").pipe(block) +block.pipe(fs.createWriteStream("block-file")) +``` + +When `.end()` or `.flush()` is called, it'll pad the block with zeroes. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/block-stream/block-stream.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/block-stream/block-stream.js new file mode 100644 index 0000000..af63e5f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/block-stream/block-stream.js @@ -0,0 +1,209 @@ +// write data to it, and it'll emit data in 512 byte blocks. +// if you .end() or .flush(), it'll emit whatever it's got, +// padded with nulls to 512 bytes. + +module.exports = BlockStream + +var Stream = require("stream").Stream + , inherits = require("../inherits/inherits.js") + , assert = require("assert").ok + , debug = process.env.DEBUG ? console.error : function () {} + +function BlockStream (size, opt) { + this.writable = this.readable = true + this._opt = opt || {} + this._chunkSize = size || 512 + this._offset = 0 + this._buffer = [] + this._bufferLength = 0 + if (this._opt.nopad) this._zeroes = false + else { + this._zeroes = new Buffer(this._chunkSize) + for (var i = 0; i < this._chunkSize; i ++) { + this._zeroes[i] = 0 + } + } +} + +inherits(BlockStream, Stream) + +BlockStream.prototype.write = function (c) { + // debug(" BS write", c) + if (this._ended) throw new Error("BlockStream: write after end") + if (c && !Buffer.isBuffer(c)) c = new Buffer(c + "") + if (c.length) { + this._buffer.push(c) + this._bufferLength += c.length + } + // debug("pushed onto buffer", this._bufferLength) + if (this._bufferLength >= this._chunkSize) { + if (this._paused) { + // debug(" BS paused, return false, need drain") + this._needDrain = true + return false + } + this._emitChunk() + } + return true +} + +BlockStream.prototype.pause = function () { + // debug(" BS pausing") + this._paused = true +} + +BlockStream.prototype.resume = function () { + // debug(" BS resume") + this._paused = false + return this._emitChunk() +} + +BlockStream.prototype.end = function (chunk) { + // debug("end", chunk) + if (typeof chunk === "function") cb = chunk, chunk = null + if (chunk) this.write(chunk) + this._ended = true + this.flush() +} + +BlockStream.prototype.flush = function () { + this._emitChunk(true) +} + +BlockStream.prototype._emitChunk = function (flush) { + // debug("emitChunk flush=%j emitting=%j paused=%j", flush, this._emitting, this._paused) + + // emit a chunk + if (flush && this._zeroes) { + // debug(" BS push zeroes", this._bufferLength) + // push a chunk of zeroes + var padBytes = (this._bufferLength % this._chunkSize) + if (padBytes !== 0) padBytes = this._chunkSize - padBytes + if (padBytes > 0) { + // debug("padBytes", padBytes, this._zeroes.slice(0, padBytes)) + this._buffer.push(this._zeroes.slice(0, padBytes)) + this._bufferLength += padBytes + // debug(this._buffer[this._buffer.length - 1].length, this._bufferLength) + } + } + + if (this._emitting || this._paused) return + this._emitting = true + + // debug(" BS entering loops") + var bufferIndex = 0 + while (this._bufferLength >= this._chunkSize && + (flush || !this._paused)) { + // debug(" BS data emission loop", this._bufferLength) + + var out + , outOffset = 0 + , outHas = this._chunkSize + + while (outHas > 0 && (flush || !this._paused) ) { + // debug(" BS data inner emit loop", this._bufferLength) + var cur = this._buffer[bufferIndex] + , curHas = cur.length - this._offset + // debug("cur=", cur) + // debug("curHas=%j", curHas) + // If it's not big enough to fill the whole thing, then we'll need + // to copy multiple buffers into one. However, if it is big enough, + // then just slice out the part we want, to save unnecessary copying. + // Also, need to copy if we've already done some copying, since buffers + // can't be joined like cons strings. + if (out || curHas < outHas) { + out = out || new Buffer(this._chunkSize) + cur.copy(out, outOffset, + this._offset, this._offset + Math.min(curHas, outHas)) + } else if (cur.length === outHas && this._offset === 0) { + // shortcut -- cur is exactly long enough, and no offset. + out = cur + } else { + // slice out the piece of cur that we need. + out = cur.slice(this._offset, this._offset + outHas) + } + + if (curHas > outHas) { + // means that the current buffer couldn't be completely output + // update this._offset to reflect how much WAS written + this._offset += outHas + outHas = 0 + } else { + // output the entire current chunk. + // toss it away + outHas -= curHas + outOffset += curHas + bufferIndex ++ + this._offset = 0 + } + } + + this._bufferLength -= this._chunkSize + assert(out.length === this._chunkSize) + // debug("emitting data", out) + // debug(" BS emitting, paused=%j", this._paused, this._bufferLength) + this.emit("data", out) + out = null + } + // debug(" BS out of loops", this._bufferLength) + + // whatever is left, it's not enough to fill up a block, or we're paused + this._buffer = this._buffer.slice(bufferIndex) + if (this._paused) { + // debug(" BS paused, leaving", this._bufferLength) + this._needsDrain = true + this._emitting = false + return + } + + // if flushing, and not using null-padding, then need to emit the last + // chunk(s) sitting in the queue. We know that it's not enough to + // fill up a whole block, because otherwise it would have been emitted + // above, but there may be some offset. + var l = this._buffer.length + if (flush && !this._zeroes && l) { + if (l === 1) { + if (this._offset) { + this.emit("data", this._buffer[0].slice(this._offset)) + } else { + this.emit("data", this._buffer[0]) + } + } else { + var outHas = this._bufferLength + , out = new Buffer(outHas) + , outOffset = 0 + for (var i = 0; i < l; i ++) { + var cur = this._buffer[i] + , curHas = cur.length - this._offset + cur.copy(out, outOffset, this._offset) + this._offset = 0 + outOffset += curHas + this._bufferLength -= curHas + } + this.emit("data", out) + } + // truncate + this._buffer.length = 0 + this._bufferLength = 0 + this._offset = 0 + } + + // now either drained or ended + // debug("either draining, or ended", this._bufferLength, this._ended) + // means that we've flushed out all that we can so far. + if (this._needDrain) { + // debug("emitting drain", this._bufferLength) + this._needDrain = false + this.emit("drain") + } + + if ((this._bufferLength === 0) && this._ended && !this._endEmitted) { + // debug("emitting end", this._bufferLength) + this._endEmitted = true + this.emit("end") + } + + this._emitting = false + + // debug(" BS no longer emitting", flush, this._paused, this._emitting, this._bufferLength, this._chunkSize) +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/LICENCE b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/LICENCE new file mode 100644 index 0000000..74489e2 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/LICENCE @@ -0,0 +1,25 @@ +Copyright (c) Isaac Z. Schlueter +All rights reserved. + +The BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. 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. + +THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/README.md b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/README.md new file mode 100644 index 0000000..9d8cb77 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/README.md @@ -0,0 +1,76 @@ +Like FS streams, but with stat on them, and supporting directories and +symbolic links, as well as normal files. Also, you can use this to set +the stats on a file, even if you don't change its contents, or to create +a symlink, etc. + +So, for example, you can "write" a directory, and it'll call `mkdir`. You +can specify a uid and gid, and it'll call `chown`. You can specify a +`mtime` and `atime`, and it'll call `utimes`. You can call it a symlink +and provide a `linkpath` and it'll call `symlink`. + +Note that it won't automatically resolve symbolic links. So, if you +call `fstream.Reader('/some/symlink')` then you'll get an object +that stats and then ends immediately (since it has no data). To follow +symbolic links, do this: `fstream.Reader({path:'/some/symlink', follow: +true })`. + +There are various checks to make sure that the bytes emitted are the +same as the intended size, if the size is set. + +## Examples + +```javascript +fstream + .Writer({ path: "path/to/file" + , mode: 0755 + , size: 6 + }) + .write("hello\n") + .end() +``` + +This will create the directories if they're missing, and then write +`hello\n` into the file, chmod it to 0755, and assert that 6 bytes have +been written when it's done. + +```javascript +fstream + .Writer({ path: "path/to/file" + , mode: 0755 + , size: 6 + , flags: "a" + }) + .write("hello\n") + .end() +``` + +You can pass flags in, if you want to append to a file. + +```javascript +fstream + .Writer({ path: "path/to/symlink" + , linkpath: "./file" + , SymbolicLink: true + , mode: "0755" // octal strings supported + }) + .end() +``` + +If isSymbolicLink is a function, it'll be called, and if it returns +true, then it'll treat it as a symlink. If it's not a function, then +any truish value will make a symlink, or you can set `type: +'SymbolicLink'`, which does the same thing. + +Note that the linkpath is relative to the symbolic link location, not +the parent dir or cwd. + +```javascript +fstream + .Reader("path/to/dir") + .pipe(fstream.Writer("path/to/other/dir")) +``` + +This will do like `cp -Rp path/to/dir path/to/other/dir`. If the other +dir exists and isn't a directory, then it'll emit an error. It'll also +set the uid, gid, mode, etc. to be identical. In this way, it's more +like `rsync -a` than simply a copy. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/fstream.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/fstream.js new file mode 100644 index 0000000..c66d26f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/fstream.js @@ -0,0 +1,31 @@ +exports.Abstract = require("./lib/abstract.js") +exports.Reader = require("./lib/reader.js") +exports.Writer = require("./lib/writer.js") + +exports.File = + { Reader: require("./lib/file-reader.js") + , Writer: require("./lib/file-writer.js") } + +exports.Dir = + { Reader : require("./lib/dir-reader.js") + , Writer : require("./lib/dir-writer.js") } + +exports.Link = + { Reader : require("./lib/link-reader.js") + , Writer : require("./lib/link-writer.js") } + +exports.Proxy = + { Reader : require("./lib/proxy-reader.js") + , Writer : require("./lib/proxy-writer.js") } + +exports.Reader.Dir = exports.DirReader = exports.Dir.Reader +exports.Reader.File = exports.FileReader = exports.File.Reader +exports.Reader.Link = exports.LinkReader = exports.Link.Reader +exports.Reader.Proxy = exports.ProxyReader = exports.Proxy.Reader + +exports.Writer.Dir = exports.DirWriter = exports.Dir.Writer +exports.Writer.File = exports.FileWriter = exports.File.Writer +exports.Writer.Link = exports.LinkWriter = exports.Link.Writer +exports.Writer.Proxy = exports.ProxyWriter = exports.Proxy.Writer + +exports.collect = require("./lib/collect.js") diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/abstract.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/abstract.js new file mode 100644 index 0000000..6161f3b --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/abstract.js @@ -0,0 +1,85 @@ +// the parent class for all fstreams. + +module.exports = Abstract + +var Stream = require("stream").Stream + , inherits = require("../../inherits/inherits.js") + +function Abstract () { + Stream.call(this) +} + +inherits(Abstract, Stream) + +Abstract.prototype.on = function (ev, fn) { + if (ev === "ready" && this.ready) { + process.nextTick(fn.bind(this)) + } else { + Stream.prototype.on.call(this, ev, fn) + } + return this +} + +Abstract.prototype.abort = function () { + this._aborted = true + this.emit("abort") +} + +Abstract.prototype.destroy = function () {} + +Abstract.prototype.warn = function (msg, code) { + var me = this + , er = decorate(msg, code, me) + if (!me.listeners("warn")) { + console.error("%s %s\n" + + "path = %s\n" + + "syscall = %s\n" + + "fstream_type = %s\n" + + "fstream_path = %s\n" + + "fstream_unc_path = %s\n" + + "fstream_class = %s\n" + + "fstream_stack =\n%s\n", + code || "UNKNOWN", + er.stack, + er.path, + er.syscall, + er.fstream_type, + er.fstream_path, + er.fstream_unc_path, + er.fstream_class, + er.fstream_stack.join("\n")) + } else { + me.emit("warn", er) + } +} + +Abstract.prototype.info = function (msg, code) { + this.emit("info", msg, code) +} + +Abstract.prototype.error = function (msg, code, th) { + var er = decorate(msg, code, this) + if (th) throw er + else this.emit("error", er) +} + +function decorate (er, code, me) { + if (!(er instanceof Error)) er = new Error(er) + er.code = er.code || code + er.path = er.path || me.path + er.fstream_type = er.fstream_type || me.type + er.fstream_path = er.fstream_path || me.path + if (me._path !== me.path) { + er.fstream_unc_path = er.fstream_unc_path || me._path + } + if (me.linkpath) { + er.fstream_linkpath = er.fstream_linkpath || me.linkpath + } + er.fstream_class = er.fstream_class || me.constructor.name + er.fstream_stack = er.fstream_stack || + new Error().stack.split(/\n/).slice(3).map(function (s) { + return s.replace(/^ at /, "") + }) + + return er +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/collect.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/collect.js new file mode 100644 index 0000000..a36f780 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/collect.js @@ -0,0 +1,67 @@ +module.exports = collect + +function collect (stream) { + if (stream._collected) return + + stream._collected = true + stream.pause() + + stream.on("data", save) + stream.on("end", save) + var buf = [] + function save (b) { + if (typeof b === "string") b = new Buffer(b) + if (Buffer.isBuffer(b) && !b.length) return + buf.push(b) + } + + stream.on("entry", saveEntry) + var entryBuffer = [] + function saveEntry (e) { + collect(e) + entryBuffer.push(e) + } + + stream.on("proxy", proxyPause) + function proxyPause (p) { + p.pause() + } + + + // replace the pipe method with a new version that will + // unlock the buffered stuff. if you just call .pipe() + // without a destination, then it'll re-play the events. + stream.pipe = (function (orig) { return function (dest) { + // console.error(" === open the pipes", dest && dest.path) + + // let the entries flow through one at a time. + // Once they're all done, then we can resume completely. + var e = 0 + ;(function unblockEntry () { + var entry = entryBuffer[e++] + // console.error(" ==== unblock entry", entry && entry.path) + if (!entry) return resume() + entry.on("end", unblockEntry) + if (dest) dest.add(entry) + else stream.emit("entry", entry) + })() + + function resume () { + stream.removeListener("entry", saveEntry) + stream.removeListener("data", save) + stream.removeListener("end", save) + + stream.pipe = orig + if (dest) stream.pipe(dest) + + buf.forEach(function (b) { + if (b) stream.emit("data", b) + else stream.emit("end") + }) + + stream.resume() + } + + return dest + }})(stream.pipe) +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/dir-reader.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/dir-reader.js new file mode 100644 index 0000000..e655b0d --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/dir-reader.js @@ -0,0 +1,250 @@ +// A thing that emits "entry" events with Reader objects +// Pausing it causes it to stop emitting entry events, and also +// pauses the current entry if there is one. + +module.exports = DirReader + +var fs = require("../../graceful-fs/graceful-fs.js") + , fstream = require("../fstream.js") + , Reader = fstream.Reader + , inherits = require("../../inherits/inherits.js") + , mkdir = require("../../mkdirp") + , path = require("path") + , Reader = require("./reader.js") + , assert = require("assert").ok + +inherits(DirReader, Reader) + +function DirReader (props) { + var me = this + if (!(me instanceof DirReader)) throw new Error( + "DirReader must be called as constructor.") + + // should already be established as a Directory type + if (props.type !== "Directory" || !props.Directory) { + throw new Error("Non-directory type "+ props.type) + } + + me.entries = null + me._index = -1 + me._paused = false + me._length = -1 + + if (props.sort) { + this.sort = props.sort + } + + Reader.call(this, props) +} + +DirReader.prototype._getEntries = function () { + var me = this + + // race condition. might pause() before calling _getEntries, + // and then resume, and try to get them a second time. + if (me._gotEntries) return + me._gotEntries = true + + fs.readdir(me._path, function (er, entries) { + if (er) return me.error(er) + + me.entries = entries + + me.emit("entries", entries) + if (me._paused) me.once("resume", processEntries) + else processEntries() + + function processEntries () { + me._length = me.entries.length + if (typeof me.sort === "function") { + me.entries = me.entries.sort(me.sort.bind(me)) + } + me._read() + } + }) +} + +// start walking the dir, and emit an "entry" event for each one. +DirReader.prototype._read = function () { + var me = this + + if (!me.entries) return me._getEntries() + + if (me._paused || me._currentEntry || me._aborted) { + // console.error("DR paused=%j, current=%j, aborted=%j", me._paused, !!me._currentEntry, me._aborted) + return + } + + me._index ++ + if (me._index >= me.entries.length) { + if (!me._ended) { + me._ended = true + me.emit("end") + me.emit("close") + } + return + } + + // ok, handle this one, then. + + // save creating a proxy, by stat'ing the thing now. + var p = path.resolve(me._path, me.entries[me._index]) + assert(p !== me._path) + assert(me.entries[me._index]) + + // set this to prevent trying to _read() again in the stat time. + me._currentEntry = p + fs[ me.props.follow ? "stat" : "lstat" ](p, function (er, stat) { + if (er) return me.error(er) + + var who = me._proxy || me + + stat.path = p + stat.basename = path.basename(p) + stat.dirname = path.dirname(p) + var childProps = me.getChildProps.call(who, stat) + childProps.path = p + childProps.basename = path.basename(p) + childProps.dirname = path.dirname(p) + + var entry = Reader(childProps, stat) + + // console.error("DR Entry", p, stat.size) + + me._currentEntry = entry + + // "entry" events are for direct entries in a specific dir. + // "child" events are for any and all children at all levels. + // This nomenclature is not completely final. + + entry.on("pause", function (who) { + if (!me._paused && !entry._disowned) { + me.pause(who) + } + }) + + entry.on("resume", function (who) { + if (me._paused && !entry._disowned) { + me.resume(who) + } + }) + + entry.on("stat", function (props) { + me.emit("_entryStat", entry, props) + if (entry._aborted) return + if (entry._paused) entry.once("resume", function () { + me.emit("entryStat", entry, props) + }) + else me.emit("entryStat", entry, props) + }) + + entry.on("ready", function EMITCHILD () { + // console.error("DR emit child", entry._path) + if (me._paused) { + // console.error(" DR emit child - try again later") + // pause the child, and emit the "entry" event once we drain. + // console.error("DR pausing child entry") + entry.pause(me) + return me.once("resume", EMITCHILD) + } + + // skip over sockets. they can't be piped around properly, + // so there's really no sense even acknowledging them. + // if someone really wants to see them, they can listen to + // the "socket" events. + if (entry.type === "Socket") { + me.emit("socket", entry) + } else { + me.emitEntry(entry) + } + }) + + var ended = false + entry.on("close", onend) + entry.on("disown", onend) + function onend () { + if (ended) return + ended = true + me.emit("childEnd", entry) + me.emit("entryEnd", entry) + me._currentEntry = null + if (!me._paused) { + me._read() + } + } + + // XXX Remove this. Works in node as of 0.6.2 or so. + // Long filenames should not break stuff. + entry.on("error", function (er) { + if (entry._swallowErrors) { + me.warn(er) + entry.emit("end") + entry.emit("close") + } else { + me.emit("error", er) + } + }) + + // proxy up some events. + ; [ "child" + , "childEnd" + , "warn" + ].forEach(function (ev) { + entry.on(ev, me.emit.bind(me, ev)) + }) + }) +} + +DirReader.prototype.disown = function (entry) { + entry.emit("beforeDisown") + entry._disowned = true + entry.parent = entry.root = null + if (entry === this._currentEntry) { + this._currentEntry = null + } + entry.emit("disown") +} + +DirReader.prototype.getChildProps = function (stat) { + return { depth: this.depth + 1 + , root: this.root || this + , parent: this + , follow: this.follow + , filter: this.filter + , sort: this.props.sort + } +} + +DirReader.prototype.pause = function (who) { + var me = this + if (me._paused) return + who = who || me + me._paused = true + if (me._currentEntry && me._currentEntry.pause) { + me._currentEntry.pause(who) + } + me.emit("pause", who) +} + +DirReader.prototype.resume = function (who) { + var me = this + if (!me._paused) return + who = who || me + + me._paused = false + // console.error("DR Emit Resume", me._path) + me.emit("resume", who) + if (me._paused) { + // console.error("DR Re-paused", me._path) + return + } + + if (me._currentEntry) { + if (me._currentEntry.resume) me._currentEntry.resume(who) + } else me._read() +} + +DirReader.prototype.emitEntry = function (entry) { + this.emit("entry", entry) + this.emit("child", entry) +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/dir-writer.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/dir-writer.js new file mode 100644 index 0000000..71eb358 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/dir-writer.js @@ -0,0 +1,171 @@ +// It is expected that, when .add() returns false, the consumer +// of the DirWriter will pause until a "drain" event occurs. Note +// that this is *almost always going to be the case*, unless the +// thing being written is some sort of unsupported type, and thus +// skipped over. + +module.exports = DirWriter + +var fs = require("../../graceful-fs/graceful-fs.js") + , fstream = require("../fstream.js") + , Writer = require("./writer.js") + , inherits = require("../../inherits/inherits.js") + , mkdir = require("../../mkdirp") + , path = require("path") + , collect = require("./collect.js") + +inherits(DirWriter, Writer) + +function DirWriter (props) { + var me = this + if (!(me instanceof DirWriter)) me.error( + "DirWriter must be called as constructor.", null, true) + + // should already be established as a Directory type + if (props.type !== "Directory" || !props.Directory) { + me.error("Non-directory type "+ props.type + " " + + JSON.stringify(props), null, true) + } + + Writer.call(this, props) +} + +DirWriter.prototype._create = function () { + var me = this + mkdir(me._path, Writer.dirmode, function (er) { + if (er) return me.error(er) + // ready to start getting entries! + me.ready = true + me.emit("ready") + me._process() + }) +} + +// a DirWriter has an add(entry) method, but its .write() doesn't +// do anything. Why a no-op rather than a throw? Because this +// leaves open the door for writing directory metadata for +// gnu/solaris style dumpdirs. +DirWriter.prototype.write = function () { + return true +} + +DirWriter.prototype.end = function () { + this._ended = true + this._process() +} + +DirWriter.prototype.add = function (entry) { + var me = this + + // console.error("\tadd", entry._path, "->", me._path) + collect(entry) + if (!me.ready || me._currentEntry) { + me._buffer.push(entry) + return false + } + + // create a new writer, and pipe the incoming entry into it. + if (me._ended) { + return me.error("add after end") + } + + me._buffer.push(entry) + me._process() + + return 0 === this._buffer.length +} + +DirWriter.prototype._process = function () { + var me = this + + // console.error("DW Process p=%j", me._processing, me.basename) + + if (me._processing) return + + var entry = me._buffer.shift() + if (!entry) { + // console.error("DW Drain") + me.emit("drain") + if (me._ended) me._finish() + return + } + + me._processing = true + // console.error("DW Entry", entry._path) + + me.emit("entry", entry) + + // ok, add this entry + // + // don't allow recursive copying + var p = entry + do { + var pp = p._path || p.path + if (pp === me.root._path || pp === me._path || + (pp && pp.indexOf(me._path) === 0)) { + // console.error("DW Exit (recursive)", entry.basename, me._path) + me._processing = false + if (entry._collected) entry.pipe() + return me._process() + } + } while (p = p.parent) + + // console.error("DW not recursive") + + // chop off the entry's root dir, replace with ours + var props = { parent: me + , root: me.root || me + , type: entry.type + , depth: me.depth + 1 } + + var p = entry._path || entry.path || entry.props.path + if (entry.parent) { + p = p.substr(entry.parent._path.length + 1) + } + // get rid of any ../../ shenanigans + props.path = path.join(me.path, path.join("/", p)) + + // if i have a filter, the child should inherit it. + props.filter = me.filter + + // all the rest of the stuff, copy over from the source. + Object.keys(entry.props).forEach(function (k) { + if (!props.hasOwnProperty(k)) { + props[k] = entry.props[k] + } + }) + + // not sure at this point what kind of writer this is. + var child = me._currentChild = new Writer(props) + child.on("ready", function () { + // console.error("DW Child Ready", child.type, child._path) + // console.error(" resuming", entry._path) + entry.pipe(child) + entry.resume() + }) + + // XXX Make this work in node. + // Long filenames should not break stuff. + child.on("error", function (er) { + if (child._swallowErrors) { + me.warn(er) + child.emit("end") + child.emit("close") + } else { + me.emit("error", er) + } + }) + + // we fire _end internally *after* end, so that we don't move on + // until any "end" listeners have had their chance to do stuff. + child.on("close", onend) + var ended = false + function onend () { + if (ended) return + ended = true + // console.error("* DW Child end", child.basename) + me._currentChild = null + me._processing = false + me._process() + } +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/file-reader.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/file-reader.js new file mode 100644 index 0000000..e53718a --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/file-reader.js @@ -0,0 +1,147 @@ +// Basically just a wrapper around an fs.ReadStream + +module.exports = FileReader + +var fs = require("../../graceful-fs/graceful-fs.js") + , fstream = require("../fstream.js") + , Reader = fstream.Reader + , inherits = require("../../inherits/inherits.js") + , mkdir = require("../../mkdirp") + , Reader = require("./reader.js") + , EOF = {EOF: true} + , CLOSE = {CLOSE: true} + +inherits(FileReader, Reader) + +function FileReader (props) { + // console.error(" FR create", props.path, props.size, new Error().stack) + var me = this + if (!(me instanceof FileReader)) throw new Error( + "FileReader must be called as constructor.") + + // should already be established as a File type + // XXX Todo: preserve hardlinks by tracking dev+inode+nlink, + // with a HardLinkReader class. + if (!((props.type === "Link" && props.Link) || + (props.type === "File" && props.File))) { + throw new Error("Non-file type "+ props.type) + } + + me._buffer = [] + me._bytesEmitted = 0 + Reader.call(me, props) +} + +FileReader.prototype._getStream = function () { + var me = this + , stream = me._stream = fs.createReadStream(me._path, me.props) + + if (me.props.blksize) { + stream.bufferSize = me.props.blksize + } + + stream.on("open", me.emit.bind(me, "open")) + + stream.on("data", function (c) { + // console.error("\t\t%d %s", c.length, me.basename) + me._bytesEmitted += c.length + // no point saving empty chunks + if (!c.length) return + else if (me._paused || me._buffer.length) { + me._buffer.push(c) + me._read() + } else me.emit("data", c) + }) + + stream.on("end", function () { + if (me._paused || me._buffer.length) { + // console.error("FR Buffering End", me._path) + me._buffer.push(EOF) + me._read() + } else { + me.emit("end") + } + + if (me._bytesEmitted !== me.props.size) { + me.error("Didn't get expected byte count\n"+ + "expect: "+me.props.size + "\n" + + "actual: "+me._bytesEmitted) + } + }) + + stream.on("close", function () { + if (me._paused || me._buffer.length) { + // console.error("FR Buffering Close", me._path) + me._buffer.push(CLOSE) + me._read() + } else { + // console.error("FR close 1", me._path) + me.emit("close") + } + }) + + me._read() +} + +FileReader.prototype._read = function () { + var me = this + // console.error("FR _read", me._path) + if (me._paused) { + // console.error("FR _read paused", me._path) + return + } + + if (!me._stream) { + // console.error("FR _getStream calling", me._path) + return me._getStream() + } + + // clear out the buffer, if there is one. + if (me._buffer.length) { + // console.error("FR _read has buffer", me._buffer.length, me._path) + var buf = me._buffer + for (var i = 0, l = buf.length; i < l; i ++) { + var c = buf[i] + if (c === EOF) { + // console.error("FR Read emitting buffered end", me._path) + me.emit("end") + } else if (c === CLOSE) { + // console.error("FR Read emitting buffered close", me._path) + me.emit("close") + } else { + // console.error("FR Read emitting buffered data", me._path) + me.emit("data", c) + } + + if (me._paused) { + // console.error("FR Read Re-pausing at "+i, me._path) + me._buffer = buf.slice(i) + return + } + } + me._buffer.length = 0 + } + // console.error("FR _read done") + // that's about all there is to it. +} + +FileReader.prototype.pause = function (who) { + var me = this + // console.error("FR Pause", me._path) + if (me._paused) return + who = who || me + me._paused = true + if (me._stream) me._stream.pause() + me.emit("pause", who) +} + +FileReader.prototype.resume = function (who) { + var me = this + // console.error("FR Resume", me._path) + if (!me._paused) return + who = who || me + me.emit("resume", who) + me._paused = false + if (me._stream) me._stream.resume() + me._read() +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/file-writer.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/file-writer.js new file mode 100644 index 0000000..70bb86d --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/file-writer.js @@ -0,0 +1,95 @@ +module.exports = FileWriter + +var fs = require("../../graceful-fs/graceful-fs.js") + , mkdir = require("../../mkdirp") + , Writer = require("./writer.js") + , inherits = require("../../inherits/inherits.js") + , EOF = {} + +inherits(FileWriter, Writer) + +function FileWriter (props) { + var me = this + if (!(me instanceof FileWriter)) throw new Error( + "FileWriter must be called as constructor.") + + // should already be established as a File type + if (props.type !== "File" || !props.File) { + throw new Error("Non-file type "+ props.type) + } + + me._buffer = [] + me._bytesWritten = 0 + + Writer.call(this, props) +} + +FileWriter.prototype._create = function () { + var me = this + if (me._stream) return + + var so = {} + if (me.props.flags) so.flags = me.props.flags + so.mode = Writer.filemode + if (me._old && me._old.blksize) so.bufferSize = me._old.blksize + + me._stream = fs.createWriteStream(me._path, so) + + me._stream.on("open", function (fd) { + me.ready = true + me._buffer.forEach(function (c) { + if (c === EOF) me._stream.end() + else me._stream.write(c) + }) + me.emit("ready") + }) + + me._stream.on("drain", function () { me.emit("drain") }) + + me._stream.on("close", function () { + // console.error("\n\nFW Stream Close", me._path, me.size) + me._finish() + }) +} + +FileWriter.prototype.write = function (c) { + var me = this + + me._bytesWritten += c.length + + if (!me.ready) { + me._buffer.push(c) + return false + } + + var ret = me._stream.write(c) + // console.error("\t-- fw wrote, _stream says", ret, me._stream._queue.length) + + // allow 2 buffered writes, because otherwise there's just too + // much stop and go bs. + return ret || (me._stream._queue && me._stream._queue.length <= 2) +} + +FileWriter.prototype.end = function (c) { + var me = this + + if (c) me.write(c) + + if (!me.ready) { + me._buffer.push(EOF) + return false + } + + return me._stream.end() +} + +FileWriter.prototype._finish = function () { + var me = this + if (typeof me.size === "number" && me._bytesWritten != me.size) { + me.error( + "Did not get expected byte count.\n" + + "expect: " + me.size + "\n" + + "actual: " + me._bytesWritten) + } + Writer.prototype._finish.call(me) +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/get-type.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/get-type.js new file mode 100644 index 0000000..cd65c41 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/get-type.js @@ -0,0 +1,32 @@ +module.exports = getType + +function getType (st) { + var types = + [ "Directory" + , "File" + , "SymbolicLink" + , "Link" // special for hardlinks from tarballs + , "BlockDevice" + , "CharacterDevice" + , "FIFO" + , "Socket" ] + , type + + if (st.type && -1 !== types.indexOf(st.type)) { + st[st.type] = true + return st.type + } + + for (var i = 0, l = types.length; i < l; i ++) { + type = types[i] + var is = st[type] || st["is" + type] + if (typeof is === "function") is = is.call(st) + if (is) { + st[type] = true + st.type = type + return type + } + } + + return null +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/link-reader.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/link-reader.js new file mode 100644 index 0000000..1d07e2f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/link-reader.js @@ -0,0 +1,54 @@ +// Basically just a wrapper around an fs.readlink +// +// XXX: Enhance this to support the Link type, by keeping +// a lookup table of {:}, so that hardlinks +// can be preserved in tarballs. + +module.exports = LinkReader + +var fs = require("../../graceful-fs/graceful-fs.js") + , fstream = require("../fstream.js") + , inherits = require("../../inherits/inherits.js") + , mkdir = require("../../mkdirp") + , Reader = require("./reader.js") + +inherits(LinkReader, Reader) + +function LinkReader (props) { + var me = this + if (!(me instanceof LinkReader)) throw new Error( + "LinkReader must be called as constructor.") + + if (!((props.type === "Link" && props.Link) || + (props.type === "SymbolicLink" && props.SymbolicLink))) { + throw new Error("Non-link type "+ props.type) + } + + Reader.call(me, props) +} + +// When piping a LinkReader into a LinkWriter, we have to +// already have the linkpath property set, so that has to +// happen *before* the "ready" event, which means we need to +// override the _stat method. +LinkReader.prototype._stat = function (currentStat) { + var me = this + fs.readlink(me._path, function (er, linkpath) { + if (er) return me.error(er) + me.linkpath = me.props.linkpath = linkpath + me.emit("linkpath", linkpath) + Reader.prototype._stat.call(me, currentStat) + }) +} + +LinkReader.prototype._read = function () { + var me = this + if (me._paused) return + // basically just a no-op, since we got all the info we need + // from the _stat method + if (!me._ended) { + me.emit("end") + me.emit("close") + me._ended = true + } +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/link-writer.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/link-writer.js new file mode 100644 index 0000000..c652eb3 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/link-writer.js @@ -0,0 +1,95 @@ + +module.exports = LinkWriter + +var fs = require("../../graceful-fs/graceful-fs.js") + , Writer = require("./writer.js") + , inherits = require("../../inherits/inherits.js") + , path = require("path") + , rimraf = require("../../rimraf/rimraf.js") + +inherits(LinkWriter, Writer) + +function LinkWriter (props) { + var me = this + if (!(me instanceof LinkWriter)) throw new Error( + "LinkWriter must be called as constructor.") + + // should already be established as a Link type + if (!((props.type === "Link" && props.Link) || + (props.type === "SymbolicLink" && props.SymbolicLink))) { + throw new Error("Non-link type "+ props.type) + } + + if (props.linkpath === "") props.linkpath = "." + if (!props.linkpath) { + me.error("Need linkpath property to create " + props.type) + } + + Writer.call(this, props) +} + +LinkWriter.prototype._create = function () { + // console.error(" LW _create") + var me = this + , hard = me.type === "Link" || process.platform === "win32" + , link = hard ? "link" : "symlink" + , lp = hard ? path.resolve(me.dirname, me.linkpath) : me.linkpath + + // can only change the link path by clobbering + // For hard links, let's just assume that's always the case, since + // there's no good way to read them if we don't already know. + if (hard) return clobber(me, lp, link) + + fs.readlink(me._path, function (er, p) { + // only skip creation if it's exactly the same link + if (p && p === lp) return finish(me) + clobber(me, lp, link) + }) +} + +function clobber (me, lp, link) { + rimraf(me._path, function (er) { + if (er) return me.error(er) + create(me, lp, link) + }) +} + +function create (me, lp, link) { + fs[link](lp, me._path, function (er) { + // if this is a hard link, and we're in the process of writing out a + // directory, it's very possible that the thing we're linking to + // doesn't exist yet (especially if it was intended as a symlink), + // so swallow ENOENT errors here and just soldier in. + // Additionally, an EPERM or EACCES can happen on win32 if it's trying + // to make a link to a directory. Again, just skip it. + // A better solution would be to have fs.symlink be supported on + // windows in some nice fashion. + if (er) { + if ((er.code === "ENOENT" || + er.code === "EACCES" || + er.code === "EPERM" ) && process.platform === "win32") { + me.ready = true + me.emit("ready") + me.emit("end") + me.emit("close") + me.end = me._finish = function () {} + } else return me.error(er) + } + finish(me) + }) +} + +function finish (me) { + me.ready = true + me.emit("ready") + if (me._ended && !me._finished) me._finish() +} + +LinkWriter.prototype.end = function () { + // console.error("LW finish in end") + this._ended = true + if (this.ready) { + this._finished = true + this._finish() + } +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/proxy-reader.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/proxy-reader.js new file mode 100644 index 0000000..a51ebdf --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/proxy-reader.js @@ -0,0 +1,93 @@ +// A reader for when we don't yet know what kind of thing +// the thing is. + +module.exports = ProxyReader + +var Reader = require("./reader.js") + , getType = require("./get-type.js") + , inherits = require("../../inherits/inherits.js") + , fs = require("../../graceful-fs/graceful-fs.js") + +inherits(ProxyReader, Reader) + +function ProxyReader (props) { + var me = this + if (!(me instanceof ProxyReader)) throw new Error( + "ProxyReader must be called as constructor.") + + me.props = props + me._buffer = [] + me.ready = false + + Reader.call(me, props) +} + +ProxyReader.prototype._stat = function () { + var me = this + , props = me.props + // stat the thing to see what the proxy should be. + , stat = props.follow ? "stat" : "lstat" + + fs[stat](props.path, function (er, current) { + var type + if (er || !current) { + type = "File" + } else { + type = getType(current) + } + + props[type] = true + props.type = me.type = type + + me._old = current + me._addProxy(Reader(props, current)) + }) +} + +ProxyReader.prototype._addProxy = function (proxy) { + var me = this + if (me._proxyTarget) { + return me.error("proxy already set") + } + + me._proxyTarget = proxy + proxy._proxy = me + + ; [ "error" + , "data" + , "end" + , "close" + , "linkpath" + , "entry" + , "entryEnd" + , "child" + , "childEnd" + , "warn" + , "stat" + ].forEach(function (ev) { + // console.error("~~ proxy event", ev, me.path) + proxy.on(ev, me.emit.bind(me, ev)) + }) + + me.emit("proxy", proxy) + + proxy.on("ready", function () { + // console.error("~~ proxy is ready!", me.path) + me.ready = true + me.emit("ready") + }) + + var calls = me._buffer + me._buffer.length = 0 + calls.forEach(function (c) { + proxy[c[0]].apply(proxy, c[1]) + }) +} + +ProxyReader.prototype.pause = function () { + return this._proxyTarget ? this._proxyTarget.pause() : false +} + +ProxyReader.prototype.resume = function () { + return this._proxyTarget ? this._proxyTarget.resume() : false +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/proxy-writer.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/proxy-writer.js new file mode 100644 index 0000000..2e6bae4 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/proxy-writer.js @@ -0,0 +1,109 @@ +// A writer for when we don't know what kind of thing +// the thing is. That is, it's not explicitly set, +// so we're going to make it whatever the thing already +// is, or "File" +// +// Until then, collect all events. + +module.exports = ProxyWriter + +var Writer = require("./writer.js") + , getType = require("./get-type.js") + , inherits = require("../../inherits/inherits.js") + , collect = require("./collect.js") + , fs = require("fs") + +inherits(ProxyWriter, Writer) + +function ProxyWriter (props) { + var me = this + if (!(me instanceof ProxyWriter)) throw new Error( + "ProxyWriter must be called as constructor.") + + me.props = props + me._needDrain = false + + Writer.call(me, props) +} + +ProxyWriter.prototype._stat = function () { + var me = this + , props = me.props + // stat the thing to see what the proxy should be. + , stat = props.follow ? "stat" : "lstat" + + fs[stat](props.path, function (er, current) { + var type + if (er || !current) { + type = "File" + } else { + type = getType(current) + } + + props[type] = true + props.type = me.type = type + + me._old = current + me._addProxy(Writer(props, current)) + }) +} + +ProxyWriter.prototype._addProxy = function (proxy) { + // console.error("~~ set proxy", this.path) + var me = this + if (me._proxy) { + return me.error("proxy already set") + } + + me._proxy = proxy + ; [ "ready" + , "error" + , "close" + , "pipe" + , "drain" + , "warn" + ].forEach(function (ev) { + proxy.on(ev, me.emit.bind(me, ev)) + }) + + me.emit("proxy", proxy) + + var calls = me._buffer + calls.forEach(function (c) { + // console.error("~~ ~~ proxy buffered call", c[0], c[1]) + proxy[c[0]].call(proxy, c[1]) + }) + me._buffer.length = 0 + if (me._needsDrain) me.emit("drain") +} + +ProxyWriter.prototype.add = function (entry) { + // console.error("~~ proxy add") + collect(entry) + + if (!this._proxy) { + this._buffer.push(["add", [entry]]) + this._needDrain = true + return false + } + return this._proxy.add(entry) +} + +ProxyWriter.prototype.write = function (c) { + // console.error("~~ proxy write") + if (!this._proxy) { + this._buffer.push(["write", [c]]) + this._needDrain = true + return false + } + return this._proxy.write(c) +} + +ProxyWriter.prototype.end = function (c) { + // console.error("~~ proxy end") + if (!this._proxy) { + this._buffer.push(["end", c]) + return false + } + return this._proxy.end(c) +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/reader.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/reader.js new file mode 100644 index 0000000..42a8701 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/reader.js @@ -0,0 +1,258 @@ + +module.exports = Reader + +var fs = require("../../graceful-fs/graceful-fs.js") + , Stream = require("stream").Stream + , inherits = require("../../inherits/inherits.js") + , path = require("path") + , getType = require("./get-type.js") + , hardLinks = Reader.hardLinks = {} + , Abstract = require("./abstract.js") + +// Must do this *before* loading the child classes +inherits(Reader, Abstract) + +var DirReader = require("./dir-reader.js") + , FileReader = require("./file-reader.js") + , LinkReader = require("./link-reader.js") + , SocketReader = require("./socket-reader.js") + , ProxyReader = require("./proxy-reader.js") + +function Reader (props, currentStat) { + var me = this + if (!(me instanceof Reader)) return new Reader(props, currentStat) + + if (typeof props === "string") { + props = { path: props } + } + + if (!props.path) { + me.error("Must provide a path", null, true) + } + + // polymorphism. + // call fstream.Reader(dir) to get a DirReader object, etc. + // Note that, unlike in the Writer case, ProxyReader is going + // to be the *normal* state of affairs, since we rarely know + // the type of a file prior to reading it. + + + var type + , ClassType + + if (props.type && typeof props.type === "function") { + type = props.type + ClassType = type + } else { + type = getType(props) + ClassType = Reader + } + + if (currentStat && !type) { + type = getType(currentStat) + props[type] = true + props.type = type + } + + switch (type) { + case "Directory": + ClassType = DirReader + break + + case "Link": + // XXX hard links are just files. + // However, it would be good to keep track of files' dev+inode + // and nlink values, and create a HardLinkReader that emits + // a linkpath value of the original copy, so that the tar + // writer can preserve them. + // ClassType = HardLinkReader + // break + + case "File": + ClassType = FileReader + break + + case "SymbolicLink": + ClassType = LinkReader + break + + case "Socket": + ClassType = SocketReader + break + + case null: + ClassType = ProxyReader + break + } + + if (!(me instanceof ClassType)) { + return new ClassType(props) + } + + Abstract.call(me) + + me.readable = true + me.writable = false + + me.type = type + me.props = props + me.depth = props.depth = props.depth || 0 + me.parent = props.parent || null + me.root = props.root || (props.parent && props.parent.root) || me + + me._path = me.path = path.resolve(props.path) + if (process.platform === "win32") { + me.path = me._path = me.path.replace(/\?/g, "_") + if (me._path.length >= 260) { + // how DOES one create files on the moon? + // if the path has spaces in it, then UNC will fail. + me._swallowErrors = true + //if (me._path.indexOf(" ") === -1) { + me._path = "\\\\?\\" + me.path.replace(/\//g, "\\") + //} + } + } + me.basename = props.basename = path.basename(me.path) + me.dirname = props.dirname = path.dirname(me.path) + + // these have served their purpose, and are now just noisy clutter + props.parent = props.root = null + + // console.error("\n\n\n%s setting size to", props.path, props.size) + me.size = props.size + me.filter = typeof props.filter === "function" ? props.filter : null + if (props.sort === "alpha") props.sort = alphasort + + // start the ball rolling. + // this will stat the thing, and then call me._read() + // to start reading whatever it is. + // console.error("calling stat", props.path, currentStat) + me._stat(currentStat) +} + +function alphasort (a, b) { + return a === b ? 0 + : a.toLowerCase() > b.toLowerCase() ? 1 + : a.toLowerCase() < b.toLowerCase() ? -1 + : a > b ? 1 + : -1 +} + +Reader.prototype._stat = function (currentStat) { + var me = this + , props = me.props + , stat = props.follow ? "stat" : "lstat" + + // console.error("Reader._stat", me._path, currentStat) + if (currentStat) process.nextTick(statCb.bind(null, null, currentStat)) + else fs[stat](me._path, statCb) + + + function statCb (er, props_) { + // console.error("Reader._stat, statCb", me._path, props_, props_.nlink) + if (er) return me.error(er) + + Object.keys(props_).forEach(function (k) { + props[k] = props_[k] + }) + + // if it's not the expected size, then abort here. + if (undefined !== me.size && props.size !== me.size) { + return me.error("incorrect size") + } + me.size = props.size + + var type = getType(props) + // special little thing for handling hardlinks. + if (type !== "Directory" && props.nlink && props.nlink > 1) { + var k = props.dev + ":" + props.ino + // console.error("Reader has nlink", me._path, k) + if (hardLinks[k] === me._path || !hardLinks[k]) hardLinks[k] = me._path + else { + // switch into hardlink mode. + type = me.type = me.props.type = "Link" + me.Link = me.props.Link = true + me.linkpath = me.props.linkpath = hardLinks[k] + // console.error("Hardlink detected, switching mode", me._path, me.linkpath) + // Setting __proto__ would arguably be the "correct" + // approach here, but that just seems too wrong. + me._stat = me._read = LinkReader.prototype._read + } + } + + if (me.type && me.type !== type) { + me.error("Unexpected type: " + type) + } + + // if the filter doesn't pass, then just skip over this one. + // still have to emit end so that dir-walking can move on. + if (me.filter) { + var who = me._proxy || me + // special handling for ProxyReaders + if (!me.filter.call(who, who, props)) { + if (!me._disowned) { + me.abort() + me.emit("end") + me.emit("close") + } + return + } + } + + // last chance to abort or disown before the flow starts! + var events = ["_stat", "stat", "ready"] + var e = 0 + ;(function go () { + if (me._aborted) { + me.emit("end") + me.emit("close") + return + } + + if (me._paused) { + me.once("resume", go) + return + } + + var ev = events[e ++] + if (!ev) return me._read() + me.emit(ev, props) + go() + })() + } +} + +Reader.prototype.pipe = function (dest, opts) { + var me = this + if (typeof dest.add === "function") { + // piping to a multi-compatible, and we've got directory entries. + me.on("entry", function (entry) { + var ret = dest.add(entry) + if (false === ret) { + me.pause() + } + }) + } + + // console.error("R Pipe apply Stream Pipe") + return Stream.prototype.pipe.apply(this, arguments) +} + +Reader.prototype.pause = function (who) { + this._paused = true + who = who || this + this.emit("pause", who) + if (this._stream) this._stream.pause(who) +} + +Reader.prototype.resume = function (who) { + this._paused = false + who = who || this + this.emit("resume", who) + if (this._stream) this._stream.resume(who) + this._read() +} + +Reader.prototype._read = function () { + this.error("Cannot read unknown type: "+this.type) +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/socket-reader.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/socket-reader.js new file mode 100644 index 0000000..1de8ce9 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/socket-reader.js @@ -0,0 +1,38 @@ +// Just get the stats, and then don't do anything. +// You can't really "read" from a socket. You "connect" to it. +// Mostly, this is here so that reading a dir with a socket in it +// doesn't blow up. + +module.exports = SocketReader + +var fs = require("../../graceful-fs/graceful-fs.js") + , fstream = require("../fstream.js") + , inherits = require("../../inherits/inherits.js") + , mkdir = require("../../mkdirp") + , Reader = require("./reader.js") + +inherits(SocketReader, Reader) + +function SocketReader (props) { + var me = this + if (!(me instanceof SocketReader)) throw new Error( + "SocketReader must be called as constructor.") + + if (!(props.type === "Socket" && props.Socket)) { + throw new Error("Non-socket type "+ props.type) + } + + Reader.call(me, props) +} + +SocketReader.prototype._read = function () { + var me = this + if (me._paused) return + // basically just a no-op, since we got all the info we have + // from the _stat method + if (!me._ended) { + me.emit("end") + me.emit("close") + me._ended = true + } +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/writer.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/writer.js new file mode 100644 index 0000000..decc20e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/fstream/lib/writer.js @@ -0,0 +1,389 @@ + +module.exports = Writer + +var fs = require("../../graceful-fs/graceful-fs.js") + , inherits = require("../../inherits/inherits.js") + , rimraf = require("../../rimraf/rimraf.js") + , mkdir = require("../../mkdirp") + , path = require("path") + , umask = process.platform === "win32" ? 0 : process.umask() + , getType = require("./get-type.js") + , Abstract = require("./abstract.js") + +// Must do this *before* loading the child classes +inherits(Writer, Abstract) + +Writer.dirmode = 0777 & (~umask) +Writer.filemode = 0666 & (~umask) + +var DirWriter = require("./dir-writer.js") + , LinkWriter = require("./link-writer.js") + , FileWriter = require("./file-writer.js") + , ProxyWriter = require("./proxy-writer.js") + +// props is the desired state. current is optionally the current stat, +// provided here so that subclasses can avoid statting the target +// more than necessary. +function Writer (props, current) { + var me = this + + if (typeof props === "string") { + props = { path: props } + } + + if (!props.path) me.error("Must provide a path", null, true) + + // polymorphism. + // call fstream.Writer(dir) to get a DirWriter object, etc. + var type = getType(props) + , ClassType = Writer + + switch (type) { + case "Directory": + ClassType = DirWriter + break + case "File": + ClassType = FileWriter + break + case "Link": + case "SymbolicLink": + ClassType = LinkWriter + break + case null: + // Don't know yet what type to create, so we wrap in a proxy. + ClassType = ProxyWriter + break + } + + if (!(me instanceof ClassType)) return new ClassType(props) + + // now get down to business. + + Abstract.call(me) + + // props is what we want to set. + // set some convenience properties as well. + me.type = props.type + me.props = props + me.depth = props.depth || 0 + me.clobber = false === props.clobber ? props.clobber : true + me.parent = props.parent || null + me.root = props.root || (props.parent && props.parent.root) || me + + me._path = me.path = path.resolve(props.path) + if (process.platform === "win32") { + me.path = me._path = me.path.replace(/\?/g, "_") + if (me._path.length >= 260) { + me._swallowErrors = true + me._path = "\\\\?\\" + me.path.replace(/\//g, "\\") + } + } + me.basename = path.basename(props.path) + me.dirname = path.dirname(props.path) + me.linkpath = props.linkpath || null + + props.parent = props.root = null + + // console.error("\n\n\n%s setting size to", props.path, props.size) + me.size = props.size + + if (typeof props.mode === "string") { + props.mode = parseInt(props.mode, 8) + } + + me.readable = false + me.writable = true + + // buffer until ready, or while handling another entry + me._buffer = [] + me.ready = false + + me.filter = typeof props.filter === "function" ? props.filter: null + + // start the ball rolling. + // this checks what's there already, and then calls + // me._create() to call the impl-specific creation stuff. + me._stat(current) +} + +// Calling this means that it's something we can't create. +// Just assert that it's already there, otherwise raise a warning. +Writer.prototype._create = function () { + var me = this + fs[me.props.follow ? "stat" : "lstat"](me._path, function (er, current) { + if (er) { + return me.warn("Cannot create " + me._path + "\n" + + "Unsupported type: "+me.type, "ENOTSUP") + } + me._finish() + }) +} + +Writer.prototype._stat = function (current) { + var me = this + , props = me.props + , stat = props.follow ? "stat" : "lstat" + , who = me._proxy || me + + if (current) statCb(null, current) + else fs[stat](me._path, statCb) + + function statCb (er, current) { + if (me.filter && !me.filter.call(who, who, current)) { + me._aborted = true + me.emit("end") + me.emit("close") + return + } + + // if it's not there, great. We'll just create it. + // if it is there, then we'll need to change whatever differs + if (er || !current) { + return create(me) + } + + me._old = current + var currentType = getType(current) + + // if it's a type change, then we need to clobber or error. + // if it's not a type change, then let the impl take care of it. + if (currentType !== me.type) { + return rimraf(me._path, function (er) { + if (er) return me.error(er) + me._old = null + create(me) + }) + } + + // otherwise, just handle in the app-specific way + // this creates a fs.WriteStream, or mkdir's, or whatever + create(me) + } +} + +function create (me) { + // console.error("W create", me._path, Writer.dirmode) + + // XXX Need to clobber non-dirs that are in the way, + // unless { clobber: false } in the props. + mkdir(path.dirname(me._path), Writer.dirmode, function (er, made) { + // console.error("W created", path.dirname(me._path), er) + if (er) return me.error(er) + + // later on, we have to set the mode and owner for these + me._madeDir = made + return me._create() + }) +} + +function endChmod (me, want, current, path, cb) { + var wantMode = want.mode + , chmod = want.follow || me.type !== "SymbolicLink" + ? "chmod" : "lchmod" + + if (!fs[chmod]) return cb() + if (typeof wantMode !== "number") return cb() + + var curMode = current.mode & 0777 + wantMode = wantMode & 0777 + if (wantMode === curMode) return cb() + + fs[chmod](path, wantMode, cb) +} + + +function endChown (me, want, current, path, cb) { + // Don't even try it unless root. Too easy to EPERM. + if (process.platform === "win32") return cb() + if (!process.getuid || !process.getuid() === 0) return cb() + if (typeof want.uid !== "number" && + typeof want.gid !== "number" ) return cb() + + if (current.uid === want.uid && + current.gid === want.gid) return cb() + + var chown = (me.props.follow || me.type !== "SymbolicLink") + ? "chown" : "lchown" + if (!fs[chown]) return cb() + + if (typeof want.uid !== "number") want.uid = current.uid + if (typeof want.gid !== "number") want.gid = current.gid + + fs[chown](path, want.uid, want.gid, cb) +} + +function endUtimes (me, want, current, path, cb) { + if (!fs.utimes || process.platform === "win32") return cb() + + var utimes = (want.follow || me.type !== "SymbolicLink") + ? "utimes" : "lutimes" + + if (utimes === "lutimes" && !fs[utimes]) { + utimes = "utimes" + } + + if (!fs[utimes]) return cb() + + var curA = current.atime + , curM = current.mtime + , meA = want.atime + , meM = want.mtime + + if (meA === undefined) meA = curA + if (meM === undefined) meM = curM + + if (!isDate(meA)) meA = new Date(meA) + if (!isDate(meM)) meA = new Date(meM) + + if (meA.getTime() === curA.getTime() && + meM.getTime() === curM.getTime()) return cb() + + fs[utimes](path, meA, meM, cb) +} + + +// XXX This function is beastly. Break it up! +Writer.prototype._finish = function () { + var me = this + + // console.error(" W Finish", me._path, me.size) + + // set up all the things. + // At this point, we're already done writing whatever we've gotta write, + // adding files to the dir, etc. + var todo = 0 + var errState = null + var done = false + + if (me._old) { + // the times will almost *certainly* have changed. + // adds the utimes syscall, but remove another stat. + me._old.atime = new Date(0) + me._old.mtime = new Date(0) + // console.error(" W Finish Stale Stat", me._path, me.size) + setProps(me._old) + } else { + var stat = me.props.follow ? "stat" : "lstat" + // console.error(" W Finish Stating", me._path, me.size) + fs[stat](me._path, function (er, current) { + // console.error(" W Finish Stated", me._path, me.size, current) + if (er) { + // if we're in the process of writing out a + // directory, it's very possible that the thing we're linking to + // doesn't exist yet (especially if it was intended as a symlink), + // so swallow ENOENT errors here and just soldier on. + if (er.code === "ENOENT" && + (me.type === "Link" || me.type === "SymbolicLink") && + process.platform === "win32") { + me.ready = true + me.emit("ready") + me.emit("end") + me.emit("close") + me.end = me._finish = function () {} + return + } else return me.error(er) + } + setProps(me._old = current) + }) + } + + return + + function setProps (current) { + endChmod(me, me.props, current, me._path, next("chmod")) + endChown(me, me.props, current, me._path, next("chown")) + endUtimes(me, me.props, current, me._path, next("chown")) + } + + function next (what) { + todo ++ + return function (er) { + // console.error(" W Finish", what, todo) + if (errState) return + if (er) { + er.fstream_finish_call = what + return me.error(errState = er) + } + if (--todo > 0) return + if (done) return + done = true + + // we may still need to set the mode/etc. on some parent dirs + // that were created previously. delay end/close until then. + if (!me._madeDir) return end() + else endMadeDir(me, me._path, end) + + function end (er) { + if (er) { + er.fstream_finish_call = "setupMadeDir" + return me.error(er) + } + // all the props have been set, so we're completely done. + me.emit("end") + me.emit("close") + } + } + } +} + +function endMadeDir (me, p, cb) { + var made = me._madeDir + // everything *between* made and path.dirname(me._path) + // needs to be set up. Note that this may just be one dir. + var d = path.dirname(p) + + endMadeDir_(me, d, function (er) { + if (er) return cb(er) + if (d === made) { + return cb() + } + endMadeDir(me, d, cb) + }) +} + +function endMadeDir_ (me, p, cb) { + var dirProps = {} + Object.keys(me.props).forEach(function (k) { + dirProps[k] = me.props[k] + + // only make non-readable dirs if explicitly requested. + if (k === "mode" && me.type !== "Directory") { + dirProps[k] = dirProps[k] | 0111 + } + }) + + var todo = 3 + , errState = null + fs.stat(p, function (er, current) { + if (er) return cb(errState = er) + endChmod(me, dirProps, current, p, next) + endChown(me, dirProps, current, p, next) + endUtimes(me, dirProps, current, p, next) + }) + + function next (er) { + if (errState) return + if (er) return cb(errState = er) + if (-- todo === 0) return cb() + } +} + +Writer.prototype.pipe = function () { + this.error("Can't pipe from writable stream") +} + +Writer.prototype.add = function () { + this.error("Cannot add to non-Directory type") +} + +Writer.prototype.write = function () { + return true +} + +function objectToString (d) { + return Object.prototype.toString.call(d) +} + +function isDate(d) { + return typeof d === 'object' && objectToString(d) === '[object Date]'; +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/graceful-fs/LICENSE b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/graceful-fs/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/graceful-fs/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The 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. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/graceful-fs/README.md b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/graceful-fs/README.md new file mode 100644 index 0000000..7d2e681 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/graceful-fs/README.md @@ -0,0 +1,5 @@ +Just like node's `fs` module, but it does an incremental back-off when +EMFILE is encountered. + +Useful in asynchronous situations where one needs to try to open lots +and lots of files. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/graceful-fs/graceful-fs.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/graceful-fs/graceful-fs.js new file mode 100644 index 0000000..be9951e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/graceful-fs/graceful-fs.js @@ -0,0 +1,312 @@ +// this keeps a queue of opened file descriptors, and will make +// fs operations wait until some have closed before trying to open more. + +var fs = require("fs") + +// there is such a thing as TOO graceful. +if (fs.open === gracefulOpen) return + +var queue = [] + , constants = require("constants") + +exports = module.exports = fs +fs._curOpen = 0 + +fs.MIN_MAX_OPEN = 64 +fs.MAX_OPEN = 1024 + +var originalOpen = fs.open + , originalOpenSync = fs.openSync + , originalClose = fs.close + , originalCloseSync = fs.closeSync + + +// prevent EMFILE errors +function OpenReq (path, flags, mode, cb) { + this.path = path + this.flags = flags + this.mode = mode + this.cb = cb +} + +function noop () {} + +fs.open = gracefulOpen + +function gracefulOpen (path, flags, mode, cb) { + if (typeof mode === "function") cb = mode, mode = null + if (typeof cb !== "function") cb = noop + + if (fs._curOpen >= fs.MAX_OPEN) { + queue.push(new OpenReq(path, flags, mode, cb)) + setTimeout(flush) + return + } + open(path, flags, mode, function (er, fd) { + if (er && er.code === "EMFILE" && fs._curOpen > fs.MIN_MAX_OPEN) { + // that was too many. reduce max, get back in queue. + // this should only happen once in a great while, and only + // if the ulimit -n is set lower than 1024. + fs.MAX_OPEN = fs._curOpen - 1 + return fs.open(path, flags, mode, cb) + } + cb(er, fd) + }) +} + +function open (path, flags, mode, cb) { + cb = cb || noop + fs._curOpen ++ + originalOpen.call(fs, path, flags, mode, function (er, fd) { + if (er) onclose() + cb(er, fd) + }) +} + +fs.openSync = function (path, flags, mode) { + var ret + ret = originalOpenSync.call(fs, path, flags, mode) + fs._curOpen ++ + return ret +} + +function onclose () { + fs._curOpen -- + flush() +} + +function flush () { + while (fs._curOpen < fs.MAX_OPEN) { + var req = queue.shift() + if (!req) return + open(req.path, req.flags || "r", req.mode || 0777, req.cb) + } +} + +fs.close = function (fd, cb) { + cb = cb || noop + originalClose.call(fs, fd, function (er) { + onclose() + cb(er) + }) +} + +fs.closeSync = function (fd) { + onclose() + return originalCloseSync.call(fs, fd) +} + + +// (re-)implement some things that are known busted or missing. + +var constants = require("constants") + +// lchmod, broken prior to 0.6.2 +// back-port the fix here. +if (constants.hasOwnProperty('O_SYMLINK') && + process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) { + fs.lchmod = function (path, mode, callback) { + callback = callback || noop + fs.open( path + , constants.O_WRONLY | constants.O_SYMLINK + , mode + , function (err, fd) { + if (err) { + callback(err) + return + } + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + fs.fchmod(fd, mode, function (err) { + fs.close(fd, function(err2) { + callback(err || err2) + }) + }) + }) + } + + fs.lchmodSync = function (path, mode) { + var fd = fs.openSync(path, constants.O_WRONLY | constants.O_SYMLINK, mode) + + // prefer to return the chmod error, if one occurs, + // but still try to close, and report closing errors if they occur. + var err, err2 + try { + var ret = fs.fchmodSync(fd, mode) + } catch (er) { + err = er + } + try { + fs.closeSync(fd) + } catch (er) { + err2 = er + } + if (err || err2) throw (err || err2) + return ret + } +} + + +// lutimes implementation, or no-op +if (!fs.lutimes) { + if (constants.hasOwnProperty("O_SYMLINK")) { + fs.lutimes = function (path, at, mt, cb) { + fs.open(path, constants.O_SYMLINK, function (er, fd) { + cb = cb || noop + if (er) return cb(er) + fs.futimes(fd, at, mt, function (er) { + fs.close(fd, function (er2) { + return cb(er || er2) + }) + }) + }) + } + + fs.lutimesSync = function (path, at, mt) { + var fd = fs.openSync(path, constants.O_SYMLINK) + , err + , err2 + , ret + + try { + var ret = fs.futimesSync(fd, at, mt) + } catch (er) { + err = er + } + try { + fs.closeSync(fd) + } catch (er) { + err2 = er + } + if (err || err2) throw (err || err2) + return ret + } + + } else if (fs.utimensat && constants.hasOwnProperty("AT_SYMLINK_NOFOLLOW")) { + // maybe utimensat will be bound soonish? + fs.lutimes = function (path, at, mt, cb) { + fs.utimensat(path, at, mt, constants.AT_SYMLINK_NOFOLLOW, cb) + } + + fs.lutimesSync = function (path, at, mt) { + return fs.utimensatSync(path, at, mt, constants.AT_SYMLINK_NOFOLLOW) + } + + } else { + fs.lutimes = function (_a, _b, _c, cb) { process.nextTick(cb) } + fs.lutimesSync = function () {} + } +} + + +// https://github.com/isaacs/node-graceful-fs/issues/4 +// Chown should not fail on einval or eperm if non-root. + +fs.chown = chownFix(fs.chown) +fs.fchown = chownFix(fs.fchown) +fs.lchown = chownFix(fs.lchown) + +fs.chownSync = chownFixSync(fs.chownSync) +fs.fchownSync = chownFixSync(fs.fchownSync) +fs.lchownSync = chownFixSync(fs.lchownSync) + +function chownFix (orig) { + if (!orig) return orig + return function (target, uid, gid, cb) { + return orig.call(fs, target, uid, gid, function (er, res) { + if (chownErOk(er)) er = null + cb(er, res) + }) + } +} + +function chownFixSync (orig) { + if (!orig) return orig + return function (target, uid, gid) { + try { + return orig.call(fs, target, uid, gid) + } catch (er) { + if (!chownErOk(er)) throw er + } + } +} + +function chownErOk (er) { + // if there's no getuid, or if getuid() is something other than 0, + // and the error is EINVAL or EPERM, then just ignore it. + // This specific case is a silent failure in cp, install, tar, + // and most other unix tools that manage permissions. + // When running as root, or if other types of errors are encountered, + // then it's strict. + if (!er || (!process.getuid || process.getuid() !== 0) + && (er.code === "EINVAL" || er.code === "EPERM")) return true +} + + +// if lchmod/lchown do not exist, then make them no-ops +if (!fs.lchmod) { + fs.lchmod = function (path, mode, cb) { + process.nextTick(cb) + } + fs.lchmodSync = function () {} +} +if (!fs.lchown) { + fs.lchown = function (path, uid, gid, cb) { + process.nextTick(cb) + } + fs.lchownSync = function () {} +} + + + +// on Windows, A/V software can lock the directory, causing this +// to fail with an EACCES or EPERM if the directory contains newly +// created files. Try again on failure, for up to 1 second. +if (process.platform === "win32") { + var rename_ = fs.rename + fs.rename = function rename (from, to, cb) { + var start = Date.now() + rename_(from, to, function CB (er) { + if (er + && (er.code === "EACCES" || er.code === "EPERM") + && Date.now() - start < 1000) { + return rename_(from, to, CB) + } + cb(er) + }) + } +} + + +// if read() returns EAGAIN, then just try it again. +var read = fs.read +fs.read = function (fd, buffer, offset, length, position, callback_) { + var callback + if (callback_ && typeof callback_ === 'function') { + var eagCounter = 0 + callback = function (er, _, __) { + if (er && er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + return read.call(fs, fd, buffer, offset, length, position, callback) + } + callback_.apply(this, arguments) + } + } + return read.call(fs, fd, buffer, offset, length, position, callback) +} + +var readSync = fs.readSync +fs.readSync = function (fd, buffer, offset, length, position) { + var eagCounter = 0 + while (true) { + try { + return readSync.call(fs, fd, buffer, offset, length, position) + } catch (er) { + if (er.code === 'EAGAIN' && eagCounter < 10) { + eagCounter ++ + continue + } + throw er + } + } +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/inherits/README.md b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/inherits/README.md new file mode 100644 index 0000000..b2beaed --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/inherits/README.md @@ -0,0 +1,51 @@ +A dead simple way to do inheritance in JS. + + var inherits = require("inherits") + + function Animal () { + this.alive = true + } + Animal.prototype.say = function (what) { + console.log(what) + } + + inherits(Dog, Animal) + function Dog () { + Dog.super.apply(this) + } + Dog.prototype.sniff = function () { + this.say("sniff sniff") + } + Dog.prototype.bark = function () { + this.say("woof woof") + } + + inherits(Chihuahua, Dog) + function Chihuahua () { + Chihuahua.super.apply(this) + } + Chihuahua.prototype.bark = function () { + this.say("yip yip") + } + + // also works + function Cat () { + Cat.super.apply(this) + } + Cat.prototype.hiss = function () { + this.say("CHSKKSS!!") + } + inherits(Cat, Animal, { + meow: function () { this.say("miao miao") } + }) + Cat.prototype.purr = function () { + this.say("purr purr") + } + + + var c = new Chihuahua + assert(c instanceof Chihuahua) + assert(c instanceof Dog) + assert(c instanceof Animal) + +The actual function is laughably small. 10-lines small. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/inherits/inherits.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/inherits/inherits.js new file mode 100644 index 0000000..061b396 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/inherits/inherits.js @@ -0,0 +1,29 @@ +module.exports = inherits + +function inherits (c, p, proto) { + proto = proto || {} + var e = {} + ;[c.prototype, proto].forEach(function (s) { + Object.getOwnPropertyNames(s).forEach(function (k) { + e[k] = Object.getOwnPropertyDescriptor(s, k) + }) + }) + c.prototype = Object.create(p.prototype, e) + c.super = p +} + +//function Child () { +// Child.super.call(this) +// console.error([this +// ,this.constructor +// ,this.constructor === Child +// ,this.constructor.super === Parent +// ,Object.getPrototypeOf(this) === Child.prototype +// ,Object.getPrototypeOf(Object.getPrototypeOf(this)) +// === Parent.prototype +// ,this instanceof Child +// ,this instanceof Parent]) +//} +//function Parent () {} +//inherits(Child, Parent) +//new Child diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/mkdirp/LICENSE b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/mkdirp/LICENSE new file mode 100644 index 0000000..432d1ae --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/mkdirp/LICENSE @@ -0,0 +1,21 @@ +Copyright 2010 James Halliday (mail@substack.net) + +This project is free software released under the MIT/X11 license: + +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. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/mkdirp/README.markdown b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/mkdirp/README.markdown new file mode 100644 index 0000000..40de04f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/mkdirp/README.markdown @@ -0,0 +1,61 @@ +mkdirp +====== + +Like `mkdir -p`, but in node.js! + +[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp) + +example +======= + +pow.js +------ + var mkdirp = require('mkdirp'); + + mkdirp('/tmp/foo/bar/baz', function (err) { + if (err) console.error(err) + else console.log('pow!') + }); + +Output + pow! + +And now /tmp/foo/bar/baz exists, huzzah! + +methods +======= + +var mkdirp = require('mkdirp'); + +mkdirp(dir, mode, cb) +--------------------- + +Create a new directory and any necessary subdirectories at `dir` with octal +permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +`cb(err, made)` fires with the error or the first directory `made` +that had to be created, if any. + +mkdirp.sync(dir, mode) +---------------------- + +Synchronously create a new directory and any necessary subdirectories at `dir` +with octal permission string `mode`. + +If `mode` isn't specified, it defaults to `0777 & (~process.umask())`. + +Returns the first directory that had to be created, if any. + +install +======= + +With [npm](http://npmjs.org) do: + + npm install mkdirp + +license +======= + +MIT/X11 diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/mkdirp/index.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/mkdirp/index.js new file mode 100644 index 0000000..fda6de8 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/mkdirp/index.js @@ -0,0 +1,82 @@ +var path = require('path'); +var fs = require('fs'); + +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP; + +function mkdirP (p, mode, f, made) { + if (typeof mode === 'function' || mode === undefined) { + f = mode; + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + var cb = f || function () {}; + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + fs.mkdir(p, mode, function (er) { + if (!er) { + made = made || p; + return cb(null, made); + } + switch (er.code) { + case 'ENOENT': + mkdirP(path.dirname(p), mode, function (er, made) { + if (er) cb(er, made); + else mkdirP(p, mode, cb, made); + }); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + fs.stat(p, function (er2, stat) { + // if the stat fails, then that's super weird. + // let the original error be the failure reason. + if (er2 || !stat.isDirectory()) cb(er, made) + else cb(null, made); + }); + break; + } + }); +} + +mkdirP.sync = function sync (p, mode, made) { + if (mode === undefined) { + mode = 0777 & (~process.umask()); + } + if (!made) made = null; + + if (typeof mode === 'string') mode = parseInt(mode, 8); + p = path.resolve(p); + + try { + fs.mkdirSync(p, mode); + made = made || p; + } + catch (err0) { + switch (err0.code) { + case 'ENOENT' : + made = sync(path.dirname(p), mode, made); + sync(p, mode, made); + break; + + // In the case of any other error, just see if there's a dir + // there already. If so, then hooray! If not, then something + // is borked. + default: + var stat; + try { + stat = fs.statSync(p); + } + catch (err1) { + throw err0; + } + if (!stat.isDirectory()) throw err0; + break; + } + } + + return made; +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/AUTHORS b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/AUTHORS new file mode 100644 index 0000000..247b754 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/AUTHORS @@ -0,0 +1,6 @@ +# Authors sorted by whether or not they're me. +Isaac Z. Schlueter (http://blog.izs.me) +Wayne Larsen (http://github.com/wvl) +ritch +Marcel Laverdet +Yosef Dinerstein diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/LICENSE b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The 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. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/README.md b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/README.md new file mode 100644 index 0000000..96ce9b2 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/README.md @@ -0,0 +1,21 @@ +A `rm -rf` for node. + +Install with `npm install rimraf`, or just drop rimraf.js somewhere. + +## API + +`rimraf(f, callback)` + +The callback will be called with an error if there is one. Certain +errors are handled for you: + +* `EBUSY` - rimraf will back off a maximum of opts.maxBusyTries times + before giving up. +* `EMFILE` - If too many file descriptors get opened, rimraf will + patiently wait until more become available. + + +## rimraf.sync + +It can remove stuff synchronously, too. But that's not so good. Use +the async API. It's better. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/rimraf.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/rimraf.js new file mode 100644 index 0000000..bef2e06 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/tar/vendor/rimraf/rimraf.js @@ -0,0 +1,161 @@ +module.exports = rimraf +rimraf.sync = rimrafSync + +var path = require("path") + , fs + +try { + // optional dependency + fs = require("../../graceful-fs/graceful-fs.js") +} catch (er) { + fs = require("fs") +} + +var lstat = "lstat" +if (process.platform === "win32") { + // not reliable on windows prior to 0.7.9 + var v = process.version.replace(/^v/, '').split(/\.|-/).map(Number) + if (v[0] === 0 && (v[1] < 7 || v[1] == 7 && v[2] < 9)) { + lstat = "stat" + } +} +if (!fs[lstat]) lstat = "stat" +var lstatSync = lstat + "Sync" + +// for EMFILE handling +var timeout = 0 +exports.EMFILE_MAX = 1000 +exports.BUSYTRIES_MAX = 3 + +function rimraf (p, cb) { + + if (!cb) throw new Error("No callback passed to rimraf()") + + var busyTries = 0 + + rimraf_(p, function CB (er) { + if (er) { + if (er.code === "EBUSY" && busyTries < exports.BUSYTRIES_MAX) { + busyTries ++ + var time = busyTries * 100 + // try again, with the same exact callback as this one. + return setTimeout(function () { + rimraf_(p, CB) + }, time) + } + + // this one won't happen if graceful-fs is used. + if (er.code === "EMFILE" && timeout < exports.EMFILE_MAX) { + return setTimeout(function () { + rimraf_(p, CB) + }, timeout ++) + } + + // already gone + if (er.code === "ENOENT") er = null + } + + timeout = 0 + cb(er) + }) +} + +function rimraf_ (p, cb) { + fs[lstat](p, function (er, s) { + if (er) { + // already gone + if (er.code === "ENOENT") return cb() + // some other kind of error, permissions, etc. + return cb(er) + } + + return rm_(p, s, false, cb) + }) +} + + +var myGid = function myGid () { + var g = process.getuid && process.getgid() + myGid = function myGid () { return g } + return g +} + +var myUid = function myUid () { + var u = process.getuid && process.getuid() + myUid = function myUid () { return u } + return u +} + + +function writable (s) { + var mode = s.mode || 0777 + , uid = myUid() + , gid = myGid() + return (mode & 0002) + || (gid === s.gid && (mode & 0020)) + || (uid === s.uid && (mode & 0200)) +} + +function rm_ (p, s, didWritableCheck, cb) { + if (!didWritableCheck && !writable(s)) { + // make file writable + // user/group/world, doesn't matter at this point + // since it's about to get nuked. + return fs.chmod(p, s.mode | 0222, function (er) { + if (er) return cb(er) + rm_(p, s, true, cb) + }) + } + + if (!s.isDirectory()) { + return fs.unlink(p, cb) + } + + // directory + fs.readdir(p, function (er, files) { + if (er) return cb(er) + asyncForEach(files.map(function (f) { + return path.join(p, f) + }), function (file, cb) { + rimraf(file, cb) + }, function (er) { + if (er) return cb(er) + fs.rmdir(p, cb) + }) + }) +} + +function asyncForEach (list, fn, cb) { + if (!list.length) cb() + var c = list.length + , errState = null + list.forEach(function (item, i, list) { + fn(item, function (er) { + if (errState) return + if (er) return cb(errState = er) + if (-- c === 0) return cb() + }) + }) +} + +// this looks simpler, but it will fail with big directory trees, +// or on slow stupid awful cygwin filesystems +function rimrafSync (p) { + try { + var s = fs[lstatSync](p) + } catch (er) { + if (er.code === "ENOENT") return + throw er + } + + if (!writable(s)) { + fs.chmodSync(p, s.mode | 0222) + } + + if (!s.isDirectory()) return fs.unlinkSync(p) + + fs.readdirSync(p).forEach(function (f) { + rimrafSync(path.join(p, f)) + }) + fs.rmdirSync(p) +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/underscore/LICENSE b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/underscore/LICENSE new file mode 100644 index 0000000..0d8dbe4 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/underscore/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2009-2013 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. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/underscore/README.md b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/underscore/README.md new file mode 100644 index 0000000..b1f3e50 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/underscore/README.md @@ -0,0 +1,19 @@ + __ + /\ \ __ + __ __ ___ \_\ \ __ _ __ ____ ___ ___ _ __ __ /\_\ ____ + /\ \/\ \ /' _ `\ /'_ \ /'__`\/\ __\/ ,__\ / ___\ / __`\/\ __\/'__`\ \/\ \ /',__\ + \ \ \_\ \/\ \/\ \/\ \ \ \/\ __/\ \ \//\__, `\/\ \__//\ \ \ \ \ \//\ __/ __ \ \ \/\__, `\ + \ \____/\ \_\ \_\ \___,_\ \____\\ \_\\/\____/\ \____\ \____/\ \_\\ \____\/\_\ _\ \ \/\____/ + \/___/ \/_/\/_/\/__,_ /\/____/ \/_/ \/___/ \/____/\/___/ \/_/ \/____/\/_//\ \_\ \/___/ + \ \____/ + \/___/ + +Underscore.js is a utility-belt library for JavaScript that provides +support for the usual functional suspects (each, map, reduce, filter...) +without extending any core JavaScript objects. + +For Docs, License, Tests, and pre-packed downloads, see: +http://underscorejs.org + +Many thanks to our contributors: +https://github.com/documentcloud/underscore/contributors diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/underscore/underscore.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/underscore/underscore.js new file mode 100644 index 0000000..a12f0d9 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/lodash/vendor/underscore/underscore.js @@ -0,0 +1,1226 @@ +// Underscore.js 1.4.4 +// http://underscorejs.org +// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc. +// Underscore may be freely distributed under the MIT license. + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `global` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Establish the object that gets returned to break out of a loop iteration. + var breaker = {}; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + + // Create quick reference variables for speed access to core prototypes. + var push = ArrayProto.push, + slice = ArrayProto.slice, + concat = ArrayProto.concat, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeForEach = ArrayProto.forEach, + nativeMap = ArrayProto.map, + nativeReduce = ArrayProto.reduce, + nativeReduceRight = ArrayProto.reduceRight, + nativeFilter = ArrayProto.filter, + nativeEvery = ArrayProto.every, + nativeSome = ArrayProto.some, + nativeIndexOf = ArrayProto.indexOf, + nativeLastIndexOf = ArrayProto.lastIndexOf, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { + if (obj instanceof _) return obj; + if (!(this instanceof _)) return new _(obj); + this._wrapped = obj; + }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for the old `require()` API. If we're in + // the browser, add `_` as a global object via a string identifier, + // for Closure Compiler "advanced" mode. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root._ = _; + } + + // Current version. + _.VERSION = '1.4.4'; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles objects with the built-in `forEach`, arrays, and raw objects. + // Delegates to **ECMAScript 5**'s native `forEach` if available. + var each = _.each = _.forEach = function(obj, iterator, context) { + if (obj == null) return; + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, l = obj.length; i < l; i++) { + if (iterator.call(context, obj[i], i, obj) === breaker) return; + } + } else { + for (var key in obj) { + if (_.has(obj, key)) { + if (iterator.call(context, obj[key], key, obj) === breaker) return; + } + } + } + }; + + // Return the results of applying the iterator to each element. + // Delegates to **ECMAScript 5**'s native `map` if available. + _.map = _.collect = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + each(obj, function(value, index, list) { + results[results.length] = iterator.call(context, value, index, list); + }); + return results; + }; + + var reduceError = 'Reduce of empty array with no initial value'; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. + _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + // Delegates to **ECMAScript 5**'s native `reduceRight` if available. + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var length = obj.length; + if (length !== +length) { + var keys = _.keys(obj); + length = keys.length; + } + each(obj, function(value, index, list) { + index = keys ? keys[--length] : --length; + if (!initial) { + memo = obj[index]; + initial = true; + } else { + memo = iterator.call(context, memo, obj[index], index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, iterator, context) { + var result; + any(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Delegates to **ECMAScript 5**'s native `filter` if available. + // Aliased as `select`. + _.filter = _.select = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context); + each(obj, function(value, index, list) { + if (iterator.call(context, value, index, list)) results[results.length] = value; + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, iterator, context) { + return _.filter(obj, function(value, index, list) { + return !iterator.call(context, value, index, list); + }, context); + }; + + // Determine whether all of the elements match a truth test. + // Delegates to **ECMAScript 5**'s native `every` if available. + // Aliased as `all`. + _.every = _.all = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context); + each(obj, function(value, index, list) { + if (!(result = result && iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if at least one element in the object matches a truth test. + // Delegates to **ECMAScript 5**'s native `some` if available. + // Aliased as `any`. + var any = _.some = _.any = function(obj, iterator, context) { + iterator || (iterator = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context); + each(obj, function(value, index, list) { + if (result || (result = iterator.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if the array or object contains a given value (using `===`). + // Aliased as `include`. + _.contains = _.include = function(obj, target) { + if (obj == null) return false; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + return any(obj, function(value) { + return value === target; + }); + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + var isFunc = _.isFunction(method); + return _.map(obj, function(value) { + return (isFunc ? method : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, function(value){ return value[key]; }); + }; + + // Convenience version of a common use case of `filter`: selecting only objects + // containing specific `key:value` pairs. + _.where = function(obj, attrs, first) { + if (_.isEmpty(attrs)) return first ? null : []; + return _[first ? 'find' : 'filter'](obj, function(value) { + for (var key in attrs) { + if (attrs[key] !== value[key]) return false; + } + return true; + }); + }; + + // Convenience version of a common use case of `find`: getting the first object + // containing specific `key:value` pairs. + _.findWhere = function(obj, attrs) { + return _.where(obj, attrs, true); + }; + + // Return the maximum element or (element-based computation). + // Can't optimize arrays of integers longer than 65,535 elements. + // See: https://bugs.webkit.org/show_bug.cgi?id=80797 + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.max.apply(Math, obj); + } + if (!iterator && _.isEmpty(obj)) return -Infinity; + var result = {computed : -Infinity, value: -Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed >= result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.min.apply(Math, obj); + } + if (!iterator && _.isEmpty(obj)) return Infinity; + var result = {computed : Infinity, value: Infinity}; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + computed < result.computed && (result = {value : value, computed : computed}); + }); + return result.value; + }; + + // Shuffle an array. + _.shuffle = function(obj) { + var rand; + var index = 0; + var shuffled = []; + each(obj, function(value) { + rand = _.random(index++); + shuffled[index - 1] = shuffled[rand]; + shuffled[rand] = value; + }); + return shuffled; + }; + + // An internal function to generate lookup iterators. + var lookupIterator = function(value) { + return _.isFunction(value) ? value : function(obj){ return obj[value]; }; + }; + + // Sort the object's values by a criterion produced by an iterator. + _.sortBy = function(obj, value, context) { + var iterator = lookupIterator(value); + return _.pluck(_.map(obj, function(value, index, list) { + return { + value : value, + index : index, + criteria : iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index < right.index ? -1 : 1; + }), 'value'); + }; + + // An internal function used for aggregate "group by" operations. + var group = function(obj, value, context, behavior) { + var result = {}; + var iterator = lookupIterator(value || _.identity); + each(obj, function(value, index) { + var key = iterator.call(context, value, index, obj); + behavior(result, key, value); + }); + return result; + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = function(obj, value, context) { + return group(obj, value, context, function(result, key, value) { + (_.has(result, key) ? result[key] : (result[key] = [])).push(value); + }); + }; + + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = function(obj, value, context) { + return group(obj, value, context, function(result, key) { + if (!_.has(result, key)) result[key] = 0; + result[key]++; + }); + }; + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator, context) { + iterator = iterator == null ? _.identity : lookupIterator(iterator); + var value = iterator.call(context, obj); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >>> 1; + iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; + } + return low; + }; + + // Safely convert anything iterable into a real, live array. + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (obj.length === +obj.length) return _.map(obj, _.identity); + return _.values(obj); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + if (obj == null) return 0; + return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { + if (array == null) return void 0; + return (n != null) && !guard ? slice.call(array, 0, n) : array[0]; + }; + + // Returns everything but the last entry of the array. Especially useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if (array == null) return void 0; + if ((n != null) && !guard) { + return slice.call(array, Math.max(array.length - n, 0)); + } else { + return array[array.length - 1]; + } + }; + + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, (n == null) || guard ? 1 : n); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, _.identity); + }; + + // Internal implementation of a recursive `flatten` function. + var flatten = function(input, shallow, output) { + each(input, function(value) { + if (_.isArray(value)) { + shallow ? push.apply(output, value) : flatten(value, shallow, output); + } else { + output.push(value); + } + }); + return output; + }; + + // Return a completely flattened version of an array. + _.flatten = function(array, shallow) { + return flatten(array, shallow, []); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iterator, context) { + if (_.isFunction(isSorted)) { + context = iterator; + iterator = isSorted; + isSorted = false; + } + var initial = iterator ? _.map(array, iterator, context) : array; + var results = []; + var seen = []; + each(initial, function(value, index) { + if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { + seen.push(value); + results.push(array[index]); + } + }); + return results; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(concat.apply(ArrayProto, arguments)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. + _.intersection = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.indexOf(other, item) >= 0; + }); + }); + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.contains(rest, value); }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + var args = slice.call(arguments); + var length = _.max(_.pluck(args, 'length')); + var results = new Array(length); + for (var i = 0; i < length; i++) { + results[i] = _.pluck(args, "" + i); + } + return results; + }; + + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. + _.object = function(list, values) { + if (list == null) return {}; + var result = {}; + for (var i = 0, l = list.length; i < l; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), + // we need this function. Return the position of the first occurrence of an + // item in an array, or -1 if the item is not included in the array. + // Delegates to **ECMAScript 5**'s native `indexOf` if available. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i = 0, l = array.length; + if (isSorted) { + if (typeof isSorted == 'number') { + i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted); + } else { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); + for (; i < l; i++) if (array[i] === item) return i; + return -1; + }; + + // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. + _.lastIndexOf = function(array, item, from) { + if (array == null) return -1; + var hasIndex = from != null; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { + return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); + } + var i = (hasIndex ? from : array.length); + while (i--) if (array[i] === item) return i; + return -1; + }; + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var len = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(len); + + while(idx < len) { + range[idx++] = start; + start += step; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. + _.bind = function(func, context) { + if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + var args = slice.call(arguments, 2); + return function() { + return func.apply(context, args.concat(slice.call(arguments))); + }; + }; + + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. + _.partial = function(func) { + var args = slice.call(arguments, 1); + return function() { + return func.apply(this, args.concat(slice.call(arguments))); + }; + }; + + // Bind all of an object's methods to that object. Useful for ensuring that + // all callbacks defined on an object belong to it. + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length === 0) funcs = _.functions(obj); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ return func.apply(null, args); }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. + _.throttle = function(func, wait) { + var context, args, timeout, result; + var previous = 0; + var later = function() { + previous = new Date; + timeout = null; + result = func.apply(context, args); + }; + return function() { + var now = new Date; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + } else if (!timeout) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var timeout, result; + return function() { + var context = this, args = arguments; + var later = function() { + timeout = null; + if (!immediate) result = func.apply(context, args); + }; + var callNow = immediate && !timeout; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + if (callNow) result = func.apply(context, args); + return result; + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + memo = func.apply(this, arguments); + func = null; + return memo; + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return function() { + var args = [func]; + push.apply(args, arguments); + return wrapper.apply(this, args); + }; + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + if (times <= 0) return func(); + return function() { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = nativeKeys || function(obj) { + if (obj !== Object(obj)) throw new TypeError('Invalid object'); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key; + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + var values = []; + for (var key in obj) if (_.has(obj, key)) values.push(obj[key]); + return values; + }; + + // Convert an object into a list of `[key, value]` pairs. + _.pairs = function(obj) { + var pairs = []; + for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]); + return pairs; + }; + + // Invert the keys and values of an object. The values must be serializable. + _.invert = function(obj) { + var result = {}; + for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key; + return result; + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Return a copy of the object only containing the whitelisted properties. + _.pick = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + each(keys, function(key) { + if (key in obj) copy[key] = obj[key]; + }); + return copy; + }; + + // Return a copy of the object without the blacklisted properties. + _.omit = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + for (var key in obj) { + if (!_.contains(keys, key)) copy[key] = obj[key]; + } + return copy; + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + if (obj[prop] == null) obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Internal recursive comparison function for `isEqual`. + var eq = function(a, b, aStack, bStack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal. + if (a === b) return a !== 0 || 1 / a == 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') return false; + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] == a) return bStack[length] == b; + } + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + if (!(result = eq(a[size], b[size], aStack, bStack))) break; + } + } + } else { + // Objects with different constructors are not equivalent, but `Object`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && + _.isFunction(bCtor) && (bCtor instanceof bCtor))) { + return false; + } + // Deep compare objects. + for (var key in a) { + if (_.has(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (_.has(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + return result; + }; + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b, [], []); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (obj == null) return true; + if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (_.has(obj, key)) return false; + return true; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType === 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) == '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + return obj === Object(obj); + }; + + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. + each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) == '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE), where + // there isn't any inspectable "Arguments" type. + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && _.has(obj, 'callee')); + }; + } + + // Optimize `isFunction` if appropriate. + if (typeof (/./) !== 'function') { + _.isFunction = function(obj) { + return typeof obj === 'function'; + }; + } + + // Is a given object a finite number? + _.isFinite = function(obj) { + return isFinite(obj) && !isNaN(parseFloat(obj)); + }; + + // Is the given value `NaN`? (NaN is the only number which does not equal itself). + _.isNaN = function(obj) { + return _.isNumber(obj) && obj != +obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). + _.has = function(obj, key) { + return hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iterators. + _.identity = function(value) { + return value; + }; + + // Run a function **n** times. + _.times = function(n, iterator, context) { + var accum = Array(n); + for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); + return accum; + }; + + // Return a random integer between min and max (inclusive). + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + Math.floor(Math.random() * (max - min + 1)); + }; + + // List of HTML entities for escaping. + var entityMap = { + escape: { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/' + } + }; + entityMap.unescape = _.invert(entityMap.escape); + + // Regexes containing the keys and values listed immediately above. + var entityRegexes = { + escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), + unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') + }; + + // Functions for escaping and unescaping strings to/from HTML interpolation. + _.each(['escape', 'unescape'], function(method) { + _[method] = function(string) { + if (string == null) return ''; + return ('' + string).replace(entityRegexes[method], function(match) { + return entityMap[method][match]; + }); + }; + }); + + // If the value of the named property is a function then invoke it; + // otherwise, return it. + _.result = function(object, property) { + if (object == null) return null; + var value = object[property]; + return _.isFunction(value) ? value.call(object) : value; + }; + + // Add your own custom functions to the Underscore object. + _.mixin = function(obj) { + each(_.functions(obj), function(name){ + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return result.call(this, func.apply(_, args)); + }; + }); + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /(.)^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\t': 't', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + _.template = function(text, data, settings) { + var render; + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = new RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset) + .replace(escaper, function(match) { return '\\' + escapes[match]; }); + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } + if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } + if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + "return __p;\n"; + + try { + render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + if (data) return render(data, _); + var template = function(data) { + return render.call(this, data, _); + }; + + // Provide the compiled function source as a convenience for precompilation. + template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; + + return template; + }; + + // Add a "chain" function, which will delegate to the wrapper. + _.chain = function(obj) { + return _(obj).chain(); + }; + + // OOP + // --------------- + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + + // Helper function to continue chaining intermediate results. + var result = function(obj) { + return this._chain ? _(obj).chain() : obj; + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; + return result.call(this, obj); + }; + }); + + // Add all accessor Array functions to the wrapper. + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + return result.call(this, method.apply(this._wrapped, arguments)); + }; + }); + + _.extend(_.prototype, { + + // Start chaining a wrapped Underscore object. + chain: function() { + this._chain = true; + return this; + }, + + // Extracts the result from a wrapped and chained object. + value: function() { + return this._wrapped; + } + + }); + +}).call(this); diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/.npmignore b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/LICENSE b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The 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. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/README.md b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/README.md new file mode 100644 index 0000000..978268e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/README.md @@ -0,0 +1,218 @@ +# minimatch + +A minimal matching utility. + +[![Build Status](https://secure.travis-ci.org/isaacs/minimatch.png)](http://travis-ci.org/isaacs/minimatch) + + +This is the matching library used internally by npm. + +Eventually, it will replace the C binding in node-glob. + +It works by converting glob expressions into JavaScript `RegExp` +objects. + +## Usage + +```javascript +var minimatch = require("minimatch") + +minimatch("bar.foo", "*.foo") // true! +minimatch("bar.foo", "*.bar") // false! +minimatch("bar.foo", "*.+(bar|foo)", { debug: true }) // true, and noisy! +``` + +## Features + +Supports these glob features: + +* Brace Expansion +* Extended glob matching +* "Globstar" `**` matching + +See: + +* `man sh` +* `man bash` +* `man 3 fnmatch` +* `man 5 gitignore` + +## Minimatch Class + +Create a minimatch object by instanting the `minimatch.Minimatch` class. + +```javascript +var Minimatch = require("minimatch").Minimatch +var mm = new Minimatch(pattern, options) +``` + +### Properties + +* `pattern` The original pattern the minimatch object represents. +* `options` The options supplied to the constructor. +* `set` A 2-dimensional array of regexp or string expressions. + Each row in the + array corresponds to a brace-expanded pattern. Each item in the row + corresponds to a single path-part. For example, the pattern + `{a,b/c}/d` would expand to a set of patterns like: + + [ [ a, d ] + , [ b, c, d ] ] + + If a portion of the pattern doesn't have any "magic" in it + (that is, it's something like `"foo"` rather than `fo*o?`), then it + will be left as a string rather than converted to a regular + expression. + +* `regexp` Created by the `makeRe` method. A single regular expression + expressing the entire pattern. This is useful in cases where you wish + to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled. +* `negate` True if the pattern is negated. +* `comment` True if the pattern is a comment. +* `empty` True if the pattern is `""`. + +### Methods + +* `makeRe` Generate the `regexp` member if necessary, and return it. + Will return `false` if the pattern is invalid. +* `match(fname)` Return true if the filename matches the pattern, or + false otherwise. +* `matchOne(fileArray, patternArray, partial)` Take a `/`-split + filename, and match it against a single row in the `regExpSet`. This + method is mainly for internal use, but is exposed so that it can be + used by a glob-walker that needs to avoid excessive filesystem calls. + +All other methods are internal, and will be called as necessary. + +## Functions + +The top-level exported function has a `cache` property, which is an LRU +cache set to store 100 items. So, calling these methods repeatedly +with the same pattern and options will use the same Minimatch object, +saving the cost of parsing it multiple times. + +### minimatch(path, pattern, options) + +Main export. Tests a path against the pattern using the options. + +```javascript +var isJS = minimatch(file, "*.js", { matchBase: true }) +``` + +### minimatch.filter(pattern, options) + +Returns a function that tests its +supplied argument, suitable for use with `Array.filter`. Example: + +```javascript +var javascripts = fileList.filter(minimatch.filter("*.js", {matchBase: true})) +``` + +### minimatch.match(list, pattern, options) + +Match against the list of +files, in the style of fnmatch or glob. If nothing is matched, and +options.nonull is set, then return a list containing the pattern itself. + +```javascript +var javascripts = minimatch.match(fileList, "*.js", {matchBase: true})) +``` + +### minimatch.makeRe(pattern, options) + +Make a regular expression object from the pattern. + +## Options + +All options are `false` by default. + +### debug + +Dump a ton of stuff to stderr. + +### nobrace + +Do not expand `{a,b}` and `{1..3}` brace sets. + +### noglobstar + +Disable `**` matching against multiple folder names. + +### dot + +Allow patterns to match filenames starting with a period, even if +the pattern does not explicitly have a period in that spot. + +Note that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot` +is set. + +### noext + +Disable "extglob" style patterns like `+(a|b)`. + +### nocase + +Perform a case-insensitive match. + +### nonull + +When a match is not found by `minimatch.match`, return a list containing +the pattern itself. When set, an empty list is returned if there are +no matches. + +### matchBase + +If set, then patterns without slashes will be matched +against the basename of the path if it contains slashes. For example, +`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`. + +### nocomment + +Suppress the behavior of treating `#` at the start of a pattern as a +comment. + +### nonegate + +Suppress the behavior of treating a leading `!` character as negation. + +### flipNegate + +Returns from negate expressions the same as if they were not negated. +(Ie, true on a hit, false on a miss.) + + +## Comparisons to other fnmatch/glob implementations + +While strict compliance with the existing standards is a worthwhile +goal, some discrepancies exist between minimatch and other +implementations, and are intentional. + +If the pattern starts with a `!` character, then it is negated. Set the +`nonegate` flag to suppress this behavior, and treat leading `!` +characters normally. This is perhaps relevant if you wish to start the +pattern with a negative extglob pattern like `!(a|B)`. Multiple `!` +characters at the start of a pattern will negate the pattern multiple +times. + +If a pattern starts with `#`, then it is treated as a comment, and +will not match anything. Use `\#` to match a literal `#` at the +start of a line, or set the `nocomment` flag to suppress this behavior. + +The double-star character `**` is supported by default, unless the +`noglobstar` flag is set. This is supported in the manner of bsdglob +and bash 4.1, where `**` only has special significance if it is the only +thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but +`a/**b` will not. + +If an escaped pattern has no matches, and the `nonull` flag is set, +then minimatch.match returns the pattern as-provided, rather than +interpreting the character escapes. For example, +`minimatch.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than +`"*a?"`. This is akin to setting the `nullglob` option in bash, except +that it does not resolve escaped pattern characters. + +If brace expansion is not disabled, then it is performed before any +other interpretation of the glob pattern. Thus, a pattern like +`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded +**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are +checked for validity. Since those two are valid, matching proceeds. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/minimatch.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/minimatch.js new file mode 100644 index 0000000..c633f89 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/minimatch.js @@ -0,0 +1,1055 @@ +;(function (require, exports, module, platform) { + +if (module) module.exports = minimatch +else exports.minimatch = minimatch + +if (!require) { + require = function (id) { + switch (id) { + case "sigmund": return function sigmund (obj) { + return JSON.stringify(obj) + } + case "path": return { basename: function (f) { + f = f.split(/[\/\\]/) + var e = f.pop() + if (!e) e = f.pop() + return e + }} + case "lru-cache": return function LRUCache () { + // not quite an LRU, but still space-limited. + var cache = {} + var cnt = 0 + this.set = function (k, v) { + cnt ++ + if (cnt >= 100) cache = {} + cache[k] = v + } + this.get = function (k) { return cache[k] } + } + } + } +} + +minimatch.Minimatch = Minimatch + +var LRU = require("lru-cache") + , cache = minimatch.cache = new LRU({max: 100}) + , GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} + , sigmund = require("sigmund") + +var path = require("path") + // any single thing other than / + // don't need to escape / when using new RegExp() + , qmark = "[^/]" + + // * => any number of characters + , star = qmark + "*?" + + // ** when dots are allowed. Anything goes, except .. and . + // not (^ or / followed by one or two dots followed by $ or /), + // followed by anything, any number of times. + , twoStarDot = "(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?" + + // not a ^ or / followed by a dot, + // followed by anything, any number of times. + , twoStarNoDot = "(?:(?!(?:\\\/|^)\\.).)*?" + + // characters that need to be escaped in RegExp. + , reSpecials = charSet("().*{}+?[]^$\\!") + +// "abc" -> { a:true, b:true, c:true } +function charSet (s) { + return s.split("").reduce(function (set, c) { + set[c] = true + return set + }, {}) +} + +// normalizes slashes. +var slashSplit = /\/+/ + +minimatch.filter = filter +function filter (pattern, options) { + options = options || {} + return function (p, i, list) { + return minimatch(p, pattern, options) + } +} + +function ext (a, b) { + a = a || {} + b = b || {} + var t = {} + Object.keys(b).forEach(function (k) { + t[k] = b[k] + }) + Object.keys(a).forEach(function (k) { + t[k] = a[k] + }) + return t +} + +minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return minimatch + + var orig = minimatch + + var m = function minimatch (p, pattern, options) { + return orig.minimatch(p, pattern, ext(def, options)) + } + + m.Minimatch = function Minimatch (pattern, options) { + return new orig.Minimatch(pattern, ext(def, options)) + } + + return m +} + +Minimatch.defaults = function (def) { + if (!def || !Object.keys(def).length) return Minimatch + return minimatch.defaults(def).Minimatch +} + + +function minimatch (p, pattern, options) { + if (typeof pattern !== "string") { + throw new TypeError("glob pattern string required") + } + + if (!options) options = {} + + // shortcut: comments match nothing. + if (!options.nocomment && pattern.charAt(0) === "#") { + return false + } + + // "" only matches "" + if (pattern.trim() === "") return p === "" + + return new Minimatch(pattern, options).match(p) +} + +function Minimatch (pattern, options) { + if (!(this instanceof Minimatch)) { + return new Minimatch(pattern, options, cache) + } + + if (typeof pattern !== "string") { + throw new TypeError("glob pattern string required") + } + + if (!options) options = {} + pattern = pattern.trim() + + // windows: need to use /, not \ + // On other platforms, \ is a valid (albeit bad) filename char. + if (platform === "win32") { + pattern = pattern.split("\\").join("/") + } + + // lru storage. + // these things aren't particularly big, but walking down the string + // and turning it into a regexp can get pretty costly. + var cacheKey = pattern + "\n" + sigmund(options) + var cached = minimatch.cache.get(cacheKey) + if (cached) return cached + minimatch.cache.set(cacheKey, this) + + this.options = options + this.set = [] + this.pattern = pattern + this.regexp = null + this.negate = false + this.comment = false + this.empty = false + + // make the set of regexps etc. + this.make() +} + +Minimatch.prototype.debug = function() {} + +Minimatch.prototype.make = make +function make () { + // don't do it more than once. + if (this._made) return + + var pattern = this.pattern + var options = this.options + + // empty patterns and comments match nothing. + if (!options.nocomment && pattern.charAt(0) === "#") { + this.comment = true + return + } + if (!pattern) { + this.empty = true + return + } + + // step 1: figure out negation, etc. + this.parseNegate() + + // step 2: expand braces + var set = this.globSet = this.braceExpand() + + if (options.debug) this.debug = console.error + + this.debug(this.pattern, set) + + // step 3: now we have a set, so turn each one into a series of path-portion + // matching patterns. + // These will be regexps, except in the case of "**", which is + // set to the GLOBSTAR object for globstar behavior, + // and will not contain any / characters + set = this.globParts = set.map(function (s) { + return s.split(slashSplit) + }) + + this.debug(this.pattern, set) + + // glob --> regexps + set = set.map(function (s, si, set) { + return s.map(this.parse, this) + }, this) + + this.debug(this.pattern, set) + + // filter out everything that didn't compile properly. + set = set.filter(function (s) { + return -1 === s.indexOf(false) + }) + + this.debug(this.pattern, set) + + this.set = set +} + +Minimatch.prototype.parseNegate = parseNegate +function parseNegate () { + var pattern = this.pattern + , negate = false + , options = this.options + , negateOffset = 0 + + if (options.nonegate) return + + for ( var i = 0, l = pattern.length + ; i < l && pattern.charAt(i) === "!" + ; i ++) { + negate = !negate + negateOffset ++ + } + + if (negateOffset) this.pattern = pattern.substr(negateOffset) + this.negate = negate +} + +// Brace expansion: +// a{b,c}d -> abd acd +// a{b,}c -> abc ac +// a{0..3}d -> a0d a1d a2d a3d +// a{b,c{d,e}f}g -> abg acdfg acefg +// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg +// +// Invalid sets are not expanded. +// a{2..}b -> a{2..}b +// a{b}c -> a{b}c +minimatch.braceExpand = function (pattern, options) { + return new Minimatch(pattern, options).braceExpand() +} + +Minimatch.prototype.braceExpand = braceExpand +function braceExpand (pattern, options) { + options = options || this.options + pattern = typeof pattern === "undefined" + ? this.pattern : pattern + + if (typeof pattern === "undefined") { + throw new Error("undefined pattern") + } + + if (options.nobrace || + !pattern.match(/\{.*\}/)) { + // shortcut. no need to expand. + return [pattern] + } + + var escaping = false + + // examples and comments refer to this crazy pattern: + // a{b,c{d,e},{f,g}h}x{y,z} + // expected: + // abxy + // abxz + // acdxy + // acdxz + // acexy + // acexz + // afhxy + // afhxz + // aghxy + // aghxz + + // everything before the first \{ is just a prefix. + // So, we pluck that off, and work with the rest, + // and then prepend it to everything we find. + if (pattern.charAt(0) !== "{") { + this.debug(pattern) + var prefix = null + for (var i = 0, l = pattern.length; i < l; i ++) { + var c = pattern.charAt(i) + this.debug(i, c) + if (c === "\\") { + escaping = !escaping + } else if (c === "{" && !escaping) { + prefix = pattern.substr(0, i) + break + } + } + + // actually no sets, all { were escaped. + if (prefix === null) { + this.debug("no sets") + return [pattern] + } + + var tail = braceExpand.call(this, pattern.substr(i), options) + return tail.map(function (t) { + return prefix + t + }) + } + + // now we have something like: + // {b,c{d,e},{f,g}h}x{y,z} + // walk through the set, expanding each part, until + // the set ends. then, we'll expand the suffix. + // If the set only has a single member, then'll put the {} back + + // first, handle numeric sets, since they're easier + var numset = pattern.match(/^\{(-?[0-9]+)\.\.(-?[0-9]+)\}/) + if (numset) { + this.debug("numset", numset[1], numset[2]) + var suf = braceExpand.call(this, pattern.substr(numset[0].length), options) + , start = +numset[1] + , end = +numset[2] + , inc = start > end ? -1 : 1 + , set = [] + for (var i = start; i != (end + inc); i += inc) { + // append all the suffixes + for (var ii = 0, ll = suf.length; ii < ll; ii ++) { + set.push(i + suf[ii]) + } + } + return set + } + + // ok, walk through the set + // We hope, somewhat optimistically, that there + // will be a } at the end. + // If the closing brace isn't found, then the pattern is + // interpreted as braceExpand("\\" + pattern) so that + // the leading \{ will be interpreted literally. + var i = 1 // skip the \{ + , depth = 1 + , set = [] + , member = "" + , sawEnd = false + , escaping = false + + function addMember () { + set.push(member) + member = "" + } + + this.debug("Entering for") + FOR: for (i = 1, l = pattern.length; i < l; i ++) { + var c = pattern.charAt(i) + this.debug("", i, c) + + if (escaping) { + escaping = false + member += "\\" + c + } else { + switch (c) { + case "\\": + escaping = true + continue + + case "{": + depth ++ + member += "{" + continue + + case "}": + depth -- + // if this closes the actual set, then we're done + if (depth === 0) { + addMember() + // pluck off the close-brace + i ++ + break FOR + } else { + member += c + continue + } + + case ",": + if (depth === 1) { + addMember() + } else { + member += c + } + continue + + default: + member += c + continue + } // switch + } // else + } // for + + // now we've either finished the set, and the suffix is + // pattern.substr(i), or we have *not* closed the set, + // and need to escape the leading brace + if (depth !== 0) { + this.debug("didn't close", pattern) + return braceExpand.call(this, "\\" + pattern, options) + } + + // x{y,z} -> ["xy", "xz"] + this.debug("set", set) + this.debug("suffix", pattern.substr(i)) + var suf = braceExpand.call(this, pattern.substr(i), options) + // ["b", "c{d,e}","{f,g}h"] -> + // [["b"], ["cd", "ce"], ["fh", "gh"]] + var addBraces = set.length === 1 + this.debug("set pre-expanded", set) + set = set.map(function (p) { + return braceExpand.call(this, p, options) + }, this) + this.debug("set expanded", set) + + + // [["b"], ["cd", "ce"], ["fh", "gh"]] -> + // ["b", "cd", "ce", "fh", "gh"] + set = set.reduce(function (l, r) { + return l.concat(r) + }) + + if (addBraces) { + set = set.map(function (s) { + return "{" + s + "}" + }) + } + + // now attach the suffixes. + var ret = [] + for (var i = 0, l = set.length; i < l; i ++) { + for (var ii = 0, ll = suf.length; ii < ll; ii ++) { + ret.push(set[i] + suf[ii]) + } + } + return ret +} + +// parse a component of the expanded set. +// At this point, no pattern may contain "/" in it +// so we're going to return a 2d array, where each entry is the full +// pattern, split on '/', and then turned into a regular expression. +// A regexp is made at the end which joins each array with an +// escaped /, and another full one which joins each regexp with |. +// +// Following the lead of Bash 4.1, note that "**" only has special meaning +// when it is the *only* thing in a path portion. Otherwise, any series +// of * is equivalent to a single *. Globstar behavior is enabled by +// default, and can be disabled by setting options.noglobstar. +Minimatch.prototype.parse = parse +var SUBPARSE = {} +function parse (pattern, isSub) { + var options = this.options + + // shortcuts + if (!options.noglobstar && pattern === "**") return GLOBSTAR + if (pattern === "") return "" + + var re = "" + , hasMagic = !!options.nocase + , escaping = false + // ? => one single character + , patternListStack = [] + , plType + , stateChar + , inClass = false + , reClassStart = -1 + , classStart = -1 + // . and .. never match anything that doesn't start with ., + // even when options.dot is set. + , patternStart = pattern.charAt(0) === "." ? "" // anything + // not (start or / followed by . or .. followed by / or end) + : options.dot ? "(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))" + : "(?!\\.)" + , self = this + + function clearStateChar () { + if (stateChar) { + // we had some state-tracking character + // that wasn't consumed by this pass. + switch (stateChar) { + case "*": + re += star + hasMagic = true + break + case "?": + re += qmark + hasMagic = true + break + default: + re += "\\"+stateChar + break + } + self.debug('clearStateChar %j %j', stateChar, re) + stateChar = false + } + } + + for ( var i = 0, len = pattern.length, c + ; (i < len) && (c = pattern.charAt(i)) + ; i ++ ) { + + this.debug("%s\t%s %s %j", pattern, i, re, c) + + // skip over any that are escaped. + if (escaping && reSpecials[c]) { + re += "\\" + c + escaping = false + continue + } + + SWITCH: switch (c) { + case "/": + // completely not allowed, even escaped. + // Should already be path-split by now. + return false + + case "\\": + clearStateChar() + escaping = true + continue + + // the various stateChar values + // for the "extglob" stuff. + case "?": + case "*": + case "+": + case "@": + case "!": + this.debug("%s\t%s %s %j <-- stateChar", pattern, i, re, c) + + // all of those are literals inside a class, except that + // the glob [!a] means [^a] in regexp + if (inClass) { + this.debug(' in class') + if (c === "!" && i === classStart + 1) c = "^" + re += c + continue + } + + // if we already have a stateChar, then it means + // that there was something like ** or +? in there. + // Handle the stateChar, then proceed with this one. + self.debug('call clearStateChar %j', stateChar) + clearStateChar() + stateChar = c + // if extglob is disabled, then +(asdf|foo) isn't a thing. + // just clear the statechar *now*, rather than even diving into + // the patternList stuff. + if (options.noext) clearStateChar() + continue + + case "(": + if (inClass) { + re += "(" + continue + } + + if (!stateChar) { + re += "\\(" + continue + } + + plType = stateChar + patternListStack.push({ type: plType + , start: i - 1 + , reStart: re.length }) + // negation is (?:(?!js)[^/]*) + re += stateChar === "!" ? "(?:(?!" : "(?:" + this.debug('plType %j %j', stateChar, re) + stateChar = false + continue + + case ")": + if (inClass || !patternListStack.length) { + re += "\\)" + continue + } + + clearStateChar() + hasMagic = true + re += ")" + plType = patternListStack.pop().type + // negation is (?:(?!js)[^/]*) + // The others are (?:) + switch (plType) { + case "!": + re += "[^/]*?)" + break + case "?": + case "+": + case "*": re += plType + case "@": break // the default anyway + } + continue + + case "|": + if (inClass || !patternListStack.length || escaping) { + re += "\\|" + escaping = false + continue + } + + clearStateChar() + re += "|" + continue + + // these are mostly the same in regexp and glob + case "[": + // swallow any state-tracking char before the [ + clearStateChar() + + if (inClass) { + re += "\\" + c + continue + } + + inClass = true + classStart = i + reClassStart = re.length + re += c + continue + + case "]": + // a right bracket shall lose its special + // meaning and represent itself in + // a bracket expression if it occurs + // first in the list. -- POSIX.2 2.8.3.2 + if (i === classStart + 1 || !inClass) { + re += "\\" + c + escaping = false + continue + } + + // finish up the class. + hasMagic = true + inClass = false + re += c + continue + + default: + // swallow any state char that wasn't consumed + clearStateChar() + + if (escaping) { + // no need + escaping = false + } else if (reSpecials[c] + && !(c === "^" && inClass)) { + re += "\\" + } + + re += c + + } // switch + } // for + + + // handle the case where we left a class open. + // "[abc" is valid, equivalent to "\[abc" + if (inClass) { + // split where the last [ was, and escape it + // this is a huge pita. We now have to re-walk + // the contents of the would-be class to re-translate + // any characters that were passed through as-is + var cs = pattern.substr(classStart + 1) + , sp = this.parse(cs, SUBPARSE) + re = re.substr(0, reClassStart) + "\\[" + sp[0] + hasMagic = hasMagic || sp[1] + } + + // handle the case where we had a +( thing at the *end* + // of the pattern. + // each pattern list stack adds 3 chars, and we need to go through + // and escape any | chars that were passed through as-is for the regexp. + // Go through and escape them, taking care not to double-escape any + // | chars that were already escaped. + var pl + while (pl = patternListStack.pop()) { + var tail = re.slice(pl.reStart + 3) + // maybe some even number of \, then maybe 1 \, followed by a | + tail = tail.replace(/((?:\\{2})*)(\\?)\|/g, function (_, $1, $2) { + if (!$2) { + // the | isn't already escaped, so escape it. + $2 = "\\" + } + + // need to escape all those slashes *again*, without escaping the + // one that we need for escaping the | character. As it works out, + // escaping an even number of slashes can be done by simply repeating + // it exactly after itself. That's why this trick works. + // + // I am sorry that you have to see this. + return $1 + $1 + $2 + "|" + }) + + this.debug("tail=%j\n %s", tail, tail) + var t = pl.type === "*" ? star + : pl.type === "?" ? qmark + : "\\" + pl.type + + hasMagic = true + re = re.slice(0, pl.reStart) + + t + "\\(" + + tail + } + + // handle trailing things that only matter at the very end. + clearStateChar() + if (escaping) { + // trailing \\ + re += "\\\\" + } + + // only need to apply the nodot start if the re starts with + // something that could conceivably capture a dot + var addPatternStart = false + switch (re.charAt(0)) { + case ".": + case "[": + case "(": addPatternStart = true + } + + // if the re is not "" at this point, then we need to make sure + // it doesn't match against an empty path part. + // Otherwise a/* will match a/, which it should not. + if (re !== "" && hasMagic) re = "(?=.)" + re + + if (addPatternStart) re = patternStart + re + + // parsing just a piece of a larger pattern. + if (isSub === SUBPARSE) { + return [ re, hasMagic ] + } + + // skip the regexp for non-magical patterns + // unescape anything in it, though, so that it'll be + // an exact match against a file etc. + if (!hasMagic) { + return globUnescape(pattern) + } + + var flags = options.nocase ? "i" : "" + , regExp = new RegExp("^" + re + "$", flags) + + regExp._glob = pattern + regExp._src = re + + return regExp +} + +minimatch.makeRe = function (pattern, options) { + return new Minimatch(pattern, options || {}).makeRe() +} + +Minimatch.prototype.makeRe = makeRe +function makeRe () { + if (this.regexp || this.regexp === false) return this.regexp + + // at this point, this.set is a 2d array of partial + // pattern strings, or "**". + // + // It's better to use .match(). This function shouldn't + // be used, really, but it's pretty convenient sometimes, + // when you just want to work with a regex. + var set = this.set + + if (!set.length) return this.regexp = false + var options = this.options + + var twoStar = options.noglobstar ? star + : options.dot ? twoStarDot + : twoStarNoDot + , flags = options.nocase ? "i" : "" + + var re = set.map(function (pattern) { + return pattern.map(function (p) { + return (p === GLOBSTAR) ? twoStar + : (typeof p === "string") ? regExpEscape(p) + : p._src + }).join("\\\/") + }).join("|") + + // must match entire pattern + // ending in a * or ** will make it less strict. + re = "^(?:" + re + ")$" + + // can match anything, as long as it's not this. + if (this.negate) re = "^(?!" + re + ").*$" + + try { + return this.regexp = new RegExp(re, flags) + } catch (ex) { + return this.regexp = false + } +} + +minimatch.match = function (list, pattern, options) { + var mm = new Minimatch(pattern, options) + list = list.filter(function (f) { + return mm.match(f) + }) + if (options.nonull && !list.length) { + list.push(pattern) + } + return list +} + +Minimatch.prototype.match = match +function match (f, partial) { + this.debug("match", f, this.pattern) + // short-circuit in the case of busted things. + // comments, etc. + if (this.comment) return false + if (this.empty) return f === "" + + if (f === "/" && partial) return true + + var options = this.options + + // windows: need to use /, not \ + // On other platforms, \ is a valid (albeit bad) filename char. + if (platform === "win32") { + f = f.split("\\").join("/") + } + + // treat the test path as a set of pathparts. + f = f.split(slashSplit) + this.debug(this.pattern, "split", f) + + // just ONE of the pattern sets in this.set needs to match + // in order for it to be valid. If negating, then just one + // match means that we have failed. + // Either way, return on the first hit. + + var set = this.set + this.debug(this.pattern, "set", set) + + var splitFile = path.basename(f.join("/")).split("/") + + for (var i = 0, l = set.length; i < l; i ++) { + var pattern = set[i], file = f + if (options.matchBase && pattern.length === 1) { + file = splitFile + } + var hit = this.matchOne(file, pattern, partial) + if (hit) { + if (options.flipNegate) return true + return !this.negate + } + } + + // didn't get any hits. this is success if it's a negative + // pattern, failure otherwise. + if (options.flipNegate) return false + return this.negate +} + +// set partial to true to test if, for example, +// "/a/b" matches the start of "/*/b/*/d" +// Partial means, if you run out of file before you run +// out of pattern, then that's fine, as long as all +// the parts match. +Minimatch.prototype.matchOne = function (file, pattern, partial) { + var options = this.options + + this.debug("matchOne", + { "this": this + , file: file + , pattern: pattern }) + + this.debug("matchOne", file.length, pattern.length) + + for ( var fi = 0 + , pi = 0 + , fl = file.length + , pl = pattern.length + ; (fi < fl) && (pi < pl) + ; fi ++, pi ++ ) { + + this.debug("matchOne loop") + var p = pattern[pi] + , f = file[fi] + + this.debug(pattern, p, f) + + // should be impossible. + // some invalid regexp stuff in the set. + if (p === false) return false + + if (p === GLOBSTAR) { + this.debug('GLOBSTAR', [pattern, p, f]) + + // "**" + // a/**/b/**/c would match the following: + // a/b/x/y/z/c + // a/x/y/z/b/c + // a/b/x/b/x/c + // a/b/c + // To do this, take the rest of the pattern after + // the **, and see if it would match the file remainder. + // If so, return success. + // If not, the ** "swallows" a segment, and try again. + // This is recursively awful. + // + // a/**/b/**/c matching a/b/x/y/z/c + // - a matches a + // - doublestar + // - matchOne(b/x/y/z/c, b/**/c) + // - b matches b + // - doublestar + // - matchOne(x/y/z/c, c) -> no + // - matchOne(y/z/c, c) -> no + // - matchOne(z/c, c) -> no + // - matchOne(c, c) yes, hit + var fr = fi + , pr = pi + 1 + if (pr === pl) { + this.debug('** at the end') + // a ** at the end will just swallow the rest. + // We have found a match. + // however, it will not swallow /.x, unless + // options.dot is set. + // . and .. are *never* matched by **, for explosively + // exponential reasons. + for ( ; fi < fl; fi ++) { + if (file[fi] === "." || file[fi] === ".." || + (!options.dot && file[fi].charAt(0) === ".")) return false + } + return true + } + + // ok, let's see if we can swallow whatever we can. + WHILE: while (fr < fl) { + var swallowee = file[fr] + + this.debug('\nglobstar while', + file, fr, pattern, pr, swallowee) + + // XXX remove this slice. Just pass the start index. + if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { + this.debug('globstar found match!', fr, fl, swallowee) + // found a match. + return true + } else { + // can't swallow "." or ".." ever. + // can only swallow ".foo" when explicitly asked. + if (swallowee === "." || swallowee === ".." || + (!options.dot && swallowee.charAt(0) === ".")) { + this.debug("dot detected!", file, fr, pattern, pr) + break WHILE + } + + // ** swallows a segment, and continue. + this.debug('globstar swallow a segment, and continue') + fr ++ + } + } + // no match was found. + // However, in partial mode, we can't say this is necessarily over. + // If there's more *pattern* left, then + if (partial) { + // ran out of file + this.debug("\n>>> no match, partial?", file, fr, pattern, pr) + if (fr === fl) return true + } + return false + } + + // something other than ** + // non-magic patterns just have to match exactly + // patterns with magic have been turned into regexps. + var hit + if (typeof p === "string") { + if (options.nocase) { + hit = f.toLowerCase() === p.toLowerCase() + } else { + hit = f === p + } + this.debug("string match", p, f, hit) + } else { + hit = f.match(p) + this.debug("pattern match", p, f, hit) + } + + if (!hit) return false + } + + // Note: ending in / means that we'll get a final "" + // at the end of the pattern. This can only match a + // corresponding "" at the end of the file. + // If the file ends in /, then it can only match a + // a pattern that ends in /, unless the pattern just + // doesn't have any more for it. But, a/b/ should *not* + // match "a/b/*", even though "" matches against the + // [^/]*? pattern, except in partial mode, where it might + // simply not be reached yet. + // However, a/b/ should still satisfy a/* + + // now either we fell off the end of the pattern, or we're done. + if (fi === fl && pi === pl) { + // ran out of pattern and filename at the same time. + // an exact hit! + return true + } else if (fi === fl) { + // ran out of file, but still had pattern left. + // this is ok if we're doing the match as part of + // a glob fs traversal. + return partial + } else if (pi === pl) { + // ran out of pattern, still have file left. + // this is only acceptable if we're on the very last + // empty segment of a file with a trailing slash. + // a/* should match a/b/ + var emptyFileEnd = (fi === fl - 1) && (file[fi] === "") + return emptyFileEnd + } + + // should be unreachable. + throw new Error("wtf?") +} + + +// replace stuff like \* with * +function globUnescape (s) { + return s.replace(/\\(.)/g, "$1") +} + + +function regExpEscape (s) { + return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") +} + +})( typeof require === "function" ? require : null, + this, + typeof module === "object" ? module : null, + typeof process === "object" ? process.platform : "win32" + ) diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/.npmignore b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/.npmignore new file mode 100644 index 0000000..07e6e47 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/.npmignore @@ -0,0 +1 @@ +/node_modules diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/CONTRIBUTORS b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/CONTRIBUTORS new file mode 100644 index 0000000..4a0bc50 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/CONTRIBUTORS @@ -0,0 +1,14 @@ +# Authors, sorted by whether or not they are me +Isaac Z. Schlueter +Brian Cottingham +Carlos Brito Lage +Jesse Dailey +Kevin O'Hara +Marco Rogers +Mark Cavage +Marko Mikulicic +Nathan Rajlich +Satheesh Natesan +Trent Mick +ashleybrener +n4kz diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/LICENSE b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The 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. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/README.md b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/README.md new file mode 100644 index 0000000..03ee0f9 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/README.md @@ -0,0 +1,97 @@ +# lru cache + +A cache object that deletes the least-recently-used items. + +## Usage: + +```javascript +var LRU = require("lru-cache") + , options = { max: 500 + , length: function (n) { return n * 2 } + , dispose: function (key, n) { n.close() } + , maxAge: 1000 * 60 * 60 } + , cache = LRU(options) + , otherCache = LRU(50) // sets just the max size + +cache.set("key", "value") +cache.get("key") // "value" + +cache.reset() // empty the cache +``` + +If you put more stuff in it, then items will fall out. + +If you try to put an oversized thing in it, then it'll fall out right +away. + +## Options + +* `max` The maximum size of the cache, checked by applying the length + function to all values in the cache. Not setting this is kind of + silly, since that's the whole purpose of this lib, but it defaults + to `Infinity`. +* `maxAge` Maximum age in ms. Items are not pro-actively pruned out + as they age, but if you try to get an item that is too old, it'll + drop it and return undefined instead of giving it to you. +* `length` Function that is used to calculate the length of stored + items. If you're storing strings or buffers, then you probably want + to do something like `function(n){return n.length}`. The default is + `function(n){return 1}`, which is fine if you want to store `n` + like-sized things. +* `dispose` Function that is called on items when they are dropped + from the cache. This can be handy if you want to close file + descriptors or do other cleanup tasks when items are no longer + accessible. Called with `key, value`. It's called *before* + actually removing the item from the internal cache, so if you want + to immediately put it back in, you'll have to do that in a + `nextTick` or `setTimeout` callback or it won't do anything. +* `stale` By default, if you set a `maxAge`, it'll only actually pull + stale items out of the cache when you `get(key)`. (That is, it's + not pre-emptively doing a `setTimeout` or anything.) If you set + `stale:true`, it'll return the stale value before deleting it. If + you don't set this, then it'll return `undefined` when you try to + get a stale entry, as if it had already been deleted. + +## API + +* `set(key, value)` +* `get(key) => value` + + Both of these will update the "recently used"-ness of the key. + They do what you think. + +* `peek(key)` + + Returns the key value (or `undefined` if not found) without + updating the "recently used"-ness of the key. + + (If you find yourself using this a lot, you *might* be using the + wrong sort of data structure, but there are some use cases where + it's handy.) + +* `del(key)` + + Deletes a key out of the cache. + +* `reset()` + + Clear the cache entirely, throwing away all values. + +* `has(key)` + + Check if a key is in the cache, without updating the recent-ness + or deleting it for being stale. + +* `forEach(function(value,key,cache), [thisp])` + + Just like `Array.prototype.forEach`. Iterates over all the keys + in the cache, in order of recent-ness. (Ie, more recently used + items are iterated over first.) + +* `keys()` + + Return an array of the keys in the cache. + +* `values()` + + Return an array of the values in the cache. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js new file mode 100644 index 0000000..d1d1381 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/lib/lru-cache.js @@ -0,0 +1,252 @@ +;(function () { // closure for web browsers + +if (typeof module === 'object' && module.exports) { + module.exports = LRUCache +} else { + // just set the global for non-node platforms. + this.LRUCache = LRUCache +} + +function hOP (obj, key) { + return Object.prototype.hasOwnProperty.call(obj, key) +} + +function naiveLength () { return 1 } + +function LRUCache (options) { + if (!(this instanceof LRUCache)) + return new LRUCache(options) + + if (typeof options === 'number') + options = { max: options } + + if (!options) + options = {} + + this._max = options.max + // Kind of weird to have a default max of Infinity, but oh well. + if (!this._max || !(typeof this._max === "number") || this._max <= 0 ) + this._max = Infinity + + this._lengthCalculator = options.length || naiveLength + if (typeof this._lengthCalculator !== "function") + this._lengthCalculator = naiveLength + + this._allowStale = options.stale || false + this._maxAge = options.maxAge || null + this._dispose = options.dispose + this.reset() +} + +// resize the cache when the max changes. +Object.defineProperty(LRUCache.prototype, "max", + { set : function (mL) { + if (!mL || !(typeof mL === "number") || mL <= 0 ) mL = Infinity + this._max = mL + if (this._length > this._max) trim(this) + } + , get : function () { return this._max } + , enumerable : true + }) + +// resize the cache when the lengthCalculator changes. +Object.defineProperty(LRUCache.prototype, "lengthCalculator", + { set : function (lC) { + if (typeof lC !== "function") { + this._lengthCalculator = naiveLength + this._length = this._itemCount + for (var key in this._cache) { + this._cache[key].length = 1 + } + } else { + this._lengthCalculator = lC + this._length = 0 + for (var key in this._cache) { + this._cache[key].length = this._lengthCalculator(this._cache[key].value) + this._length += this._cache[key].length + } + } + + if (this._length > this._max) trim(this) + } + , get : function () { return this._lengthCalculator } + , enumerable : true + }) + +Object.defineProperty(LRUCache.prototype, "length", + { get : function () { return this._length } + , enumerable : true + }) + + +Object.defineProperty(LRUCache.prototype, "itemCount", + { get : function () { return this._itemCount } + , enumerable : true + }) + +LRUCache.prototype.forEach = function (fn, thisp) { + thisp = thisp || this + var i = 0; + for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) { + i++ + var hit = this._lruList[k] + if (this._maxAge && (Date.now() - hit.now > this._maxAge)) { + del(this, hit) + if (!this._allowStale) hit = undefined + } + if (hit) { + fn.call(thisp, hit.value, hit.key, this) + } + } +} + +LRUCache.prototype.keys = function () { + var keys = new Array(this._itemCount) + var i = 0 + for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) { + var hit = this._lruList[k] + keys[i++] = hit.key + } + return keys +} + +LRUCache.prototype.values = function () { + var values = new Array(this._itemCount) + var i = 0 + for (var k = this._mru - 1; k >= 0 && i < this._itemCount; k--) if (this._lruList[k]) { + var hit = this._lruList[k] + values[i++] = hit.value + } + return values +} + +LRUCache.prototype.reset = function () { + if (this._dispose && this._cache) { + for (var k in this._cache) { + this._dispose(k, this._cache[k].value) + } + } + + this._cache = Object.create(null) // hash of items by key + this._lruList = Object.create(null) // list of items in order of use recency + this._mru = 0 // most recently used + this._lru = 0 // least recently used + this._length = 0 // number of items in the list + this._itemCount = 0 +} + +// Provided for debugging/dev purposes only. No promises whatsoever that +// this API stays stable. +LRUCache.prototype.dump = function () { + return this._cache +} + +LRUCache.prototype.dumpLru = function () { + return this._lruList +} + +LRUCache.prototype.set = function (key, value) { + if (hOP(this._cache, key)) { + // dispose of the old one before overwriting + if (this._dispose) this._dispose(key, this._cache[key].value) + if (this._maxAge) this._cache[key].now = Date.now() + this._cache[key].value = value + this.get(key) + return true + } + + var len = this._lengthCalculator(value) + var age = this._maxAge ? Date.now() : 0 + var hit = new Entry(key, value, this._mru++, len, age) + + // oversized objects fall out of cache automatically. + if (hit.length > this._max) { + if (this._dispose) this._dispose(key, value) + return false + } + + this._length += hit.length + this._lruList[hit.lu] = this._cache[key] = hit + this._itemCount ++ + + if (this._length > this._max) trim(this) + return true +} + +LRUCache.prototype.has = function (key) { + if (!hOP(this._cache, key)) return false + var hit = this._cache[key] + if (this._maxAge && (Date.now() - hit.now > this._maxAge)) { + return false + } + return true +} + +LRUCache.prototype.get = function (key) { + return get(this, key, true) +} + +LRUCache.prototype.peek = function (key) { + return get(this, key, false) +} + +LRUCache.prototype.pop = function () { + var hit = this._lruList[this._lru] + del(this, hit) + return hit || null +} + +LRUCache.prototype.del = function (key) { + del(this, this._cache[key]) +} + +function get (self, key, doUse) { + var hit = self._cache[key] + if (hit) { + if (self._maxAge && (Date.now() - hit.now > self._maxAge)) { + del(self, hit) + if (!self._allowStale) hit = undefined + } else { + if (doUse) use(self, hit) + } + if (hit) hit = hit.value + } + return hit +} + +function use (self, hit) { + shiftLU(self, hit) + hit.lu = self._mru ++ + self._lruList[hit.lu] = hit +} + +function trim (self) { + while (self._lru < self._mru && self._length > self._max) + del(self, self._lruList[self._lru]) +} + +function shiftLU (self, hit) { + delete self._lruList[ hit.lu ] + while (self._lru < self._mru && !self._lruList[self._lru]) self._lru ++ +} + +function del (self, hit) { + if (hit) { + if (self._dispose) self._dispose(hit.key, hit.value) + self._length -= hit.length + self._itemCount -- + delete self._cache[ hit.key ] + shiftLU(self, hit) + } +} + +// classy, since V8 prefers predictable objects. +function Entry (key, value, lu, length, now) { + this.key = key + this.value = value + this.lu = lu + this.length = length + this.now = now +} + +})() diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/package.json b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/package.json new file mode 100644 index 0000000..b2a5dbb --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/package.json @@ -0,0 +1,37 @@ +{ + "name": "lru-cache", + "description": "A cache object that deletes the least-recently-used items.", + "version": "2.5.0", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + "scripts": { + "test": "tap test --gc" + }, + "main": "lib/lru-cache.js", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/node-lru-cache.git" + }, + "devDependencies": { + "tap": "", + "weak": "" + }, + "license": { + "type": "MIT", + "url": "http://github.com/isaacs/node-lru-cache/raw/master/LICENSE" + }, + "readme": "# lru cache\n\nA cache object that deletes the least-recently-used items.\n\n## Usage:\n\n```javascript\nvar LRU = require(\"lru-cache\")\n , options = { max: 500\n , length: function (n) { return n * 2 }\n , dispose: function (key, n) { n.close() }\n , maxAge: 1000 * 60 * 60 }\n , cache = LRU(options)\n , otherCache = LRU(50) // sets just the max size\n\ncache.set(\"key\", \"value\")\ncache.get(\"key\") // \"value\"\n\ncache.reset() // empty the cache\n```\n\nIf you put more stuff in it, then items will fall out.\n\nIf you try to put an oversized thing in it, then it'll fall out right\naway.\n\n## Options\n\n* `max` The maximum size of the cache, checked by applying the length\n function to all values in the cache. Not setting this is kind of\n silly, since that's the whole purpose of this lib, but it defaults\n to `Infinity`.\n* `maxAge` Maximum age in ms. Items are not pro-actively pruned out\n as they age, but if you try to get an item that is too old, it'll\n drop it and return undefined instead of giving it to you.\n* `length` Function that is used to calculate the length of stored\n items. If you're storing strings or buffers, then you probably want\n to do something like `function(n){return n.length}`. The default is\n `function(n){return 1}`, which is fine if you want to store `n`\n like-sized things.\n* `dispose` Function that is called on items when they are dropped\n from the cache. This can be handy if you want to close file\n descriptors or do other cleanup tasks when items are no longer\n accessible. Called with `key, value`. It's called *before*\n actually removing the item from the internal cache, so if you want\n to immediately put it back in, you'll have to do that in a\n `nextTick` or `setTimeout` callback or it won't do anything.\n* `stale` By default, if you set a `maxAge`, it'll only actually pull\n stale items out of the cache when you `get(key)`. (That is, it's\n not pre-emptively doing a `setTimeout` or anything.) If you set\n `stale:true`, it'll return the stale value before deleting it. If\n you don't set this, then it'll return `undefined` when you try to\n get a stale entry, as if it had already been deleted.\n\n## API\n\n* `set(key, value)`\n* `get(key) => value`\n\n Both of these will update the \"recently used\"-ness of the key.\n They do what you think.\n\n* `peek(key)`\n\n Returns the key value (or `undefined` if not found) without\n updating the \"recently used\"-ness of the key.\n\n (If you find yourself using this a lot, you *might* be using the\n wrong sort of data structure, but there are some use cases where\n it's handy.)\n\n* `del(key)`\n\n Deletes a key out of the cache.\n\n* `reset()`\n\n Clear the cache entirely, throwing away all values.\n\n* `has(key)`\n\n Check if a key is in the cache, without updating the recent-ness\n or deleting it for being stale.\n\n* `forEach(function(value,key,cache), [thisp])`\n\n Just like `Array.prototype.forEach`. Iterates over all the keys\n in the cache, in order of recent-ness. (Ie, more recently used\n items are iterated over first.)\n\n* `keys()`\n\n Return an array of the keys in the cache.\n\n* `values()`\n\n Return an array of the values in the cache.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/node-lru-cache/issues" + }, + "homepage": "https://github.com/isaacs/node-lru-cache", + "_id": "lru-cache@2.5.0", + "dist": { + "shasum": "8dca6a61e8cb5bbe3a82ac1e2edbdac37fb17842" + }, + "_from": "lru-cache@2", + "_resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/basic.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/basic.js new file mode 100644 index 0000000..f72697c --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/basic.js @@ -0,0 +1,369 @@ +var test = require("tap").test + , LRU = require("../") + +test("basic", function (t) { + var cache = new LRU({max: 10}) + cache.set("key", "value") + t.equal(cache.get("key"), "value") + t.equal(cache.get("nada"), undefined) + t.equal(cache.length, 1) + t.equal(cache.max, 10) + t.end() +}) + +test("least recently set", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), "B") + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("lru recently gotten", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + cache.get("a") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), undefined) + t.equal(cache.get("a"), "A") + t.end() +}) + +test("del", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.del("a") + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("max", function (t) { + var cache = new LRU(3) + + // test changing the max, verify that the LRU items get dropped. + cache.max = 100 + for (var i = 0; i < 100; i ++) cache.set(i, i) + t.equal(cache.length, 100) + for (var i = 0; i < 100; i ++) { + t.equal(cache.get(i), i) + } + cache.max = 3 + t.equal(cache.length, 3) + for (var i = 0; i < 97; i ++) { + t.equal(cache.get(i), undefined) + } + for (var i = 98; i < 100; i ++) { + t.equal(cache.get(i), i) + } + + // now remove the max restriction, and try again. + cache.max = "hello" + for (var i = 0; i < 100; i ++) cache.set(i, i) + t.equal(cache.length, 100) + for (var i = 0; i < 100; i ++) { + t.equal(cache.get(i), i) + } + // should trigger an immediate resize + cache.max = 3 + t.equal(cache.length, 3) + for (var i = 0; i < 97; i ++) { + t.equal(cache.get(i), undefined) + } + for (var i = 98; i < 100; i ++) { + t.equal(cache.get(i), i) + } + t.end() +}) + +test("reset", function (t) { + var cache = new LRU(10) + cache.set("a", "A") + cache.set("b", "B") + cache.reset() + t.equal(cache.length, 0) + t.equal(cache.max, 10) + t.equal(cache.get("a"), undefined) + t.equal(cache.get("b"), undefined) + t.end() +}) + + +// Note: `.dump()` is a debugging tool only. No guarantees are made +// about the format/layout of the response. +test("dump", function (t) { + var cache = new LRU(10) + var d = cache.dump(); + t.equal(Object.keys(d).length, 0, "nothing in dump for empty cache") + cache.set("a", "A") + var d = cache.dump() // { a: { key: "a", value: "A", lu: 0 } } + t.ok(d.a) + t.equal(d.a.key, "a") + t.equal(d.a.value, "A") + t.equal(d.a.lu, 0) + + cache.set("b", "B") + cache.get("b") + d = cache.dump() + t.ok(d.b) + t.equal(d.b.key, "b") + t.equal(d.b.value, "B") + t.equal(d.b.lu, 2) + + t.end() +}) + + +test("basic with weighed length", function (t) { + var cache = new LRU({ + max: 100, + length: function (item) { return item.size } + }) + cache.set("key", {val: "value", size: 50}) + t.equal(cache.get("key").val, "value") + t.equal(cache.get("nada"), undefined) + t.equal(cache.lengthCalculator(cache.get("key")), 50) + t.equal(cache.length, 50) + t.equal(cache.max, 100) + t.end() +}) + + +test("weighed length item too large", function (t) { + var cache = new LRU({ + max: 10, + length: function (item) { return item.size } + }) + t.equal(cache.max, 10) + + // should fall out immediately + cache.set("key", {val: "value", size: 50}) + + t.equal(cache.length, 0) + t.equal(cache.get("key"), undefined) + t.end() +}) + +test("least recently set with weighed length", function (t) { + var cache = new LRU({ + max:8, + length: function (item) { return item.length } + }) + cache.set("a", "A") + cache.set("b", "BB") + cache.set("c", "CCC") + cache.set("d", "DDDD") + t.equal(cache.get("d"), "DDDD") + t.equal(cache.get("c"), "CCC") + t.equal(cache.get("b"), undefined) + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("lru recently gotten with weighed length", function (t) { + var cache = new LRU({ + max: 8, + length: function (item) { return item.length } + }) + cache.set("a", "A") + cache.set("b", "BB") + cache.set("c", "CCC") + cache.get("a") + cache.get("b") + cache.set("d", "DDDD") + t.equal(cache.get("c"), undefined) + t.equal(cache.get("d"), "DDDD") + t.equal(cache.get("b"), "BB") + t.equal(cache.get("a"), "A") + t.end() +}) + +test("set returns proper booleans", function(t) { + var cache = new LRU({ + max: 5, + length: function (item) { return item.length } + }) + + t.equal(cache.set("a", "A"), true) + + // should return false for max exceeded + t.equal(cache.set("b", "donuts"), false) + + t.equal(cache.set("b", "B"), true) + t.equal(cache.set("c", "CCCC"), true) + t.end() +}) + +test("drop the old items", function(t) { + var cache = new LRU({ + max: 5, + maxAge: 50 + }) + + cache.set("a", "A") + + setTimeout(function () { + cache.set("b", "b") + t.equal(cache.get("a"), "A") + }, 25) + + setTimeout(function () { + cache.set("c", "C") + // timed out + t.notOk(cache.get("a")) + }, 60) + + setTimeout(function () { + t.notOk(cache.get("b")) + t.equal(cache.get("c"), "C") + }, 90) + + setTimeout(function () { + t.notOk(cache.get("c")) + t.end() + }, 155) +}) + +test("disposal function", function(t) { + var disposed = false + var cache = new LRU({ + max: 1, + dispose: function (k, n) { + disposed = n + } + }) + + cache.set(1, 1) + cache.set(2, 2) + t.equal(disposed, 1) + cache.set(3, 3) + t.equal(disposed, 2) + cache.reset() + t.equal(disposed, 3) + t.end() +}) + +test("disposal function on too big of item", function(t) { + var disposed = false + var cache = new LRU({ + max: 1, + length: function (k) { + return k.length + }, + dispose: function (k, n) { + disposed = n + } + }) + var obj = [ 1, 2 ] + + t.equal(disposed, false) + cache.set("obj", obj) + t.equal(disposed, obj) + t.end() +}) + +test("has()", function(t) { + var cache = new LRU({ + max: 1, + maxAge: 10 + }) + + cache.set('foo', 'bar') + t.equal(cache.has('foo'), true) + cache.set('blu', 'baz') + t.equal(cache.has('foo'), false) + t.equal(cache.has('blu'), true) + setTimeout(function() { + t.equal(cache.has('blu'), false) + t.end() + }, 15) +}) + +test("stale", function(t) { + var cache = new LRU({ + maxAge: 10, + stale: true + }) + + cache.set('foo', 'bar') + t.equal(cache.get('foo'), 'bar') + t.equal(cache.has('foo'), true) + setTimeout(function() { + t.equal(cache.has('foo'), false) + t.equal(cache.get('foo'), 'bar') + t.equal(cache.get('foo'), undefined) + t.end() + }, 15) +}) + +test("lru update via set", function(t) { + var cache = LRU({ max: 2 }); + + cache.set('foo', 1); + cache.set('bar', 2); + cache.del('bar'); + cache.set('baz', 3); + cache.set('qux', 4); + + t.equal(cache.get('foo'), undefined) + t.equal(cache.get('bar'), undefined) + t.equal(cache.get('baz'), 3) + t.equal(cache.get('qux'), 4) + t.end() +}) + +test("least recently set w/ peek", function (t) { + var cache = new LRU(2) + cache.set("a", "A") + cache.set("b", "B") + t.equal(cache.peek("a"), "A") + cache.set("c", "C") + t.equal(cache.get("c"), "C") + t.equal(cache.get("b"), "B") + t.equal(cache.get("a"), undefined) + t.end() +}) + +test("pop the least used item", function (t) { + var cache = new LRU(3) + , last + + cache.set("a", "A") + cache.set("b", "B") + cache.set("c", "C") + + t.equal(cache.length, 3) + t.equal(cache.max, 3) + + // Ensure we pop a, c, b + cache.get("b", "B") + + last = cache.pop() + t.equal(last.key, "a") + t.equal(last.value, "A") + t.equal(cache.length, 2) + t.equal(cache.max, 3) + + last = cache.pop() + t.equal(last.key, "c") + t.equal(last.value, "C") + t.equal(cache.length, 1) + t.equal(cache.max, 3) + + last = cache.pop() + t.equal(last.key, "b") + t.equal(last.value, "B") + t.equal(cache.length, 0) + t.equal(cache.max, 3) + + last = cache.pop() + t.equal(last, null) + t.equal(cache.length, 0) + t.equal(cache.max, 3) + + t.end() +}) diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/foreach.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/foreach.js new file mode 100644 index 0000000..eefb80d --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/foreach.js @@ -0,0 +1,52 @@ +var test = require('tap').test +var LRU = require('../') + +test('forEach', function (t) { + var l = new LRU(5) + for (var i = 0; i < 10; i ++) { + l.set(i.toString(), i.toString(2)) + } + + var i = 9 + l.forEach(function (val, key, cache) { + t.equal(cache, l) + t.equal(key, i.toString()) + t.equal(val, i.toString(2)) + i -= 1 + }) + + // get in order of most recently used + l.get(6) + l.get(8) + + var order = [ 8, 6, 9, 7, 5 ] + var i = 0 + + l.forEach(function (val, key, cache) { + var j = order[i ++] + t.equal(cache, l) + t.equal(key, j.toString()) + t.equal(val, j.toString(2)) + }) + + t.end() +}) + +test('keys() and values()', function (t) { + var l = new LRU(5) + for (var i = 0; i < 10; i ++) { + l.set(i.toString(), i.toString(2)) + } + + t.similar(l.keys(), ['9', '8', '7', '6', '5']) + t.similar(l.values(), ['1001', '1000', '111', '110', '101']) + + // get in order of most recently used + l.get(6) + l.get(8) + + t.similar(l.keys(), ['8', '6', '9', '7', '5']) + t.similar(l.values(), ['1000', '110', '1001', '111', '101']) + + t.end() +}) diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js new file mode 100644 index 0000000..7af45b0 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/lru-cache/test/memory-leak.js @@ -0,0 +1,50 @@ +#!/usr/bin/env node --expose_gc + +var weak = require('weak'); +var test = require('tap').test +var LRU = require('../') +var l = new LRU({ max: 10 }) +var refs = 0 +function X() { + refs ++ + weak(this, deref) +} + +function deref() { + refs -- +} + +test('no leaks', function (t) { + // fill up the cache + for (var i = 0; i < 100; i++) { + l.set(i, new X); + // throw some gets in there, too. + if (i % 2 === 0) + l.get(i / 2) + } + + gc() + + var start = process.memoryUsage() + + // capture the memory + var startRefs = refs + + // do it again, but more + for (var i = 0; i < 10000; i++) { + l.set(i, new X); + // throw some gets in there, too. + if (i % 2 === 0) + l.get(i / 2) + } + + gc() + + var end = process.memoryUsage() + t.equal(refs, startRefs, 'no leaky refs') + + console.error('start: %j\n' + + 'end: %j', start, end); + t.pass(); + t.end(); +}) diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/LICENSE b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/LICENSE new file mode 100644 index 0000000..0c44ae7 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) Isaac Z. Schlueter ("Author") +All rights reserved. + +The BSD License + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. 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. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/README.md b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/README.md new file mode 100644 index 0000000..7e36512 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/README.md @@ -0,0 +1,53 @@ +# sigmund + +Quick and dirty signatures for Objects. + +This is like a much faster `deepEquals` comparison, which returns a +string key suitable for caches and the like. + +## Usage + +```javascript +function doSomething (someObj) { + var key = sigmund(someObj, maxDepth) // max depth defaults to 10 + var cached = cache.get(key) + if (cached) return cached) + + var result = expensiveCalculation(someObj) + cache.set(key, result) + return result +} +``` + +The resulting key will be as unique and reproducible as calling +`JSON.stringify` or `util.inspect` on the object, but is much faster. +In order to achieve this speed, some differences are glossed over. +For example, the object `{0:'foo'}` will be treated identically to the +array `['foo']`. + +Also, just as there is no way to summon the soul from the scribblings +of a cocain-addled psychoanalyst, there is no way to revive the object +from the signature string that sigmund gives you. In fact, it's +barely even readable. + +As with `sys.inspect` and `JSON.stringify`, larger objects will +produce larger signature strings. + +Because sigmund is a bit less strict than the more thorough +alternatives, the strings will be shorter, and also there is a +slightly higher chance for collisions. For example, these objects +have the same signature: + + var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]} + var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']} + +Like a good Freudian, sigmund is most effective when you already have +some understanding of what you're looking for. It can help you help +yourself, but you must be willing to do some work as well. + +Cycles are handled, and cyclical objects are silently omitted (though +the key is included in the signature output.) + +The second argument is the maximum depth, which defaults to 10, +because that is the maximum object traversal depth covered by most +insurance carriers. diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/bench.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/bench.js new file mode 100644 index 0000000..5acfd6d --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/bench.js @@ -0,0 +1,283 @@ +// different ways to id objects +// use a req/res pair, since it's crazy deep and cyclical + +// sparseFE10 and sigmund are usually pretty close, which is to be expected, +// since they are essentially the same algorithm, except that sigmund handles +// regular expression objects properly. + + +var http = require('http') +var util = require('util') +var sigmund = require('./sigmund.js') +var sreq, sres, creq, cres, test + +http.createServer(function (q, s) { + sreq = q + sres = s + sres.end('ok') + this.close(function () { setTimeout(function () { + start() + }, 200) }) +}).listen(1337, function () { + creq = http.get({ port: 1337 }) + creq.on('response', function (s) { cres = s }) +}) + +function start () { + test = [sreq, sres, creq, cres] + // test = sreq + // sreq.sres = sres + // sreq.creq = creq + // sreq.cres = cres + + for (var i in exports.compare) { + console.log(i) + var hash = exports.compare[i]() + console.log(hash) + console.log(hash.length) + console.log('') + } + + require('bench').runMain() +} + +function customWs (obj, md, d) { + d = d || 0 + var to = typeof obj + if (to === 'undefined' || to === 'function' || to === null) return '' + if (d > md || !obj || to !== 'object') return ('' + obj).replace(/[\n ]+/g, '') + + if (Array.isArray(obj)) { + return obj.map(function (i, _, __) { + return customWs(i, md, d + 1) + }).reduce(function (a, b) { return a + b }, '') + } + + var keys = Object.keys(obj) + return keys.map(function (k, _, __) { + return k + ':' + customWs(obj[k], md, d + 1) + }).reduce(function (a, b) { return a + b }, '') +} + +function custom (obj, md, d) { + d = d || 0 + var to = typeof obj + if (to === 'undefined' || to === 'function' || to === null) return '' + if (d > md || !obj || to !== 'object') return '' + obj + + if (Array.isArray(obj)) { + return obj.map(function (i, _, __) { + return custom(i, md, d + 1) + }).reduce(function (a, b) { return a + b }, '') + } + + var keys = Object.keys(obj) + return keys.map(function (k, _, __) { + return k + ':' + custom(obj[k], md, d + 1) + }).reduce(function (a, b) { return a + b }, '') +} + +function sparseFE2 (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + Object.keys(v).forEach(function (k, _, __) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') return + var to = typeof v[k] + if (to === 'function' || to === 'undefined') return + soFar += k + ':' + ch(v[k], depth + 1) + }) + soFar += '}' + } + ch(obj, 0) + return soFar +} + +function sparseFE (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + Object.keys(v).forEach(function (k, _, __) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') return + var to = typeof v[k] + if (to === 'function' || to === 'undefined') return + soFar += k + ch(v[k], depth + 1) + }) + } + ch(obj, 0) + return soFar +} + +function sparse (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + for (var k in v) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') continue + var to = typeof v[k] + if (to === 'function' || to === 'undefined') continue + soFar += k + ch(v[k], depth + 1) + } + } + ch(obj, 0) + return soFar +} + +function noCommas (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + for (var k in v) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') continue + var to = typeof v[k] + if (to === 'function' || to === 'undefined') continue + soFar += k + ':' + ch(v[k], depth + 1) + } + soFar += '}' + } + ch(obj, 0) + return soFar +} + + +function flatten (obj, maxDepth) { + var seen = [] + var soFar = '' + function ch (v, depth) { + if (depth > maxDepth) return + if (typeof v === 'function' || typeof v === 'undefined') return + if (typeof v !== 'object' || !v) { + soFar += v + return + } + if (seen.indexOf(v) !== -1 || depth === maxDepth) return + seen.push(v) + soFar += '{' + for (var k in v) { + // pseudo-private values. skip those. + if (k.charAt(0) === '_') continue + var to = typeof v[k] + if (to === 'function' || to === 'undefined') continue + soFar += k + ':' + ch(v[k], depth + 1) + soFar += ',' + } + soFar += '}' + } + ch(obj, 0) + return soFar +} + +exports.compare = +{ + // 'custom 2': function () { + // return custom(test, 2, 0) + // }, + // 'customWs 2': function () { + // return customWs(test, 2, 0) + // }, + 'JSON.stringify (guarded)': function () { + var seen = [] + return JSON.stringify(test, function (k, v) { + if (typeof v !== 'object' || !v) return v + if (seen.indexOf(v) !== -1) return undefined + seen.push(v) + return v + }) + }, + + 'flatten 10': function () { + return flatten(test, 10) + }, + + // 'flattenFE 10': function () { + // return flattenFE(test, 10) + // }, + + 'noCommas 10': function () { + return noCommas(test, 10) + }, + + 'sparse 10': function () { + return sparse(test, 10) + }, + + 'sparseFE 10': function () { + return sparseFE(test, 10) + }, + + 'sparseFE2 10': function () { + return sparseFE2(test, 10) + }, + + sigmund: function() { + return sigmund(test, 10) + }, + + + // 'util.inspect 1': function () { + // return util.inspect(test, false, 1, false) + // }, + // 'util.inspect undefined': function () { + // util.inspect(test) + // }, + // 'util.inspect 2': function () { + // util.inspect(test, false, 2, false) + // }, + // 'util.inspect 3': function () { + // util.inspect(test, false, 3, false) + // }, + // 'util.inspect 4': function () { + // util.inspect(test, false, 4, false) + // }, + // 'util.inspect Infinity': function () { + // util.inspect(test, false, Infinity, false) + // } +} + +/** results +**/ diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/package.json b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/package.json new file mode 100644 index 0000000..cb7e2bd --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/package.json @@ -0,0 +1,42 @@ +{ + "name": "sigmund", + "version": "1.0.0", + "description": "Quick and dirty signatures for Objects.", + "main": "sigmund.js", + "directories": { + "test": "test" + }, + "dependencies": {}, + "devDependencies": { + "tap": "~0.3.0" + }, + "scripts": { + "test": "tap test/*.js", + "bench": "node bench.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/isaacs/sigmund" + }, + "keywords": [ + "object", + "signature", + "key", + "data", + "psychoanalysis" + ], + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "license": "BSD", + "readme": "# sigmund\n\nQuick and dirty signatures for Objects.\n\nThis is like a much faster `deepEquals` comparison, which returns a\nstring key suitable for caches and the like.\n\n## Usage\n\n```javascript\nfunction doSomething (someObj) {\n var key = sigmund(someObj, maxDepth) // max depth defaults to 10\n var cached = cache.get(key)\n if (cached) return cached)\n\n var result = expensiveCalculation(someObj)\n cache.set(key, result)\n return result\n}\n```\n\nThe resulting key will be as unique and reproducible as calling\n`JSON.stringify` or `util.inspect` on the object, but is much faster.\nIn order to achieve this speed, some differences are glossed over.\nFor example, the object `{0:'foo'}` will be treated identically to the\narray `['foo']`.\n\nAlso, just as there is no way to summon the soul from the scribblings\nof a cocain-addled psychoanalyst, there is no way to revive the object\nfrom the signature string that sigmund gives you. In fact, it's\nbarely even readable.\n\nAs with `sys.inspect` and `JSON.stringify`, larger objects will\nproduce larger signature strings.\n\nBecause sigmund is a bit less strict than the more thorough\nalternatives, the strings will be shorter, and also there is a\nslightly higher chance for collisions. For example, these objects\nhave the same signature:\n\n var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]}\n var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']}\n\nLike a good Freudian, sigmund is most effective when you already have\nsome understanding of what you're looking for. It can help you help\nyourself, but you must be willing to do some work as well.\n\nCycles are handled, and cyclical objects are silently omitted (though\nthe key is included in the signature output.)\n\nThe second argument is the maximum depth, which defaults to 10,\nbecause that is the maximum object traversal depth covered by most\ninsurance carriers.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/sigmund/issues" + }, + "homepage": "https://github.com/isaacs/sigmund", + "_id": "sigmund@1.0.0", + "_from": "sigmund@~1.0.0" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/sigmund.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/sigmund.js new file mode 100644 index 0000000..82c7ab8 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/sigmund.js @@ -0,0 +1,39 @@ +module.exports = sigmund +function sigmund (subject, maxSessions) { + maxSessions = maxSessions || 10; + var notes = []; + var analysis = ''; + var RE = RegExp; + + function psychoAnalyze (subject, session) { + if (session > maxSessions) return; + + if (typeof subject === 'function' || + typeof subject === 'undefined') { + return; + } + + if (typeof subject !== 'object' || !subject || + (subject instanceof RE)) { + analysis += subject; + return; + } + + if (notes.indexOf(subject) !== -1 || session === maxSessions) return; + + notes.push(subject); + analysis += '{'; + Object.keys(subject).forEach(function (issue, _, __) { + // pseudo-private values. skip those. + if (issue.charAt(0) === '_') return; + var to = typeof subject[issue]; + if (to === 'function' || to === 'undefined') return; + analysis += issue; + psychoAnalyze(subject[issue], session + 1); + }); + } + psychoAnalyze(subject, 0); + return analysis; +} + +// vim: set softtabstop=4 shiftwidth=4: diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/test/basic.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/test/basic.js new file mode 100644 index 0000000..50c53a1 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/node_modules/sigmund/test/basic.js @@ -0,0 +1,24 @@ +var test = require('tap').test +var sigmund = require('../sigmund.js') + + +// occasionally there are duplicates +// that's an acceptable edge-case. JSON.stringify and util.inspect +// have some collision potential as well, though less, and collision +// detection is expensive. +var hash = '{abc/def/g{0h1i2{jkl' +var obj1 = {a:'b',c:/def/,g:['h','i',{j:'',k:'l'}]} +var obj2 = {a:'b',c:'/def/',g:['h','i','{jkl']} + +var obj3 = JSON.parse(JSON.stringify(obj1)) +obj3.c = /def/ +obj3.g[2].cycle = obj3 +var cycleHash = '{abc/def/g{0h1i2{jklcycle' + +test('basic', function (t) { + t.equal(sigmund(obj1), hash) + t.equal(sigmund(obj2), hash) + t.equal(sigmund(obj3), cycleHash) + t.end() +}) + diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/package.json b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/package.json new file mode 100644 index 0000000..18818d3 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/package.json @@ -0,0 +1,44 @@ +{ + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me" + }, + "name": "minimatch", + "description": "a glob matcher in javascript", + "version": "0.2.14", + "repository": { + "type": "git", + "url": "git://github.com/isaacs/minimatch.git" + }, + "main": "minimatch.js", + "scripts": { + "test": "tap test/*.js" + }, + "engines": { + "node": "*" + }, + "dependencies": { + "lru-cache": "2", + "sigmund": "~1.0.0" + }, + "devDependencies": { + "tap": "" + }, + "license": { + "type": "MIT", + "url": "http://github.com/isaacs/minimatch/raw/master/LICENSE" + }, + "readme": "# minimatch\n\nA minimal matching utility.\n\n[![Build Status](https://secure.travis-ci.org/isaacs/minimatch.png)](http://travis-ci.org/isaacs/minimatch)\n\n\nThis is the matching library used internally by npm.\n\nEventually, it will replace the C binding in node-glob.\n\nIt works by converting glob expressions into JavaScript `RegExp`\nobjects.\n\n## Usage\n\n```javascript\nvar minimatch = require(\"minimatch\")\n\nminimatch(\"bar.foo\", \"*.foo\") // true!\nminimatch(\"bar.foo\", \"*.bar\") // false!\nminimatch(\"bar.foo\", \"*.+(bar|foo)\", { debug: true }) // true, and noisy!\n```\n\n## Features\n\nSupports these glob features:\n\n* Brace Expansion\n* Extended glob matching\n* \"Globstar\" `**` matching\n\nSee:\n\n* `man sh`\n* `man bash`\n* `man 3 fnmatch`\n* `man 5 gitignore`\n\n## Minimatch Class\n\nCreate a minimatch object by instanting the `minimatch.Minimatch` class.\n\n```javascript\nvar Minimatch = require(\"minimatch\").Minimatch\nvar mm = new Minimatch(pattern, options)\n```\n\n### Properties\n\n* `pattern` The original pattern the minimatch object represents.\n* `options` The options supplied to the constructor.\n* `set` A 2-dimensional array of regexp or string expressions.\n Each row in the\n array corresponds to a brace-expanded pattern. Each item in the row\n corresponds to a single path-part. For example, the pattern\n `{a,b/c}/d` would expand to a set of patterns like:\n\n [ [ a, d ]\n , [ b, c, d ] ]\n\n If a portion of the pattern doesn't have any \"magic\" in it\n (that is, it's something like `\"foo\"` rather than `fo*o?`), then it\n will be left as a string rather than converted to a regular\n expression.\n\n* `regexp` Created by the `makeRe` method. A single regular expression\n expressing the entire pattern. This is useful in cases where you wish\n to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled.\n* `negate` True if the pattern is negated.\n* `comment` True if the pattern is a comment.\n* `empty` True if the pattern is `\"\"`.\n\n### Methods\n\n* `makeRe` Generate the `regexp` member if necessary, and return it.\n Will return `false` if the pattern is invalid.\n* `match(fname)` Return true if the filename matches the pattern, or\n false otherwise.\n* `matchOne(fileArray, patternArray, partial)` Take a `/`-split\n filename, and match it against a single row in the `regExpSet`. This\n method is mainly for internal use, but is exposed so that it can be\n used by a glob-walker that needs to avoid excessive filesystem calls.\n\nAll other methods are internal, and will be called as necessary.\n\n## Functions\n\nThe top-level exported function has a `cache` property, which is an LRU\ncache set to store 100 items. So, calling these methods repeatedly\nwith the same pattern and options will use the same Minimatch object,\nsaving the cost of parsing it multiple times.\n\n### minimatch(path, pattern, options)\n\nMain export. Tests a path against the pattern using the options.\n\n```javascript\nvar isJS = minimatch(file, \"*.js\", { matchBase: true })\n```\n\n### minimatch.filter(pattern, options)\n\nReturns a function that tests its\nsupplied argument, suitable for use with `Array.filter`. Example:\n\n```javascript\nvar javascripts = fileList.filter(minimatch.filter(\"*.js\", {matchBase: true}))\n```\n\n### minimatch.match(list, pattern, options)\n\nMatch against the list of\nfiles, in the style of fnmatch or glob. If nothing is matched, and\noptions.nonull is set, then return a list containing the pattern itself.\n\n```javascript\nvar javascripts = minimatch.match(fileList, \"*.js\", {matchBase: true}))\n```\n\n### minimatch.makeRe(pattern, options)\n\nMake a regular expression object from the pattern.\n\n## Options\n\nAll options are `false` by default.\n\n### debug\n\nDump a ton of stuff to stderr.\n\n### nobrace\n\nDo not expand `{a,b}` and `{1..3}` brace sets.\n\n### noglobstar\n\nDisable `**` matching against multiple folder names.\n\n### dot\n\nAllow patterns to match filenames starting with a period, even if\nthe pattern does not explicitly have a period in that spot.\n\nNote that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot`\nis set.\n\n### noext\n\nDisable \"extglob\" style patterns like `+(a|b)`.\n\n### nocase\n\nPerform a case-insensitive match.\n\n### nonull\n\nWhen a match is not found by `minimatch.match`, return a list containing\nthe pattern itself. When set, an empty list is returned if there are\nno matches.\n\n### matchBase\n\nIf set, then patterns without slashes will be matched\nagainst the basename of the path if it contains slashes. For example,\n`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.\n\n### nocomment\n\nSuppress the behavior of treating `#` at the start of a pattern as a\ncomment.\n\n### nonegate\n\nSuppress the behavior of treating a leading `!` character as negation.\n\n### flipNegate\n\nReturns from negate expressions the same as if they were not negated.\n(Ie, true on a hit, false on a miss.)\n\n\n## Comparisons to other fnmatch/glob implementations\n\nWhile strict compliance with the existing standards is a worthwhile\ngoal, some discrepancies exist between minimatch and other\nimplementations, and are intentional.\n\nIf the pattern starts with a `!` character, then it is negated. Set the\n`nonegate` flag to suppress this behavior, and treat leading `!`\ncharacters normally. This is perhaps relevant if you wish to start the\npattern with a negative extglob pattern like `!(a|B)`. Multiple `!`\ncharacters at the start of a pattern will negate the pattern multiple\ntimes.\n\nIf a pattern starts with `#`, then it is treated as a comment, and\nwill not match anything. Use `\\#` to match a literal `#` at the\nstart of a line, or set the `nocomment` flag to suppress this behavior.\n\nThe double-star character `**` is supported by default, unless the\n`noglobstar` flag is set. This is supported in the manner of bsdglob\nand bash 4.1, where `**` only has special significance if it is the only\nthing in a path part. That is, `a/**/b` will match `a/x/y/b`, but\n`a/**b` will not.\n\nIf an escaped pattern has no matches, and the `nonull` flag is set,\nthen minimatch.match returns the pattern as-provided, rather than\ninterpreting the character escapes. For example,\n`minimatch.match([], \"\\\\*a\\\\?\")` will return `\"\\\\*a\\\\?\"` rather than\n`\"*a?\"`. This is akin to setting the `nullglob` option in bash, except\nthat it does not resolve escaped pattern characters.\n\nIf brace expansion is not disabled, then it is performed before any\nother interpretation of the glob pattern. Thus, a pattern like\n`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded\n**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are\nchecked for validity. Since those two are valid, matching proceeds.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/minimatch/issues" + }, + "homepage": "https://github.com/isaacs/minimatch", + "_id": "minimatch@0.2.14", + "dist": { + "shasum": "b070e1128a5c8c453cf412786ca4bae5602d069e" + }, + "_from": "minimatch@~0.2.11", + "_resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/basic.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/basic.js new file mode 100644 index 0000000..ae7ac73 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/basic.js @@ -0,0 +1,399 @@ +// http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test +// +// TODO: Some of these tests do very bad things with backslashes, and will +// most likely fail badly on windows. They should probably be skipped. + +var tap = require("tap") + , globalBefore = Object.keys(global) + , mm = require("../") + , files = [ "a", "b", "c", "d", "abc" + , "abd", "abe", "bb", "bcd" + , "ca", "cb", "dd", "de" + , "bdir/", "bdir/cfile"] + , next = files.concat([ "a-b", "aXb" + , ".x", ".y" ]) + + +var patterns = + [ "http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test" + , ["a*", ["a", "abc", "abd", "abe"]] + , ["X*", ["X*"], {nonull: true}] + + // allow null glob expansion + , ["X*", []] + + // isaacs: Slightly different than bash/sh/ksh + // \\* is not un-escaped to literal "*" in a failed match, + // but it does make it get treated as a literal star + , ["\\*", ["\\*"], {nonull: true}] + , ["\\**", ["\\**"], {nonull: true}] + , ["\\*\\*", ["\\*\\*"], {nonull: true}] + + , ["b*/", ["bdir/"]] + , ["c*", ["c", "ca", "cb"]] + , ["**", files] + + , ["\\.\\./*/", ["\\.\\./*/"], {nonull: true}] + , ["s/\\..*//", ["s/\\..*//"], {nonull: true}] + + , "legendary larry crashes bashes" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"], {nonull: true}] + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"], {nonull: true}] + + , "character classes" + , ["[a-c]b*", ["abc", "abd", "abe", "bb", "cb"]] + , ["[a-y]*[^c]", ["abd", "abe", "bb", "bcd", + "bdir/", "ca", "cb", "dd", "de"]] + , ["a*[^c]", ["abd", "abe"]] + , function () { files.push("a-b", "aXb") } + , ["a[X-]b", ["a-b", "aXb"]] + , function () { files.push(".x", ".y") } + , ["[^a-c]*", ["d", "dd", "de"]] + , function () { files.push("a*b/", "a*b/ooo") } + , ["a\\*b/*", ["a*b/ooo"]] + , ["a\\*?/*", ["a*b/ooo"]] + , ["*\\\\!*", [], {null: true}, ["echo !7"]] + , ["*\\!*", ["echo !7"], null, ["echo !7"]] + , ["*.\\*", ["r.*"], null, ["r.*"]] + , ["a[b]c", ["abc"]] + , ["a[\\b]c", ["abc"]] + , ["a?c", ["abc"]] + , ["a\\*c", [], {null: true}, ["abc"]] + , ["", [""], { null: true }, [""]] + + , "http://www.opensource.apple.com/source/bash/bash-23/" + + "bash/tests/glob-test" + , function () { files.push("man/", "man/man1/", "man/man1/bash.1") } + , ["*/man*/bash.*", ["man/man1/bash.1"]] + , ["man/man1/bash.1", ["man/man1/bash.1"]] + , ["a***c", ["abc"], null, ["abc"]] + , ["a*****?c", ["abc"], null, ["abc"]] + , ["?*****??", ["abc"], null, ["abc"]] + , ["*****??", ["abc"], null, ["abc"]] + , ["?*****?c", ["abc"], null, ["abc"]] + , ["?***?****c", ["abc"], null, ["abc"]] + , ["?***?****?", ["abc"], null, ["abc"]] + , ["?***?****", ["abc"], null, ["abc"]] + , ["*******c", ["abc"], null, ["abc"]] + , ["*******?", ["abc"], null, ["abc"]] + , ["a*cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k***", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k**", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a****c**?**??*****", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["[-abc]", ["-"], null, ["-"]] + , ["[abc-]", ["-"], null, ["-"]] + , ["\\", ["\\"], null, ["\\"]] + , ["[\\\\]", ["\\"], null, ["\\"]] + , ["[[]", ["["], null, ["["]] + , ["[", ["["], null, ["["]] + , ["[*", ["[abc"], null, ["[abc"]] + , "a right bracket shall lose its special meaning and\n" + + "represent itself in a bracket expression if it occurs\n" + + "first in the list. -- POSIX.2 2.8.3.2" + , ["[]]", ["]"], null, ["]"]] + , ["[]-]", ["]"], null, ["]"]] + , ["[a-\z]", ["p"], null, ["p"]] + , ["??**********?****?", [], { null: true }, ["abc"]] + , ["??**********?****c", [], { null: true }, ["abc"]] + , ["?************c****?****", [], { null: true }, ["abc"]] + , ["*c*?**", [], { null: true }, ["abc"]] + , ["a*****c*?**", [], { null: true }, ["abc"]] + , ["a********???*******", [], { null: true }, ["abc"]] + , ["[]", [], { null: true }, ["a"]] + , ["[abc", [], { null: true }, ["["]] + + , "nocase tests" + , ["XYZ", ["xYz"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["ab*", ["ABC"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["[ia]?[ck]", ["ABC", "IjK"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + + // [ pattern, [matches], MM opts, files, TAP opts] + , "onestar/twostar" + , ["{/*,*}", [], {null: true}, ["/asdf/asdf/asdf"]] + , ["{/?,*}", ["/a", "bb"], {null: true} + , ["/a", "/b/b", "/a/b/c", "bb"]] + + , "dots should not match unless requested" + , ["**", ["a/b"], {}, ["a/b", "a/.d", ".a/.d"]] + + // .. and . can only match patterns starting with ., + // even when options.dot is set. + , function () { + files = ["a/./b", "a/../b", "a/c/b", "a/.d/b"] + } + , ["a/*/b", ["a/c/b", "a/.d/b"], {dot: true}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: true}] + , ["a/*/b", ["a/c/b"], {dot:false}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: false}] + + + // this also tests that changing the options needs + // to change the cache key, even if the pattern is + // the same! + , ["**", ["a/b","a/.d",".a/.d"], { dot: true } + , [ ".a/.d", "a/.d", "a/b"]] + + , "paren sets cannot contain slashes" + , ["*(a/b)", ["*(a/b)"], {nonull: true}, ["a/b"]] + + // brace sets trump all else. + // + // invalid glob pattern. fails on bash4 and bsdglob. + // however, in this implementation, it's easier just + // to do the intuitive thing, and let brace-expansion + // actually come before parsing any extglob patterns, + // like the documentation seems to say. + // + // XXX: if anyone complains about this, either fix it + // or tell them to grow up and stop complaining. + // + // bash/bsdglob says this: + // , ["*(a|{b),c)}", ["*(a|{b),c)}"], {}, ["a", "ab", "ac", "ad"]] + // but we do this instead: + , ["*(a|{b),c)}", ["a", "ab", "ac"], {}, ["a", "ab", "ac", "ad"]] + + // test partial parsing in the presence of comment/negation chars + , ["[!a*", ["[!ab"], {}, ["[!ab", "[ab"]] + , ["[#a*", ["[#ab"], {}, ["[#ab", "[ab"]] + + // like: {a,b|c\\,d\\\|e} except it's unclosed, so it has to be escaped. + , ["+(a|*\\|c\\\\|d\\\\\\|e\\\\\\\\|f\\\\\\\\\\|g" + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g"] + , {} + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g", "a", "b\\c"]] + + + // crazy nested {,,} and *(||) tests. + , function () { + files = [ "a", "b", "c", "d" + , "ab", "ac", "ad" + , "bc", "cb" + , "bc,d", "c,db", "c,d" + , "d)", "(b|c", "*(b|c" + , "b|c", "b|cc", "cb|c" + , "x(a|b|c)", "x(a|c)" + , "(a|b|c)", "(a|c)"] + } + , ["*(a|{b,c})", ["a", "b", "c", "ab", "ac"]] + , ["{a,*(b|c,d)}", ["a","(b|c", "*(b|c", "d)"]] + // a + // *(b|c) + // *(b|d) + , ["{a,*(b|{c,d})}", ["a","b", "bc", "cb", "c", "d"]] + , ["*(a|{b|c,c})", ["a", "b", "c", "ab", "ac", "bc", "cb"]] + + + // test various flag settings. + , [ "*(a|{b|c,c})", ["x(a|b|c)", "x(a|c)", "(a|b|c)", "(a|c)"] + , { noext: true } ] + , ["a?b", ["x/y/acb", "acb/"], {matchBase: true} + , ["x/y/acb", "acb/", "acb/d/e", "x/y/acb/d"] ] + , ["#*", ["#a", "#b"], {nocomment: true}, ["#a", "#b", "c#d"]] + + + // begin channelling Boole and deMorgan... + , "negation tests" + , function () { + files = ["d", "e", "!ab", "!abc", "a!b", "\\!a"] + } + + // anything that is NOT a* matches. + , ["!a*", ["\\!a", "d", "e", "!ab", "!abc"]] + + // anything that IS !a* matches. + , ["!a*", ["!ab", "!abc"], {nonegate: true}] + + // anything that IS a* matches + , ["!!a*", ["a!b"]] + + // anything that is NOT !a* matches + , ["!\\!a*", ["a!b", "d", "e", "\\!a"]] + + // negation nestled within a pattern + , function () { + files = [ "foo.js" + , "foo.bar" + // can't match this one without negative lookbehind. + , "foo.js.js" + , "blar.js" + , "foo." + , "boo.js.boo" ] + } + , ["*.!(js)", ["foo.bar", "foo.", "boo.js.boo"] ] + + // https://github.com/isaacs/minimatch/issues/5 + , function () { + files = [ 'a/b/.x/c' + , 'a/b/.x/c/d' + , 'a/b/.x/c/d/e' + , 'a/b/.x' + , 'a/b/.x/' + , 'a/.x/b' + , '.x' + , '.x/' + , '.x/a' + , '.x/a/b' + , 'a/.x/b/.x/c' + , '.x/.x' ] + } + , ["**/.x/**", [ '.x/' + , '.x/a' + , '.x/a/b' + , 'a/.x/b' + , 'a/b/.x/' + , 'a/b/.x/c' + , 'a/b/.x/c/d' + , 'a/b/.x/c/d/e' ] ] + + ] + +var regexps = + [ '/^(?:(?=.)a[^/]*?)$/', + '/^(?:(?=.)X[^/]*?)$/', + '/^(?:(?=.)X[^/]*?)$/', + '/^(?:\\*)$/', + '/^(?:(?=.)\\*[^/]*?)$/', + '/^(?:\\*\\*)$/', + '/^(?:(?=.)b[^/]*?\\/)$/', + '/^(?:(?=.)c[^/]*?)$/', + '/^(?:(?:(?!(?:\\/|^)\\.).)*?)$/', + '/^(?:\\.\\.\\/(?!\\.)(?=.)[^/]*?\\/)$/', + '/^(?:s\\/(?=.)\\.\\.[^/]*?\\/)$/', + '/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/1\\/)$/', + '/^(?:\\/\\^root:\\/\\{s\\/(?=.)\\^[^:][^/]*?:[^:][^/]*?:\\([^:]\\)[^/]*?\\.[^/]*?\\$\\/\u0001\\/)$/', + '/^(?:(?!\\.)(?=.)[a-c]b[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[a-y][^/]*?[^c])$/', + '/^(?:(?=.)a[^/]*?[^c])$/', + '/^(?:(?=.)a[X-]b)$/', + '/^(?:(?!\\.)(?=.)[^a-c][^/]*?)$/', + '/^(?:a\\*b\\/(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?=.)a\\*[^/]\\/(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\\\\\![^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\![^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\.\\*)$/', + '/^(?:(?=.)a[b]c)$/', + '/^(?:(?=.)a[b]c)$/', + '/^(?:(?=.)a[^/]c)$/', + '/^(?:a\\*c)$/', + 'false', + '/^(?:(?!\\.)(?=.)[^/]*?\\/(?=.)man[^/]*?\\/(?=.)bash\\.[^/]*?)$/', + '/^(?:man\\/man1\\/bash\\.1)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/])$/', + '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/])$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?!\\.)(?=.)[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/])$/', + '/^(?:(?=.)a[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/]k[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/][^/]*?[^/]*?cd[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?k[^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[-abc])$/', + '/^(?:(?!\\.)(?=.)[abc-])$/', + '/^(?:\\\\)$/', + '/^(?:(?!\\.)(?=.)[\\\\])$/', + '/^(?:(?!\\.)(?=.)[\\[])$/', + '/^(?:\\[)$/', + '/^(?:(?=.)\\[(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[\\]])$/', + '/^(?:(?!\\.)(?=.)[\\]-])$/', + '/^(?:(?!\\.)(?=.)[a-z])$/', + '/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/])$/', + '/^(?:(?!\\.)(?=.)[^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?c)$/', + '/^(?:(?!\\.)(?=.)[^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?c[^/]*?[^/][^/]*?[^/]*?)$/', + '/^(?:(?=.)a[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/][^/][^/][^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?[^/]*?)$/', + '/^(?:\\[\\])$/', + '/^(?:\\[abc)$/', + '/^(?:(?=.)XYZ)$/i', + '/^(?:(?=.)ab[^/]*?)$/i', + '/^(?:(?!\\.)(?=.)[ia][^/][ck])$/i', + '/^(?:\\/(?!\\.)(?=.)[^/]*?|(?!\\.)(?=.)[^/]*?)$/', + '/^(?:\\/(?!\\.)(?=.)[^/]|(?!\\.)(?=.)[^/]*?)$/', + '/^(?:(?:(?!(?:\\/|^)\\.).)*?)$/', + '/^(?:a\\/(?!(?:^|\\/)\\.{1,2}(?:$|\\/))(?=.)[^/]*?\\/b)$/', + '/^(?:a\\/(?=.)\\.[^/]*?\\/b)$/', + '/^(?:a\\/(?!\\.)(?=.)[^/]*?\\/b)$/', + '/^(?:a\\/(?=.)\\.[^/]*?\\/b)$/', + '/^(?:(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\(a\\/b\\))$/', + '/^(?:(?!\\.)(?=.)(?:a|b)*|(?!\\.)(?=.)(?:a|c)*)$/', + '/^(?:(?=.)\\[(?=.)\\!a[^/]*?)$/', + '/^(?:(?=.)\\[(?=.)#a[^/]*?)$/', + '/^(?:(?=.)\\+\\(a\\|[^/]*?\\|c\\\\\\\\\\|d\\\\\\\\\\|e\\\\\\\\\\\\\\\\\\|f\\\\\\\\\\\\\\\\\\|g)$/', + '/^(?:(?!\\.)(?=.)(?:a|b)*|(?!\\.)(?=.)(?:a|c)*)$/', + '/^(?:a|(?!\\.)(?=.)[^/]*?\\(b\\|c|d\\))$/', + '/^(?:a|(?!\\.)(?=.)(?:b|c)*|(?!\\.)(?=.)(?:b|d)*)$/', + '/^(?:(?!\\.)(?=.)(?:a|b|c)*|(?!\\.)(?=.)(?:a|c)*)$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\(a\\|b\\|c\\)|(?!\\.)(?=.)[^/]*?\\(a\\|c\\))$/', + '/^(?:(?=.)a[^/]b)$/', + '/^(?:(?=.)#[^/]*?)$/', + '/^(?!^(?:(?=.)a[^/]*?)$).*$/', + '/^(?:(?=.)\\!a[^/]*?)$/', + '/^(?:(?=.)a[^/]*?)$/', + '/^(?!^(?:(?=.)\\!a[^/]*?)$).*$/', + '/^(?:(?!\\.)(?=.)[^/]*?\\.(?:(?!js)[^/]*?))$/', + '/^(?:(?:(?!(?:\\/|^)\\.).)*?\\/\\.x\\/(?:(?!(?:\\/|^)\\.).)*?)$/' ] +var re = 0; + +tap.test("basic tests", function (t) { + var start = Date.now() + + // [ pattern, [matches], MM opts, files, TAP opts] + patterns.forEach(function (c) { + if (typeof c === "function") return c() + if (typeof c === "string") return t.comment(c) + + var pattern = c[0] + , expect = c[1].sort(alpha) + , options = c[2] || {} + , f = c[3] || files + , tapOpts = c[4] || {} + + // options.debug = true + var m = new mm.Minimatch(pattern, options) + var r = m.makeRe() + var expectRe = regexps[re++] + tapOpts.re = String(r) || JSON.stringify(r) + tapOpts.files = JSON.stringify(f) + tapOpts.pattern = pattern + tapOpts.set = m.set + tapOpts.negated = m.negate + + var actual = mm.match(f, pattern, options) + actual.sort(alpha) + + t.equivalent( actual, expect + , JSON.stringify(pattern) + " " + JSON.stringify(expect) + , tapOpts ) + + t.equal(tapOpts.re, expectRe, tapOpts) + }) + + t.comment("time=" + (Date.now() - start) + "ms") + t.end() +}) + +tap.test("global leak test", function (t) { + var globalAfter = Object.keys(global) + t.equivalent(globalAfter, globalBefore, "no new globals, please") + t.end() +}) + +function alpha (a, b) { + return a > b ? 1 : -1 +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/brace-expand.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/brace-expand.js new file mode 100644 index 0000000..7ee278a --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/brace-expand.js @@ -0,0 +1,33 @@ +var tap = require("tap") + , minimatch = require("../") + +tap.test("brace expansion", function (t) { + // [ pattern, [expanded] ] + ; [ [ "a{b,c{d,e},{f,g}h}x{y,z}" + , [ "abxy" + , "abxz" + , "acdxy" + , "acdxz" + , "acexy" + , "acexz" + , "afhxy" + , "afhxz" + , "aghxy" + , "aghxz" ] ] + , [ "a{1..5}b" + , [ "a1b" + , "a2b" + , "a3b" + , "a4b" + , "a5b" ] ] + , [ "a{b}c", ["a{b}c"] ] + ].forEach(function (tc) { + var p = tc[0] + , expect = tc[1] + t.equivalent(minimatch.braceExpand(p), expect, p) + }) + console.error("ending") + t.end() +}) + + diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/caching.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/caching.js new file mode 100644 index 0000000..0fec4b0 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/caching.js @@ -0,0 +1,14 @@ +var Minimatch = require("../minimatch.js").Minimatch +var tap = require("tap") +tap.test("cache test", function (t) { + var mm1 = new Minimatch("a?b") + var mm2 = new Minimatch("a?b") + t.equal(mm1, mm2, "should get the same object") + // the lru should drop it after 100 entries + for (var i = 0; i < 100; i ++) { + new Minimatch("a"+i) + } + mm2 = new Minimatch("a?b") + t.notEqual(mm1, mm2, "cache should have dropped") + t.end() +}) diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/defaults.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/defaults.js new file mode 100644 index 0000000..25f1f60 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/defaults.js @@ -0,0 +1,274 @@ +// http://www.bashcookbook.com/bashinfo/source/bash-1.14.7/tests/glob-test +// +// TODO: Some of these tests do very bad things with backslashes, and will +// most likely fail badly on windows. They should probably be skipped. + +var tap = require("tap") + , globalBefore = Object.keys(global) + , mm = require("../") + , files = [ "a", "b", "c", "d", "abc" + , "abd", "abe", "bb", "bcd" + , "ca", "cb", "dd", "de" + , "bdir/", "bdir/cfile"] + , next = files.concat([ "a-b", "aXb" + , ".x", ".y" ]) + +tap.test("basic tests", function (t) { + var start = Date.now() + + // [ pattern, [matches], MM opts, files, TAP opts] + ; [ "http://www.bashcookbook.com/bashinfo" + + "/source/bash-1.14.7/tests/glob-test" + , ["a*", ["a", "abc", "abd", "abe"]] + , ["X*", ["X*"], {nonull: true}] + + // allow null glob expansion + , ["X*", []] + + // isaacs: Slightly different than bash/sh/ksh + // \\* is not un-escaped to literal "*" in a failed match, + // but it does make it get treated as a literal star + , ["\\*", ["\\*"], {nonull: true}] + , ["\\**", ["\\**"], {nonull: true}] + , ["\\*\\*", ["\\*\\*"], {nonull: true}] + + , ["b*/", ["bdir/"]] + , ["c*", ["c", "ca", "cb"]] + , ["**", files] + + , ["\\.\\./*/", ["\\.\\./*/"], {nonull: true}] + , ["s/\\..*//", ["s/\\..*//"], {nonull: true}] + + , "legendary larry crashes bashes" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\\1/"], {nonull: true}] + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/" + , ["/^root:/{s/^[^:]*:[^:]*:\([^:]*\).*$/\1/"], {nonull: true}] + + , "character classes" + , ["[a-c]b*", ["abc", "abd", "abe", "bb", "cb"]] + , ["[a-y]*[^c]", ["abd", "abe", "bb", "bcd", + "bdir/", "ca", "cb", "dd", "de"]] + , ["a*[^c]", ["abd", "abe"]] + , function () { files.push("a-b", "aXb") } + , ["a[X-]b", ["a-b", "aXb"]] + , function () { files.push(".x", ".y") } + , ["[^a-c]*", ["d", "dd", "de"]] + , function () { files.push("a*b/", "a*b/ooo") } + , ["a\\*b/*", ["a*b/ooo"]] + , ["a\\*?/*", ["a*b/ooo"]] + , ["*\\\\!*", [], {null: true}, ["echo !7"]] + , ["*\\!*", ["echo !7"], null, ["echo !7"]] + , ["*.\\*", ["r.*"], null, ["r.*"]] + , ["a[b]c", ["abc"]] + , ["a[\\b]c", ["abc"]] + , ["a?c", ["abc"]] + , ["a\\*c", [], {null: true}, ["abc"]] + , ["", [""], { null: true }, [""]] + + , "http://www.opensource.apple.com/source/bash/bash-23/" + + "bash/tests/glob-test" + , function () { files.push("man/", "man/man1/", "man/man1/bash.1") } + , ["*/man*/bash.*", ["man/man1/bash.1"]] + , ["man/man1/bash.1", ["man/man1/bash.1"]] + , ["a***c", ["abc"], null, ["abc"]] + , ["a*****?c", ["abc"], null, ["abc"]] + , ["?*****??", ["abc"], null, ["abc"]] + , ["*****??", ["abc"], null, ["abc"]] + , ["?*****?c", ["abc"], null, ["abc"]] + , ["?***?****c", ["abc"], null, ["abc"]] + , ["?***?****?", ["abc"], null, ["abc"]] + , ["?***?****", ["abc"], null, ["abc"]] + , ["*******c", ["abc"], null, ["abc"]] + , ["*******?", ["abc"], null, ["abc"]] + , ["a*cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??k***", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a**?**cd**?**??***k**", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["a****c**?**??*****", ["abcdecdhjk"], null, ["abcdecdhjk"]] + , ["[-abc]", ["-"], null, ["-"]] + , ["[abc-]", ["-"], null, ["-"]] + , ["\\", ["\\"], null, ["\\"]] + , ["[\\\\]", ["\\"], null, ["\\"]] + , ["[[]", ["["], null, ["["]] + , ["[", ["["], null, ["["]] + , ["[*", ["[abc"], null, ["[abc"]] + , "a right bracket shall lose its special meaning and\n" + + "represent itself in a bracket expression if it occurs\n" + + "first in the list. -- POSIX.2 2.8.3.2" + , ["[]]", ["]"], null, ["]"]] + , ["[]-]", ["]"], null, ["]"]] + , ["[a-\z]", ["p"], null, ["p"]] + , ["??**********?****?", [], { null: true }, ["abc"]] + , ["??**********?****c", [], { null: true }, ["abc"]] + , ["?************c****?****", [], { null: true }, ["abc"]] + , ["*c*?**", [], { null: true }, ["abc"]] + , ["a*****c*?**", [], { null: true }, ["abc"]] + , ["a********???*******", [], { null: true }, ["abc"]] + , ["[]", [], { null: true }, ["a"]] + , ["[abc", [], { null: true }, ["["]] + + , "nocase tests" + , ["XYZ", ["xYz"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["ab*", ["ABC"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + , ["[ia]?[ck]", ["ABC", "IjK"], { nocase: true, null: true } + , ["xYz", "ABC", "IjK"]] + + // [ pattern, [matches], MM opts, files, TAP opts] + , "onestar/twostar" + , ["{/*,*}", [], {null: true}, ["/asdf/asdf/asdf"]] + , ["{/?,*}", ["/a", "bb"], {null: true} + , ["/a", "/b/b", "/a/b/c", "bb"]] + + , "dots should not match unless requested" + , ["**", ["a/b"], {}, ["a/b", "a/.d", ".a/.d"]] + + // .. and . can only match patterns starting with ., + // even when options.dot is set. + , function () { + files = ["a/./b", "a/../b", "a/c/b", "a/.d/b"] + } + , ["a/*/b", ["a/c/b", "a/.d/b"], {dot: true}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: true}] + , ["a/*/b", ["a/c/b"], {dot:false}] + , ["a/.*/b", ["a/./b", "a/../b", "a/.d/b"], {dot: false}] + + + // this also tests that changing the options needs + // to change the cache key, even if the pattern is + // the same! + , ["**", ["a/b","a/.d",".a/.d"], { dot: true } + , [ ".a/.d", "a/.d", "a/b"]] + + , "paren sets cannot contain slashes" + , ["*(a/b)", ["*(a/b)"], {nonull: true}, ["a/b"]] + + // brace sets trump all else. + // + // invalid glob pattern. fails on bash4 and bsdglob. + // however, in this implementation, it's easier just + // to do the intuitive thing, and let brace-expansion + // actually come before parsing any extglob patterns, + // like the documentation seems to say. + // + // XXX: if anyone complains about this, either fix it + // or tell them to grow up and stop complaining. + // + // bash/bsdglob says this: + // , ["*(a|{b),c)}", ["*(a|{b),c)}"], {}, ["a", "ab", "ac", "ad"]] + // but we do this instead: + , ["*(a|{b),c)}", ["a", "ab", "ac"], {}, ["a", "ab", "ac", "ad"]] + + // test partial parsing in the presence of comment/negation chars + , ["[!a*", ["[!ab"], {}, ["[!ab", "[ab"]] + , ["[#a*", ["[#ab"], {}, ["[#ab", "[ab"]] + + // like: {a,b|c\\,d\\\|e} except it's unclosed, so it has to be escaped. + , ["+(a|*\\|c\\\\|d\\\\\\|e\\\\\\\\|f\\\\\\\\\\|g" + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g"] + , {} + , ["+(a|b\\|c\\\\|d\\\\|e\\\\\\\\|f\\\\\\\\|g", "a", "b\\c"]] + + + // crazy nested {,,} and *(||) tests. + , function () { + files = [ "a", "b", "c", "d" + , "ab", "ac", "ad" + , "bc", "cb" + , "bc,d", "c,db", "c,d" + , "d)", "(b|c", "*(b|c" + , "b|c", "b|cc", "cb|c" + , "x(a|b|c)", "x(a|c)" + , "(a|b|c)", "(a|c)"] + } + , ["*(a|{b,c})", ["a", "b", "c", "ab", "ac"]] + , ["{a,*(b|c,d)}", ["a","(b|c", "*(b|c", "d)"]] + // a + // *(b|c) + // *(b|d) + , ["{a,*(b|{c,d})}", ["a","b", "bc", "cb", "c", "d"]] + , ["*(a|{b|c,c})", ["a", "b", "c", "ab", "ac", "bc", "cb"]] + + + // test various flag settings. + , [ "*(a|{b|c,c})", ["x(a|b|c)", "x(a|c)", "(a|b|c)", "(a|c)"] + , { noext: true } ] + , ["a?b", ["x/y/acb", "acb/"], {matchBase: true} + , ["x/y/acb", "acb/", "acb/d/e", "x/y/acb/d"] ] + , ["#*", ["#a", "#b"], {nocomment: true}, ["#a", "#b", "c#d"]] + + + // begin channelling Boole and deMorgan... + , "negation tests" + , function () { + files = ["d", "e", "!ab", "!abc", "a!b", "\\!a"] + } + + // anything that is NOT a* matches. + , ["!a*", ["\\!a", "d", "e", "!ab", "!abc"]] + + // anything that IS !a* matches. + , ["!a*", ["!ab", "!abc"], {nonegate: true}] + + // anything that IS a* matches + , ["!!a*", ["a!b"]] + + // anything that is NOT !a* matches + , ["!\\!a*", ["a!b", "d", "e", "\\!a"]] + + // negation nestled within a pattern + , function () { + files = [ "foo.js" + , "foo.bar" + // can't match this one without negative lookbehind. + , "foo.js.js" + , "blar.js" + , "foo." + , "boo.js.boo" ] + } + , ["*.!(js)", ["foo.bar", "foo.", "boo.js.boo"] ] + + ].forEach(function (c) { + if (typeof c === "function") return c() + if (typeof c === "string") return t.comment(c) + + var pattern = c[0] + , expect = c[1].sort(alpha) + , options = c[2] || {} + , f = c[3] || files + , tapOpts = c[4] || {} + + // options.debug = true + var Class = mm.defaults(options).Minimatch + var m = new Class(pattern, {}) + var r = m.makeRe() + tapOpts.re = String(r) || JSON.stringify(r) + tapOpts.files = JSON.stringify(f) + tapOpts.pattern = pattern + tapOpts.set = m.set + tapOpts.negated = m.negate + + var actual = mm.match(f, pattern, options) + actual.sort(alpha) + + t.equivalent( actual, expect + , JSON.stringify(pattern) + " " + JSON.stringify(expect) + , tapOpts ) + }) + + t.comment("time=" + (Date.now() - start) + "ms") + t.end() +}) + +tap.test("global leak test", function (t) { + var globalAfter = Object.keys(global) + t.equivalent(globalAfter, globalBefore, "no new globals, please") + t.end() +}) + +function alpha (a, b) { + return a > b ? 1 : -1 +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/extglob-ending-with-state-char.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/extglob-ending-with-state-char.js new file mode 100644 index 0000000..6676e26 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/node_modules/minimatch/test/extglob-ending-with-state-char.js @@ -0,0 +1,8 @@ +var test = require('tap').test +var minimatch = require('../') + +test('extglob ending with statechar', function(t) { + t.notOk(minimatch('ax', 'a?(b*)')) + t.ok(minimatch('ax', '?(a*|b)')) + t.end() +}) diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/package.json b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/package.json new file mode 100644 index 0000000..b529099 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/package.json @@ -0,0 +1,60 @@ +{ + "name": "globule", + "description": "An easy-to-use wildcard globbing library.", + "version": "0.1.0", + "homepage": "https://github.com/cowboy/node-globule", + "author": { + "name": "\"Cowboy\" Ben Alman", + "url": "http://benalman.com/" + }, + "repository": { + "type": "git", + "url": "git://github.com/cowboy/node-globule.git" + }, + "bugs": { + "url": "https://github.com/cowboy/node-globule/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/cowboy/node-globule/blob/master/LICENSE-MIT" + } + ], + "main": "lib/globule", + "engines": { + "node": ">= 0.8.0" + }, + "scripts": { + "test": "grunt nodeunit" + }, + "devDependencies": { + "grunt-contrib-jshint": "~0.1.1", + "grunt-contrib-nodeunit": "~0.1.2", + "grunt-contrib-watch": "~0.2.0", + "grunt": "~0.4.1" + }, + "keywords": [ + "glob", + "file", + "match", + "mapping", + "expand", + "wildcard", + "pattern", + "sync", + "awesome" + ], + "dependencies": { + "lodash": "~1.0.1", + "glob": "~3.1.21", + "minimatch": "~0.2.11" + }, + "readme": "# globule [![Build Status](https://secure.travis-ci.org/cowboy/node-globule.png?branch=master)](http://travis-ci.org/cowboy/node-globule)\n\nAn easy-to-use wildcard globbing library.\n\n## Getting Started\nInstall the module with: `npm install globule`\n\n```javascript\nvar globule = require('globule');\nvar filepaths = globule.find('**/*.js');\n```\n\n## Documentation\n\n### globule.find\nReturns a unique array of all file or directory paths that match the given globbing pattern(s). This method accepts either comma separated globbing patterns or an array of globbing patterns. Paths matching patterns that begin with `!` will be excluded from the returned array. Patterns are processed in order, so inclusion and exclusion order is significant.\n\n```js\nglobule.find(patterns [, options])\n```\n\nThe `options` object supports all [glob][] library options, along with a few extras. These are the most commonly used:\n\n* `filter` Either a valid [fs.Stats method name](http://nodejs.org/docs/latest/api/fs.html#fs_class_fs_stats) or a function that will be passed the matched `src` filepath and `options` object as arguments. This function should return a `Boolean` value.\n* `nonull` Retain globbing patterns in result set even if they fail to match files.\n* `matchBase` Patterns without slashes will match just the basename part. Eg. this makes `*.js` work like `**/*.js`.\n* `srcBase` Patterns will be matched relative to the specified path instead of the current working directory. This is a synonym for `cwd`.\n* `prefixBase` Any specified `srcBase` will be prefixed to all returned filepaths.\n\n[glob]: https://github.com/isaacs/node-glob\n\n### globule.match\nMatch one or more globbing patterns against one or more file paths. Returns a uniqued array of all file paths that match any of the specified globbing patterns. Both the `patterns` and `filepaths` arguments can be a single string or array of strings. Paths matching patterns that begin with `!` will be excluded from the returned array. Patterns are processed in order, so inclusion and exclusion order is significant.\n\n```js\ngrunt.file.match(patterns, filepaths [, options])\n```\n\n### globule.isMatch\nThis method contains the same signature and logic as the `globule.match` method, but returns `true` if any files were matched, otherwise `false`.\n\n```js\ngrunt.file.isMatch(patterns, filepaths [, options])\n```\n\n### globule.mapping\nGiven a set of source file paths, returns an array of src-dest file mapping objects. Both src and dest paths may be renamed, depending on the options specified.\n\n```js\nglobule.mapping(filepaths [, options])\n```\n\nIn addition to the options the `globule.find` method supports, the options object also supports these properties:\n\n* `srcBase` The directory from which patterns are matched. Any string specified as `srcBase` is effectively stripped from the beginning of all matched paths.\n* `destBase` The specified path is prefixed to all `dest` filepaths.\n* `ext` Remove anything after (and including) the first `.` in the destination path, then append this value.\n* `extDot` Change the behavior of `ext`, `\"first\"` and `\"last\"` will remove anything after the first or last `.` in the destination filename, respectively. Defaults to `\"first\"`.\n* `flatten` Remove the path component from all matched src files. The src file path is still joined to the specified destBase.\n* `rename` If specified, this function will be responsible for returning the final `dest` filepath. By default, it flattens paths (if specified), changes extensions (if specified) and joins the matched path to the `destBase`.\n\n### globule.findMapping\nThis method is a convenience wrapper around the `globule.find` and `globule.mapping` methods.\n\n```js\nglobule.findMapping(patterns [, options])\n```\n\n\n## Examples\n\nGiven the files `foo/a.js` and `foo/b.js`:\n\n### srcBase and destBase\n\n```js\nglobule.find(\"foo/*.js\")\n// [\"foo/a.js\", \"foo/b.js\"]\n\nglobule.find(\"*.js\", {srcBase: \"foo\"})\n// [\"a.js\", \"b.js\"]\n\nglobule.find(\"*.js\", {srcBase: \"foo\", prefixBase: true})\n// [\"foo/a.js\", \"foo/b.js\"]\n```\n\n```js\nglobule.findMapping(\"foo/*.js\")\n// [{src: \"foo/a.js\", dest: \"foo/a.js\"}, {src: \"foo/b.js\", dest: \"foo/b.js\"}]\n\nglobule.findMapping(\"foo/*.js\", {destBase: \"bar\"})\n// [{src: \"foo/a.js\", dest: \"bar/foo/a.js\"}, {src: \"foo/b.js\", dest: \"bar/foo/b.js\"}]\n\nglobule.findMapping(\"*.js\", {srcBase: \"foo\", destBase: \"bar\"})\n// [{src: \"foo/a.js\", dest: \"bar/a.js\"}, {src: \"foo/b.js\", dest: \"bar/b.js\"}]\n```\n\n```js\nglobule.mapping([\"foo/a.js\", \"foo/b.js\"])\n// [{src: \"foo/a.js\", dest: \"foo/a.js\"}, {src: \"foo/b.js\", dest: \"foo/b.js\"}]\n\nglobule.mapping([\"foo/a.js\", \"foo/b.js\"], {destBase: \"bar\"})\n// [{src: \"foo/a.js\", dest: \"bar/foo/a.js\"}, {src: \"foo/b.js\", dest: \"bar/foo/b.js\"}]\n\nglobule.mapping([\"a.js\", \"b.js\"], {srcBase: \"foo\", destBase: \"bar\"})\n// [{src: \"foo/a.js\", dest: \"bar/a.js\"}, {src: \"foo/b.js\", dest: \"bar/b.js\"}]\n```\n\n## Contributing\nIn lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/).\n\n## Release History\n_(Nothing yet)_\n\n## License\nCopyright (c) 2013 \"Cowboy\" Ben Alman \nLicensed under the MIT license.\n", + "readmeFilename": "README.md", + "_id": "globule@0.1.0", + "dist": { + "shasum": "fb62afcc20d4e236ab829ba24e12d129910a3ff2" + }, + "_from": "globule@~0.1.0", + "_resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/README.md b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/README.md new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/css/baz.css b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/css/baz.css new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/css/qux.css b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/css/qux.css new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/deep/deep.txt b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/deep/deep.txt new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/deep/deeper/deeper.txt b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/deep/deeper/deeper.txt new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/deep/deeper/deepest/deepest.txt b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/deep/deeper/deepest/deepest.txt new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/js/bar.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/js/bar.js new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/js/foo.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/fixtures/expand/js/foo.js new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/globule_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/globule_test.js new file mode 100644 index 0000000..9b55b6b --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/node_modules/globule/test/globule_test.js @@ -0,0 +1,486 @@ +'use strict'; + +var path = require('path'); + +var globule = require('../lib/globule.js'); + +/* + ======== A Handy Little Nodeunit Reference ======== + https://github.com/caolan/nodeunit + + Test methods: + test.expect(numAssertions) + test.done() + Test assertions: + test.ok(value, [message]) + test.equal(actual, expected, [message]) + test.notEqual(actual, expected, [message]) + test.deepEqual(actual, expected, [message]) + test.notDeepEqual(actual, expected, [message]) + test.strictEqual(actual, expected, [message]) + test.notStrictEqual(actual, expected, [message]) + test.throws(block, [error], [message]) + test.doesNotThrow(block, [error], [message]) + test.ifError(value) +*/ + +exports['match'] = { + 'empty set': function(test) { + test.expect(6); + // Should return empty set if a required argument is missing or an empty set. + test.deepEqual(globule.match(null, 'foo.js'), [], 'should return empty set.'); + test.deepEqual(globule.match('*.js', null), [], 'should return empty set.'); + test.deepEqual(globule.match([], 'foo.js'), [], 'should return empty set.'); + test.deepEqual(globule.match('*.js', []), [], 'should return empty set.'); + test.deepEqual(globule.match(null, ['foo.js']), [], 'should return empty set.'); + test.deepEqual(globule.match(['*.js'], null), [], 'should return empty set.'); + test.done(); + }, + 'basic matching': function(test) { + test.expect(6); + test.deepEqual(globule.match('*.js', 'foo.js'), ['foo.js'], 'should match correctly.'); + test.deepEqual(globule.match('*.js', ['foo.js']), ['foo.js'], 'should match correctly.'); + test.deepEqual(globule.match('*.js', ['foo.js', 'bar.css']), ['foo.js'], 'should match correctly.'); + test.deepEqual(globule.match(['*.js', '*.css'], 'foo.js'), ['foo.js'], 'should match correctly.'); + test.deepEqual(globule.match(['*.js', '*.css'], ['foo.js']), ['foo.js'], 'should match correctly.'); + test.deepEqual(globule.match(['*.js', '*.css'], ['foo.js', 'bar.css']), ['foo.js', 'bar.css'], 'should match correctly.'); + test.done(); + }, + 'no matches': function(test) { + test.expect(2); + test.deepEqual(globule.match('*.js', 'foo.css'), [], 'should fail to match.'); + test.deepEqual(globule.match('*.js', ['foo.css', 'bar.css']), [], 'should fail to match.'); + test.done(); + }, + 'unique': function(test) { + test.expect(2); + test.deepEqual(globule.match('*.js', ['foo.js', 'foo.js']), ['foo.js'], 'should return a uniqued set.'); + test.deepEqual(globule.match(['*.js', '*.*'], ['foo.js', 'foo.js']), ['foo.js'], 'should return a uniqued set.'); + test.done(); + }, + 'flatten': function(test) { + test.expect(1); + test.deepEqual(globule.match([['*.js', '*.css'], ['*.*', '*.js']], ['foo.js', 'bar.css']), + ['foo.js', 'bar.css'], + 'should process nested pattern arrays correctly.'); + test.done(); + }, + 'exclusion': function(test) { + test.expect(5); + test.deepEqual(globule.match(['!*.js'], ['foo.js', 'bar.js']), [], 'solitary exclusion should match nothing'); + test.deepEqual(globule.match(['*.js', '!*.js'], ['foo.js', 'bar.js']), [], 'exclusion should cancel match'); + test.deepEqual(globule.match(['*.js', '!f*.js'], ['foo.js', 'bar.js', 'baz.js']), + ['bar.js', 'baz.js'], + 'partial exclusion should partially cancel match'); + test.deepEqual(globule.match(['*.js', '!*.js', 'b*.js'], ['foo.js', 'bar.js', 'baz.js']), + ['bar.js', 'baz.js'], + 'inclusion / exclusion order matters'); + test.deepEqual(globule.match(['*.js', '!f*.js', '*.js'], ['foo.js', 'bar.js', 'baz.js']), + ['bar.js', 'baz.js', 'foo.js'], + 'inclusion / exclusion order matters'); + test.done(); + }, + 'options.matchBase': function(test) { + test.expect(2); + test.deepEqual(globule.match('*.js', ['foo.js', 'bar', 'baz/xyz.js'], {matchBase: true}), + ['foo.js', 'baz/xyz.js'], + 'should matchBase (minimatch) when specified.'); + test.deepEqual(globule.match('*.js', ['foo.js', 'bar', 'baz/xyz.js']), + ['foo.js'], + 'should not matchBase (minimatch) by default.'); + test.done(); + }, +}; + +exports['isMatch'] = { + 'basic matching': function(test) { + test.expect(6); + test.ok(globule.isMatch('*.js', 'foo.js'), 'should match correctly.'); + test.ok(globule.isMatch('*.js', ['foo.js']), 'should match correctly.'); + test.ok(globule.isMatch('*.js', ['foo.js', 'bar.css']), 'should match correctly.'); + test.ok(globule.isMatch(['*.js', '*.css'], 'foo.js'), 'should match correctly.'); + test.ok(globule.isMatch(['*.js', '*.css'], ['foo.js']), 'should match correctly.'); + test.ok(globule.isMatch(['*.js', '*.css'], ['foo.js', 'bar.css']), 'should match correctly.'); + test.done(); + }, + 'no matches': function(test) { + test.expect(6); + test.ok(!globule.isMatch('*.js', 'foo.css'), 'should fail to match.'); + test.ok(!globule.isMatch('*.js', ['foo.css', 'bar.css']), 'should fail to match.'); + test.ok(!globule.isMatch(null, 'foo.css'), 'should fail to match.'); + test.ok(!globule.isMatch('*.js', null), 'should fail to match.'); + test.ok(!globule.isMatch([], 'foo.css'), 'should fail to match.'); + test.ok(!globule.isMatch('*.js', []), 'should fail to match.'); + test.done(); + }, + 'options.matchBase': function(test) { + test.expect(2); + test.ok(globule.isMatch('*.js', ['baz/xyz.js'], {matchBase: true}), 'should matchBase (minimatch) when specified.'); + test.ok(!globule.isMatch('*.js', ['baz/xyz.js']), 'should not matchBase (minimatch) by default.'); + test.done(); + }, +}; + +exports['find'] = { + setUp: function(done) { + this.cwd = process.cwd(); + process.chdir('test/fixtures/expand'); + done(); + }, + tearDown: function(done) { + process.chdir(this.cwd); + done(); + }, + 'basic matching': function(test) { + test.expect(5); + test.deepEqual(globule.find('**/*.js'), ['js/bar.js', 'js/foo.js'], 'single pattern argument should match.'); + test.deepEqual(globule.find('**/*.js', '**/*.css'), + ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'], + 'multiple pattern arguments should match.'); + test.deepEqual(globule.find(['**/*.js', '**/*.css']), + ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'], + 'array of patterns should match.'); + test.deepEqual(globule.find([['**/*.js'], [['**/*.css', 'js/*.js']]]), + ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'], + 'array of arrays of patterns should be flattened.'); + test.deepEqual(globule.find('*.xyz'), [], 'bad pattern should fail to match.'); + test.done(); + }, + 'unique': function(test) { + test.expect(4); + test.deepEqual(globule.find('**/*.js', 'js/*.js'), + ['js/bar.js', 'js/foo.js'], + 'file list should be uniqed.'); + test.deepEqual(globule.find('**/*.js', '**/*.css', 'js/*.js'), ['js/bar.js', 'js/foo.js', + 'css/baz.css', 'css/qux.css'], + 'file list should be uniqed.'); + test.deepEqual(globule.find('js', 'js/'), + ['js', 'js/'], + 'mixed non-ending-/ and ending-/ dirs will not be uniqed by default.'); + test.deepEqual(globule.find('js', 'js/', {mark: true}), + ['js/'], + 'mixed non-ending-/ and ending-/ dirs will be uniqed when "mark" is specified.'); + test.done(); + }, + 'file order': function(test) { + test.expect(5); + var actual = globule.find('**/*.{js,css}'); + var expected = ['css/baz.css', 'css/qux.css', 'js/bar.js', 'js/foo.js']; + test.deepEqual(actual, expected, 'should select 4 files in this order, by default.'); + + actual = globule.find('js/foo.js', 'js/bar.js', '**/*.{js,css}'); + expected = ['js/foo.js', 'js/bar.js', 'css/baz.css', 'css/qux.css']; + test.deepEqual(actual, expected, 'specifically-specified-up-front file order should be maintained.'); + + actual = globule.find('js/bar.js', 'js/foo.js', '**/*.{js,css}'); + expected = ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css']; + test.deepEqual(actual, expected, 'specifically-specified-up-front file order should be maintained.'); + + actual = globule.find('**/*.{js,css}', '!css/qux.css', 'css/qux.css'); + expected = ['css/baz.css', 'js/bar.js', 'js/foo.js', 'css/qux.css']; + test.deepEqual(actual, expected, 'if a file is excluded and then re-added, it should be added at the end.'); + + actual = globule.find('js/foo.js', '**/*.{js,css}', '!css/qux.css', 'css/qux.css'); + expected = ['js/foo.js', 'css/baz.css', 'js/bar.js', 'css/qux.css']; + test.deepEqual(actual, expected, 'should be able to combine specified-up-front and excluded/added-at-end.'); + test.done(); + }, + 'exclusion': function(test) { + test.expect(8); + test.deepEqual(globule.find(['!js/*.js']), [], 'solitary exclusion should match nothing'); + test.deepEqual(globule.find(['js/bar.js','!js/bar.js']), [], 'exclusion should negate match'); + test.deepEqual(globule.find(['**/*.js', '!js/foo.js']), + ['js/bar.js'], + 'should omit single file from matched set'); + test.deepEqual(globule.find(['!js/foo.js', '**/*.js']), + ['js/bar.js', 'js/foo.js'], + 'inclusion / exclusion order matters'); + test.deepEqual(globule.find(['**/*.js', '**/*.css', '!js/bar.js', '!css/baz.css']), + ['js/foo.js','css/qux.css'], + 'multiple exclusions should be removed from the set'); + test.deepEqual(globule.find(['**/*.js', '**/*.css', '!**/*.css']), + ['js/bar.js', 'js/foo.js'], + 'excluded wildcards should be removed from the matched set'); + test.deepEqual(globule.find(['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css', '!**/b*.*']), + ['js/foo.js', 'css/qux.css'], + 'different pattern for exclusion should still work'); + test.deepEqual(globule.find(['js/bar.js', '!**/b*.*', 'js/foo.js', 'css/baz.css', 'css/qux.css']), + ['js/foo.js', 'css/baz.css', 'css/qux.css'], + 'inclusion / exclusion order matters'); + test.done(); + }, + 'options.mark': function(test) { + test.expect(4); + test.deepEqual(globule.find('**d*/**'), [ + 'deep', + 'deep/deep.txt', + 'deep/deeper', + 'deep/deeper/deeper.txt', + 'deep/deeper/deepest', + 'deep/deeper/deepest/deepest.txt'], 'should match files and directories.'); + test.deepEqual(globule.find('**d*/**/'), [ + 'deep/', + 'deep/deeper/', + 'deep/deeper/deepest/'], 'trailing / in pattern should match directories only, matches end in /.'); + test.deepEqual(globule.find('**d*/**', {mark: true}), [ + 'deep/', + 'deep/deep.txt', + 'deep/deeper/', + 'deep/deeper/deeper.txt', + 'deep/deeper/deepest/', + 'deep/deeper/deepest/deepest.txt'], 'the minimatch "mark" option ensures directories end in /.'); + test.deepEqual(globule.find('**d*/**/', {mark: true}), [ + 'deep/', + 'deep/deeper/', + 'deep/deeper/deepest/'], 'the minimatch "mark" option should not remove trailing / from matched paths.'); + test.done(); + }, + 'options.filter': function(test) { + test.expect(5); + test.deepEqual(globule.find('**d*/**', {filter: 'isFile'}), [ + 'deep/deep.txt', + 'deep/deeper/deeper.txt', + 'deep/deeper/deepest/deepest.txt' + ], 'should match files only.'); + test.deepEqual(globule.find('**d*/**', {filter: 'isDirectory'}), [ + 'deep', + 'deep/deeper', + 'deep/deeper/deepest' + ], 'should match directories only.'); + test.deepEqual(globule.find('**', { + arbitraryProp: /deepest/, + filter: function(filepath, options) { + return options.arbitraryProp.test(filepath); + } + }), [ + 'deep/deeper/deepest', + 'deep/deeper/deepest/deepest.txt', + ], 'should filter arbitrarily.'); + test.deepEqual(globule.find('js', 'css', {filter: 'isFile'}), [], 'should fail to match.'); + test.deepEqual(globule.find('**/*.js', {filter: 'isDirectory'}), [], 'should fail to match.'); + test.done(); + }, + 'options.matchBase': function(test) { + test.expect(3); + test.deepEqual(globule.find('*.js'), [], 'should not matchBase (minimatch) by default.'); + test.deepEqual(globule.find('*.js', {matchBase: true}), + ['js/bar.js', 'js/foo.js'], + 'matchBase option should be passed through to minimatch.'); + test.deepEqual(globule.find('*.js', '*.css', {matchBase: true}), + ['js/bar.js', 'js/foo.js', 'css/baz.css', 'css/qux.css'], + 'matchBase option should be passed through to minimatch.'); + test.done(); + }, + 'options.srcBase': function(test) { + test.expect(5); + test.deepEqual(globule.find(['**/deep*.txt'], {srcBase: 'deep'}), + ['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'], + 'should find paths matching pattern relative to srcBase.'); + test.deepEqual(globule.find(['**/deep*.txt'], {cwd: 'deep'}), + ['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'], + 'cwd and srcBase should do the same thing.'); + test.deepEqual(globule.find(['**/deep*'], {srcBase: 'deep', filter: 'isFile'}), + ['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'], + 'srcBase should not prevent filtering.'); + test.deepEqual(globule.find(['**/deep*'], {srcBase: 'deep', filter: 'isDirectory'}), + ['deeper', 'deeper/deepest'], + 'srcBase should not prevent filtering.'); + test.deepEqual(globule.find(['**/deep*.txt', '!**/deeper**'], {srcBase: 'deep'}), + ['deep.txt', 'deeper/deepest/deepest.txt'], + 'srcBase should not prevent exclusions.'); + test.done(); + }, + 'options.prefixBase': function(test) { + test.expect(2); + test.deepEqual(globule.find(['**/deep*.txt'], {srcBase: 'deep', prefixBase: false}), + ['deep.txt', 'deeper/deeper.txt', 'deeper/deepest/deepest.txt'], + 'should not prefix srcBase to returned paths.'); + test.deepEqual(globule.find(['**/deep*.txt'], {srcBase: 'deep', prefixBase: true}), + ['deep/deep.txt', 'deep/deeper/deeper.txt', 'deep/deeper/deepest/deepest.txt'], + 'should prefix srcBase to returned paths.'); + test.done(); + }, + 'options.nonull': function(test) { + test.expect(3); + test.deepEqual(globule.find(['*omg*'], {nonull: true}), + ['*omg*'], + 'non-matching patterns should be returned in result set.'); + test.deepEqual(globule.find(['js/a*', 'js/b*', 'js/c*'], {nonull: true}), + ['js/a*', 'js/bar.js', 'js/c*'], + 'non-matching patterns should be returned in result set.'); + test.deepEqual(globule.find(['js/foo.js', 'js/bar.js', 'js/nonexistent.js'], {nonull: true}), + ['js/foo.js', 'js/bar.js', 'js/nonexistent.js'], + 'non-matching filenames should be returned in result set.'); + test.done(); + }, +}; + +exports['mapping'] = { + 'basic mapping': function(test) { + test.expect(1); + + var actual = globule.mapping(['a.txt', 'b.txt', 'c.txt']); + var expected = [ + {dest: 'a.txt', src: ['a.txt']}, + {dest: 'b.txt', src: ['b.txt']}, + {dest: 'c.txt', src: ['c.txt']}, + ]; + test.deepEqual(actual, expected, 'default options should create same-to-same src-dest mappings.'); + + test.done(); + }, + 'options.srcBase': function(test) { + test.expect(2); + var actual, expected; + actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {srcBase: 'foo'}); + expected = [ + {dest: 'a.txt', src: ['foo/a.txt']}, + {dest: 'bar/b.txt', src: ['foo/bar/b.txt']}, + {dest: 'bar/baz/c.txt', src: ['foo/bar/baz/c.txt']}, + ]; + test.deepEqual(actual, expected, 'srcBase should be prefixed to src paths (no trailing /).'); + + actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {srcBase: 'foo/'}); + test.deepEqual(actual, expected, 'srcBase should be prefixed to src paths (trailing /).'); + + test.done(); + }, + 'options.destBase': function(test) { + test.expect(2); + var actual, expected; + + actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {destBase: 'dest'}); + expected = [ + {dest: 'dest/a.txt', src: ['a.txt']}, + {dest: 'dest/bar/b.txt', src: ['bar/b.txt']}, + {dest: 'dest/bar/baz/c.txt', src: ['bar/baz/c.txt']}, + ]; + test.deepEqual(actual, expected, 'destBase should be prefixed to dest paths (no trailing /).'); + + actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {destBase: 'dest/'}); + test.deepEqual(actual, expected, 'destBase should be prefixed to dest paths (trailing /).'); + + test.done(); + }, + 'options.flatten': function(test) { + test.expect(1); + var actual, expected; + + actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {flatten: true}); + expected = [ + {dest: 'a.txt', src: ['a.txt']}, + {dest: 'b.txt', src: ['bar/b.txt']}, + {dest: 'c.txt', src: ['bar/baz/c.txt']}, + ]; + test.deepEqual(actual, expected, 'flatten should remove all src path parts from dest.'); + + test.done(); + }, + 'options.flatten + options.destBase': function(test) { + test.expect(1); + var actual, expected; + + actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], {destBase: 'dest', flatten: true}); + expected = [ + {dest: 'dest/a.txt', src: ['a.txt']}, + {dest: 'dest/b.txt', src: ['bar/b.txt']}, + {dest: 'dest/c.txt', src: ['bar/baz/c.txt']}, + ]; + test.deepEqual(actual, expected, 'flatten and destBase should work together.'); + + test.done(); + }, + 'options.ext': function(test) { + test.expect(1); + var actual, expected; + + actual = globule.mapping(['x/a.js', 'x.y/b.min.js', 'x.y/z.z/c'], {ext: '.foo'}); + expected = [ + {dest: 'x/a.foo', src: ['x/a.js']}, + {dest: 'x.y/b.foo', src: ['x.y/b.min.js']}, + {dest: 'x.y/z.z/c.foo', src: ['x.y/z.z/c']}, + ]; + test.deepEqual(actual, expected, 'by default, ext should replace everything after the first dot in the filename.'); + + test.done(); + }, + 'options.extDot': function(test) { + test.expect(2); + var actual, expected; + + actual = globule.mapping(['x/a.js', 'x.y/b.bbb.min.js', 'x.y/z.z/c'], {ext: '.foo', extDot: 'first'}); + expected = [ + {dest: 'x/a.foo', src: ['x/a.js']}, + {dest: 'x.y/b.foo', src: ['x.y/b.bbb.min.js']}, + {dest: 'x.y/z.z/c.foo', src: ['x.y/z.z/c']}, + ]; + test.deepEqual(actual, expected, 'extDot of "first" should replace everything after the first dot in the filename.'); + + actual = globule.mapping(['x/a.js', 'x.y/b.bbb.min.js', 'x.y/z.z/c'], {ext: '.foo', extDot: 'last'}); + expected = [ + {dest: 'x/a.foo', src: ['x/a.js']}, + {dest: 'x.y/b.bbb.min.foo', src: ['x.y/b.bbb.min.js']}, + {dest: 'x.y/z.z/c.foo', src: ['x.y/z.z/c']}, + ]; + test.deepEqual(actual, expected, 'extDot of "last" should replace everything after the last dot in the filename.'); + + test.done(); + }, + 'options.rename': function(test) { + test.expect(1); + var actual, expected; + actual = globule.mapping(['a.txt', 'bar/b.txt', 'bar/baz/c.txt'], { + arbitraryProp: 'FOO', + rename: function(dest, options) { + return path.join(options.arbitraryProp, dest.toUpperCase()); + } + }); + expected = [ + {dest: 'FOO/A.TXT', src: ['a.txt']}, + {dest: 'FOO/BAR/B.TXT', src: ['bar/b.txt']}, + {dest: 'FOO/BAR/BAZ/C.TXT', src: ['bar/baz/c.txt']}, + ]; + test.deepEqual(actual, expected, 'allow arbitrary renaming of files.'); + + test.done(); + }, +}; + +exports['findMapping'] = { + setUp: function(done) { + this.cwd = process.cwd(); + process.chdir('test/fixtures'); + done(); + }, + tearDown: function(done) { + process.chdir(this.cwd); + done(); + }, + 'basic matching': function(test) { + test.expect(2); + + var actual = globule.findMapping(['expand/**/*.txt']); + var expected = [ + {dest: 'expand/deep/deep.txt', src: ['expand/deep/deep.txt']}, + {dest: 'expand/deep/deeper/deeper.txt', src: ['expand/deep/deeper/deeper.txt']}, + {dest: 'expand/deep/deeper/deepest/deepest.txt', src: ['expand/deep/deeper/deepest/deepest.txt']}, + ]; + test.deepEqual(actual, expected, 'default options'); + + expected = globule.mapping(globule.find(['expand/**/*.txt'])); + test.deepEqual(actual, expected, 'this is what it\'s doing under the hood, anwyays.'); + + test.done(); + }, + 'options.srcBase': function(test) { + test.expect(1); + var actual = globule.findMapping(['**/*.txt'], {destBase: 'dest', srcBase: 'expand/deep'}); + var expected = [ + {dest: 'dest/deep.txt', src: ['expand/deep/deep.txt']}, + {dest: 'dest/deeper/deeper.txt', src: ['expand/deep/deeper/deeper.txt']}, + {dest: 'dest/deeper/deepest/deepest.txt', src: ['expand/deep/deeper/deepest/deepest.txt']}, + ]; + test.deepEqual(actual, expected, 'srcBase should be stripped from front of destPath, pre-destBase+destPath join'); + test.done(); + }, +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/package.json b/node_modules/grunt-contrib-watch/node_modules/gaze/package.json new file mode 100644 index 0000000..3c9aa54 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/package.json @@ -0,0 +1,92 @@ +{ + "name": "gaze", + "description": "A globbing fs.watch wrapper built from the best parts of other fine watch libs.", + "version": "0.4.3", + "homepage": "https://github.com/shama/gaze", + "author": { + "name": "Kyle Robinson Young", + "email": "kyle@dontkry.com" + }, + "repository": { + "type": "git", + "url": "git://github.com/shama/gaze.git" + }, + "bugs": { + "url": "https://github.com/shama/gaze/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "https://github.com/shama/gaze/blob/master/LICENSE-MIT" + } + ], + "main": "lib/gaze", + "engines": { + "node": ">= 0.8.0" + }, + "scripts": { + "test": "grunt nodeunit -v" + }, + "dependencies": { + "globule": "~0.1.0" + }, + "devDependencies": { + "grunt": "~0.4.1", + "grunt-contrib-nodeunit": "~0.2.0", + "grunt-contrib-jshint": "~0.6.0", + "grunt-benchmark": "~0.2.0" + }, + "keywords": [ + "watch", + "glob" + ], + "contributors": [ + { + "name": "Kyle Robinson Young", + "url": "http://dontkry.com" + }, + { + "name": "Sam Day", + "url": "http://sam.is-super-awesome.com" + }, + { + "name": "Roarke Gaskill", + "url": "http://starkinvestments.com" + }, + { + "name": "Lance Pollard", + "url": "http://lancepollard.com/" + }, + { + "name": "Daniel Fagnan", + "url": "http://hydrocodedesign.com/" + }, + { + "name": "Jonas", + "url": "http://jpommerening.github.io/" + }, + { + "name": "Chris Chua", + "url": "http://sirh.cc/" + }, + { + "name": "Kael Zhang", + "url": "http://kael.me" + }, + { + "name": "Krasimir Tsonev", + "url": "http://krasimirtsonev.com/blog" + }, + { + "name": "brett-shwom" + } + ], + "readme": "# gaze [![Build Status](https://secure.travis-ci.org/shama/gaze.png?branch=master)](http://travis-ci.org/shama/gaze)\n\nA globbing fs.watch wrapper built from the best parts of other fine watch libs. \nCompatible with Node.js 0.10/0.8, Windows, OSX and Linux.\n\n![gaze](http://dontkry.com/images/repos/gaze.png)\n\n## Usage\nInstall the module with: `npm install gaze` or place into your `package.json`\nand run `npm install`.\n\n```javascript\nvar gaze = require('gaze');\n\n// Watch all .js files/dirs in process.cwd()\ngaze('**/*.js', function(err, watcher) {\n // Files have all started watching\n // watcher === this\n\n // Get all watched files\n console.log(this.watched());\n\n // On file changed\n this.on('changed', function(filepath) {\n console.log(filepath + ' was changed');\n });\n\n // On file added\n this.on('added', function(filepath) {\n console.log(filepath + ' was added');\n });\n\n // On file deleted\n this.on('deleted', function(filepath) {\n console.log(filepath + ' was deleted');\n });\n\n // On changed/added/deleted\n this.on('all', function(event, filepath) {\n console.log(filepath + ' was ' + event);\n });\n\n // Get watched files with relative paths\n console.log(this.relative());\n});\n\n// Also accepts an array of patterns\ngaze(['stylesheets/*.css', 'images/**/*.png'], function() {\n // Add more patterns later to be watched\n this.add(['js/*.js']);\n});\n```\n\n### Alternate Interface\n\n```javascript\nvar Gaze = require('gaze').Gaze;\n\nvar gaze = new Gaze('**/*');\n\n// Files have all started watching\ngaze.on('ready', function(watcher) { });\n\n// A file has been added/changed/deleted has occurred\ngaze.on('all', function(event, filepath) { });\n```\n\n### Errors\n\n```javascript\ngaze('**/*', function() {\n this.on('error', function(err) {\n // Handle error here\n });\n});\n```\n\n### Minimatch / Glob\n\nSee [isaacs's minimatch](https://github.com/isaacs/minimatch) for more\ninformation on glob patterns.\n\n## Documentation\n\n### gaze(patterns, [options], callback)\n\n* `patterns` {String|Array} File patterns to be matched\n* `options` {Object}\n* `callback` {Function}\n * `err` {Error | null}\n * `watcher` {Object} Instance of the Gaze watcher\n\n### Class: gaze.Gaze\n\nCreate a Gaze object by instanting the `gaze.Gaze` class.\n\n```javascript\nvar Gaze = require('gaze').Gaze;\nvar gaze = new Gaze(pattern, options, callback);\n```\n\n#### Properties\n\n* `options` The options object passed in.\n * `interval` {integer} Interval to pass to fs.watchFile\n * `debounceDelay` {integer} Delay for events called in succession for the same\n file/event\n\n#### Events\n\n* `ready(watcher)` When files have been globbed and watching has begun.\n* `all(event, filepath)` When an `added`, `changed` or `deleted` event occurs.\n* `added(filepath)` When a file has been added to a watch directory.\n* `changed(filepath)` When a file has been changed.\n* `deleted(filepath)` When a file has been deleted.\n* `renamed(newPath, oldPath)` When a file has been renamed.\n* `end()` When the watcher is closed and watches have been removed.\n* `error(err)` When an error occurs.\n\n#### Methods\n\n* `emit(event, [...])` Wrapper for the EventEmitter.emit.\n `added`|`changed`|`deleted` events will also trigger the `all` event.\n* `close()` Unwatch all files and reset the watch instance.\n* `add(patterns, callback)` Adds file(s) patterns to be watched.\n* `remove(filepath)` removes a file or directory from being watched. Does not\n recurse directories.\n* `watched()` Returns the currently watched files.\n* `relative([dir, unixify])` Returns the currently watched files with relative paths.\n * `dir` {string} Only return relative files for this directory.\n * `unixify` {boolean} Return paths with `/` instead of `\\\\` if on Windows.\n\n## FAQs\n\n### Why Another `fs.watch` Wrapper?\nI liked parts of other `fs.watch` wrappers but none had all the features I\nneeded. This lib combines the features I needed from other fine watch libs:\nSpeedy data behavior from\n[paulmillr's chokidar](https://github.com/paulmillr/chokidar), API interface\nfrom [mikeal's watch](https://github.com/mikeal/watch) and file globbing using\n[isaacs's glob](https://github.com/isaacs/node-glob) which is also used by\n[cowboy's Grunt](https://github.com/gruntjs/grunt).\n\n### How do I fix the error `EMFILE: Too many opened files.`?\nThis is because of your system's max opened file limit. For OSX the default is\nvery low (256). Increase your limit temporarily with `ulimit -n 10480`, the\nnumber being the new max limit.\n\n## Contributing\nIn lieu of a formal styleguide, take care to maintain the existing coding style.\nAdd unit tests for any new or changed functionality. Lint and test your code\nusing [grunt](http://gruntjs.com/).\n\n## Release History\n* 0.4.3 - Track file additions in newly created folders (@brett-shwom).\n* 0.4.2 - Fix .remove() method to remove a single file in a directory (@kaelzhang). Fixing Cannot call method 'call' of undefined (@krasimir). Track new file additions within folders (@brett-shwom).\n* 0.4.1 - Fix watchDir not respecting close in race condition (@chrisirhc).\n* 0.4.0 - Drop support for node v0.6. Use globule for file matching. Avoid node v0.10 path.resolve/join errors. Register new files when added to non-existent folder. Multiple instances can now poll the same files (@jpommerening).\n* 0.3.4 - Code clean up. Fix path must be strings errors (@groner). Fix incorrect added events (@groner).\n* 0.3.3 - Fix for multiple patterns with negate.\n* 0.3.2 - Emit `end` before removeAllListeners.\n* 0.3.1 - Fix added events within subfolder patterns.\n* 0.3.0 - Handle safewrite events, `forceWatchMethod` option removed, bug fixes and watch optimizations (@rgaskill).\n* 0.2.2 - Fix issue where subsequent add calls dont get watched (@samcday). removeAllListeners on close.\n* 0.2.1 - Fix issue with invalid `added` events in current working dir.\n* 0.2.0 - Support and mark folders with `path.sep`. Add `forceWatchMethod` option. Support `renamed` events.\n* 0.1.6 - Recognize the `cwd` option properly\n* 0.1.5 - Catch too many open file errors\n* 0.1.4 - Really fix the race condition with 2 watches\n* 0.1.3 - Fix race condition with 2 watches\n* 0.1.2 - Read triggering changed event fix\n* 0.1.1 - Minor fixes\n* 0.1.0 - Initial release\n\n## License\nCopyright (c) 2013 Kyle Robinson Young \nLicensed under the MIT license.\n", + "readmeFilename": "README.md", + "_id": "gaze@0.4.3", + "dist": { + "shasum": "1053c5bb162da046604ce100855cf6e19e81336b" + }, + "_from": "gaze@~0.4.0", + "_resolved": "https://registry.npmjs.org/gaze/-/gaze-0.4.3.tgz" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/add_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/add_test.js new file mode 100644 index 0000000..cfb1e89 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/add_test.js @@ -0,0 +1,69 @@ +'use strict'; + +var Gaze = require('../lib/gaze.js').Gaze; +var path = require('path'); +var fs = require('fs'); +var helper = require('./helper'); + +var fixtures = path.resolve(__dirname, 'fixtures'); +var sortobj = helper.sortobj; + +exports.add = { + setUp: function(done) { + process.chdir(fixtures); + done(); + }, + addToWatched: function(test) { + test.expect(1); + var files = [ + 'Project (LO)/', + 'Project (LO)/one.js', + 'nested/', + 'nested/one.js', + 'nested/three.js', + 'nested/sub/', + 'nested/sub/two.js', + 'one.js', + ]; + var expected = { + 'Project (LO)/': ['one.js'], + '.': ['Project (LO)/', 'nested/', 'one.js', 'sub/'], + 'nested/': ['sub/', 'sub2/', 'one.js', 'three.js'], + 'nested/sub/': ['two.js'], + }; + var gaze = new Gaze('addnothingtowatch'); + gaze._addToWatched(files); + var result = gaze.relative(null, true); + test.deepEqual(sortobj(result), sortobj(expected)); + test.done(); + }, + addLater: function(test) { + test.expect(3); + new Gaze('sub/one.js', function(err, watcher) { + test.deepEqual(watcher.relative('sub'), ['one.js']); + watcher.add('sub/*.js', function() { + test.deepEqual(watcher.relative('sub'), ['one.js', 'two.js']); + watcher.on('changed', function(filepath) { + test.equal('two.js', path.basename(filepath)); + watcher.close(); + test.done(); + }); + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'two.js'), 'var two = true;'); + }); + }); + }, + addNoCallback: function(test) { + test.expect(1); + new Gaze('sub/one.js', function(err, watcher) { + this.add('sub/two.js'); + this.on('changed', function(filepath) { + test.equal('two.js', path.basename(filepath)); + watcher.close(); + test.done(); + }); + setTimeout(function() { + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'two.js'), 'var two = true;'); + }, 500); + }); + }, +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/api_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/api_test.js new file mode 100644 index 0000000..42d258e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/api_test.js @@ -0,0 +1,38 @@ +'use strict'; + +var gaze = require('../lib/gaze.js'); +var path = require('path'); + +exports.api = { + setUp: function(done) { + process.chdir(path.resolve(__dirname, 'fixtures')); + done(); + }, + newGaze: function(test) { + test.expect(2); + new gaze.Gaze('**/*', {}, function() { + var result = this.relative(null, true); + test.deepEqual(result['.'], ['Project (LO)/', 'nested/', 'one.js', 'sub/']); + test.deepEqual(result['sub/'], ['one.js', 'two.js']); + this.close(); + test.done(); + }); + }, + func: function(test) { + test.expect(1); + var g = gaze('**/*', function(err, watcher) { + test.deepEqual(watcher.relative('sub', true), ['one.js', 'two.js']); + g.close(); + test.done(); + }); + }, + ready: function(test) { + test.expect(1); + var g = new gaze.Gaze('**/*'); + g.on('ready', function(watcher) { + test.deepEqual(watcher.relative('sub', true), ['one.js', 'two.js']); + this.close(); + test.done(); + }); + } +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/file_poller.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/file_poller.js new file mode 100644 index 0000000..6e96937 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/file_poller.js @@ -0,0 +1,27 @@ +'use strict'; + +var path = require('path'); +var fs = require('fs'); + +var timeout = +process.argv[2]; +if (!timeout || isNaN(timeout)) { + throw 'No specified timeout'; +} +setTimeout(function () { + process.exit(); +}, timeout); + +var pathArg = process.argv.slice(3); +if (!pathArg.length) { + throw 'No path arguments'; +} +var filepath = path.resolve.apply(path, [ __dirname ].concat(pathArg)); + +function writeToFile() { + setTimeout(function () { + fs.writeFile(filepath, ''); + return writeToFile(); + }, 0); +} + +writeToFile(); \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/Project (LO)/one.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/Project (LO)/one.js new file mode 100644 index 0000000..fefeeea --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/Project (LO)/one.js @@ -0,0 +1 @@ +var one = true; \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/one.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/one.js new file mode 100644 index 0000000..fefeeea --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/one.js @@ -0,0 +1 @@ +var one = true; \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/sub/two.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/sub/two.js new file mode 100644 index 0000000..24ad8a3 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/sub/two.js @@ -0,0 +1 @@ +var two = true; \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/sub2/two.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/sub2/two.js new file mode 100644 index 0000000..24ad8a3 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/sub2/two.js @@ -0,0 +1 @@ +var two = true; \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/three.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/three.js new file mode 100644 index 0000000..3392956 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/nested/three.js @@ -0,0 +1 @@ +var three = true; \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/one.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/one.js new file mode 100644 index 0000000..7a4b5f6 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/one.js @@ -0,0 +1 @@ +var test = true; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/sub/one.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/sub/one.js new file mode 100644 index 0000000..fefeeea --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/sub/one.js @@ -0,0 +1 @@ +var one = true; \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/sub/two.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/sub/two.js new file mode 100644 index 0000000..24ad8a3 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/fixtures/sub/two.js @@ -0,0 +1 @@ +var two = true; \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/helper.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/helper.js new file mode 100644 index 0000000..5452e3e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/helper.js @@ -0,0 +1,21 @@ +'use strict'; + +var helper = module.exports = {}; + +helper.sortobj = function sortobj(obj) { + if (Array.isArray(obj)) { + obj.sort(); + return obj; + } + var out = Object.create(null); + var keys = Object.keys(obj); + keys.sort(); + keys.forEach(function(key) { + var val = obj[key]; + if (Array.isArray(val)) { + val.sort(); + } + out[key] = val; + }); + return out; +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/matching_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/matching_test.js new file mode 100644 index 0000000..8261f2b --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/matching_test.js @@ -0,0 +1,95 @@ +'use strict'; + +var gaze = require('../lib/gaze.js'); +var grunt = require('grunt'); +var path = require('path'); +var helper = require('./helper'); + +var fixtures = path.resolve(__dirname, 'fixtures'); +var sortobj = helper.sortobj; + +function cleanUp(done) { + [ + 'newfolder', + ].forEach(function(d) { + var p = path.join(fixtures, d); + if (grunt.file.exists(p)) { + grunt.file.delete(p); + } + }); + done(); +} + +exports.matching = { + setUp: function(done) { + process.chdir(fixtures); + cleanUp(done); + }, + tearDown: cleanUp, + globAll: function(test) { + test.expect(2); + gaze('**/*', function() { + var result = this.relative(null, true); + test.deepEqual(result['.'], ['Project (LO)/', 'nested/', 'one.js', 'sub/']); + test.deepEqual(result['sub/'], ['one.js', 'two.js']); + this.close(); + test.done(); + }); + }, + relativeDir: function(test) { + test.expect(1); + gaze('**/*', function() { + test.deepEqual(this.relative('sub', true), ['one.js', 'two.js']); + this.close(); + test.done(); + }); + }, + globArray: function(test) { + test.expect(2); + gaze(['*.js', 'sub/*.js'], function() { + var result = this.relative(null, true); + test.deepEqual(sortobj(result['.']), sortobj(['one.js', 'Project (LO)/', 'nested/', 'sub/'])); + test.deepEqual(sortobj(result['sub/']), sortobj(['one.js', 'two.js'])); + this.close(); + test.done(); + }); + }, + globArrayDot: function(test) { + test.expect(1); + gaze(['./sub/*.js'], function() { + var result = this.relative(null, true); + test.deepEqual(result['sub/'], ['one.js', 'two.js']); + this.close(); + test.done(); + }); + }, + oddName: function(test) { + test.expect(1); + gaze(['Project (LO)/*.js'], function() { + var result = this.relative(null, true); + test.deepEqual(result['Project (LO)/'], ['one.js']); + this.close(); + test.done(); + }); + }, + addedLater: function(test) { + test.expect(2); + var times = 0; + gaze('**/*.js', function(err, watcher) { + watcher.on('all', function(status, filepath) { + times++; + var result = watcher.relative(null, true); + test.deepEqual(result['newfolder/'], ['added.js']); + if (times > 1) { watcher.close(); } + }); + grunt.file.write(path.join(fixtures, 'newfolder', 'added.js'), 'var added = true;'); + setTimeout(function() { + grunt.file.write(path.join(fixtures, 'newfolder', 'added.js'), 'var added = true;'); + }, 1000); + watcher.on('end', function() { + // TODO: Figure out why this test is finicky leaking it's newfolder into the other tests + setTimeout(test.done, 2000); + }); + }); + }, +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/patterns_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/patterns_test.js new file mode 100644 index 0000000..46b94e4 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/patterns_test.js @@ -0,0 +1,42 @@ +'use strict'; + +var gaze = require('../lib/gaze.js'); +var path = require('path'); +var fs = require('fs'); + +// Clean up helper to call in setUp and tearDown +function cleanUp(done) { + [ + 'added.js', + 'nested/added.js', + ].forEach(function(d) { + var p = path.resolve(__dirname, 'fixtures', d); + if (fs.existsSync(p)) { fs.unlinkSync(p); } + }); + done(); +} + +exports.patterns = { + setUp: function(done) { + process.chdir(path.resolve(__dirname, 'fixtures')); + cleanUp(done); + }, + tearDown: cleanUp, + negate: function(test) { + test.expect(1); + gaze(['**/*.js', '!nested/**/*.js'], function(err, watcher) { + watcher.on('added', function(filepath) { + var expected = path.relative(process.cwd(), filepath); + test.equal(path.join('added.js'), expected); + watcher.close(); + }); + // dont add + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'nested', 'added.js'), 'var added = true;'); + setTimeout(function() { + // should add + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'added.js'), 'var added = true;'); + }, 1000); + watcher.on('end', test.done); + }); + } +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/relative_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/relative_test.js new file mode 100644 index 0000000..492d8e5 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/relative_test.js @@ -0,0 +1,28 @@ +'use strict'; + +var Gaze = require('../lib/gaze.js').Gaze; +var path = require('path'); + +exports.relative = { + setUp: function(done) { + process.chdir(path.resolve(__dirname, 'fixtures')); + done(); + }, + relative: function(test) { + test.expect(1); + var files = [ + 'Project (LO)/', + 'Project (LO)/one.js', + 'nested/', + 'nested/one.js', + 'nested/three.js', + 'nested/sub/', + 'nested/sub/two.js', + 'one.js' + ]; + var gaze = new Gaze('addnothingtowatch'); + gaze._addToWatched(files); + test.deepEqual(gaze.relative('.', true), ['Project (LO)/', 'nested/', 'one.js', 'sub/']); + test.done(); + } +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/rename_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/rename_test.js new file mode 100644 index 0000000..5d2d496 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/rename_test.js @@ -0,0 +1,40 @@ +'use strict'; + +var gaze = require('../lib/gaze.js'); +var path = require('path'); +var fs = require('fs'); + +// Clean up helper to call in setUp and tearDown +function cleanUp(done) { + [ + 'sub/rename.js', + 'sub/renamed.js' + ].forEach(function(d) { + var p = path.resolve(__dirname, 'fixtures', d); + if (fs.existsSync(p)) { fs.unlinkSync(p); } + }); + done(); +} + +exports.watch = { + setUp: function(done) { + process.chdir(path.resolve(__dirname, 'fixtures')); + cleanUp(done); + }, + tearDown: cleanUp, + rename: function(test) { + test.expect(2); + var oldPath = path.join(__dirname, 'fixtures', 'sub', 'rename.js'); + var newPath = path.join(__dirname, 'fixtures', 'sub', 'renamed.js'); + fs.writeFileSync(oldPath, 'var rename = true;'); + gaze('**/*', function(err, watcher) { + watcher.on('renamed', function(newFile, oldFile) { + test.equal(newFile, newPath); + test.equal(oldFile, oldPath); + watcher.close(); + test.done(); + }); + fs.renameSync(oldPath, newPath); + }); + } +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/safewrite_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/safewrite_test.js new file mode 100644 index 0000000..ac76b93 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/safewrite_test.js @@ -0,0 +1,58 @@ +'use strict'; + +var gaze = require('../lib/gaze.js'); +var path = require('path'); +var fs = require('fs'); + +// Clean up helper to call in setUp and tearDown +function cleanUp(done) { + [ + 'safewrite.js' + ].forEach(function(d) { + var p = path.resolve(__dirname, 'fixtures', d); + if (fs.existsSync(p)) { fs.unlinkSync(p); } + }); + done(); +} + +exports.safewrite = { + setUp: function(done) { + process.chdir(path.resolve(__dirname, 'fixtures')); + cleanUp(done); + }, + tearDown: cleanUp, + safewrite: function(test) { + test.expect(4); + + var times = 0; + var file = path.resolve(__dirname, 'fixtures', 'safewrite.js'); + var backup = path.resolve(__dirname, 'fixtures', 'safewrite.ext~'); + fs.writeFileSync(file, 'var safe = true;'); + + function simSafewrite() { + fs.writeFileSync(backup, fs.readFileSync(file)); + fs.unlinkSync(file); + fs.renameSync(backup, file); + times++; + } + + gaze('**/*', function() { + this.on('all', function(action, filepath) { + test.equal(action, 'changed'); + test.equal(path.basename(filepath), 'safewrite.js'); + + if (times < 2) { + setTimeout(simSafewrite, 1000); + } else { + this.close(); + test.done(); + } + }); + + setTimeout(function() { + simSafewrite(); + }, 1000); + + }); + } +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/watch_race_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/watch_race_test.js new file mode 100644 index 0000000..e524692 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/watch_race_test.js @@ -0,0 +1,84 @@ +'use strict'; + +var gaze = require('../lib/gaze.js'); +var grunt = require('grunt'); +var path = require('path'); +var fs = require('fs'); +var cp = require('child_process'); + +// Clean up helper to call in setUp and tearDown +function cleanUp(done) { + [ + 'nested/sub/poller.js' + ].forEach(function(d) { + var p = path.resolve(__dirname, 'fixtures', d); + if (fs.existsSync(p)) { fs.unlinkSync(p); } + }); + done(); +} + +exports.watch_race = { + setUp: function(done) { + process.chdir(path.resolve(__dirname, 'fixtures')); + cleanUp(done); + }, + tearDown: cleanUp, + initWatchDirOnClose: function(test) { + var times = 5, + TIMEOUT = 5000, + firedWhenClosed = 0, + watchers = [], + watcherIdxes = [], + polled_file = ['fixtures', 'nested', 'sub', 'poller.js'], + expected_path = path.join.apply(path, polled_file.slice(1)); + test.expect(times); + for (var i = times; i--;) { + watcherIdxes.unshift(i); + } + // Create the file so that it can be watched + fs.writeFileSync(path.resolve.apply(path, [__dirname].concat(polled_file)), ''); + // Create a poller that keeps making changes to the file until timeout + var child_poller = cp.fork( + '../file_poller.js', + [times * TIMEOUT].concat(polled_file) + ); + grunt.util.async.forEachSeries(watcherIdxes, function(idx, next) { + var watcher = new gaze.Gaze('**/poller.js', function(err, watcher) { + var timeout = setTimeout(function () { + test.ok(false, 'watcher ' + idx + ' did not fire event on polled file.'); + watcher.close(); + }, TIMEOUT); + watcher.on('all', function (status, filepath) { + if (!filepath) { return; } + var expected = path.relative(process.cwd(), filepath); + test.equal(expected_path, expected, 'watcher ' + idx + + ' emitted unexpected event.'); + clearTimeout(timeout); + watcher.close(); + }); + watcher.on('end', function () { + // After watcher is closed and all event listeners have been removed, + // re-add a listener to see if anything is going on on this watcher. + process.nextTick(function () { + watcher.once('added', function () { + test.ok(false, 'watcher ' + idx + ' should not fire added' + + ' event on polled file after being closed.'); + }); + }); + next(); + }); + }); + watchers.push(watcher); + }, function () { + child_poller.kill(); + watchers.forEach(function (watcher) { + try { + watcher.close(); + } catch (e) { + // Ignore if this fails + } + }); + test.done(); + }); + }, +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/gaze/test/watch_test.js b/node_modules/grunt-contrib-watch/node_modules/gaze/test/watch_test.js new file mode 100644 index 0000000..0f3d368 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/gaze/test/watch_test.js @@ -0,0 +1,314 @@ +'use strict'; + +var gaze = require('../lib/gaze.js'); +var grunt = require('grunt'); +var path = require('path'); +var fs = require('fs'); + +// Clean up helper to call in setUp and tearDown +function cleanUp(done) { + [ + 'sub/tmp.js', + 'sub/tmp', + 'sub/renamed.js', + 'added.js', + 'nested/added.js', + 'nested/.tmp', + 'nested/sub/added.js', + ].forEach(function(d) { + var p = path.resolve(__dirname, 'fixtures', d); + if (fs.existsSync(p)) { fs.unlinkSync(p); } + }); + + grunt.file.delete(path.resolve(__dirname, 'fixtures', 'new_dir')); + + done(); +} + +exports.watch = { + setUp: function(done) { + process.chdir(path.resolve(__dirname, 'fixtures')); + cleanUp(done); + }, + tearDown: cleanUp, + remove: function(test) { + test.expect(2); + gaze('**/*', function() { + this.remove(path.resolve(__dirname, 'fixtures', 'sub', 'two.js')); + this.remove(path.resolve(__dirname, 'fixtures')); + var result = this.relative(null, true); + test.deepEqual(result['sub/'], ['one.js']); + test.notDeepEqual(result['.'], ['one.js']); + this.close(); + test.done(); + }); + }, + changed: function(test) { + test.expect(1); + gaze('**/*', function(err, watcher) { + watcher.on('changed', function(filepath) { + var expected = path.relative(process.cwd(), filepath); + test.equal(path.join('sub', 'one.js'), expected); + watcher.close(); + }); + this.on('added', function() { test.ok(false, 'added event should not have emitted.'); }); + this.on('deleted', function() { test.ok(false, 'deleted event should not have emitted.'); }); + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'one.js'), 'var one = true;'); + watcher.on('end', test.done); + }); + }, + added: function(test) { + test.expect(1); + gaze('**/*', function(err, watcher) { + watcher.on('added', function(filepath) { + var expected = path.relative(process.cwd(), filepath); + test.equal(path.join('sub', 'tmp.js'), expected); + watcher.close(); + }); + this.on('changed', function() { test.ok(false, 'changed event should not have emitted.'); }); + this.on('deleted', function() { test.ok(false, 'deleted event should not have emitted.'); }); + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'tmp.js'), 'var tmp = true;'); + watcher.on('end', test.done); + }); + }, + dontAddUnmatchedFiles: function(test) { + test.expect(2); + gaze('**/*.js', function(err, watcher) { + setTimeout(function() { + test.ok(true, 'Ended without adding a file.'); + watcher.close(); + }, 1000); + this.on('added', function(filepath) { + test.equal(path.relative(process.cwd(), filepath), path.join('sub', 'tmp.js')); + }); + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'tmp'), 'Dont add me!'); + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'tmp.js'), 'add me!'); + watcher.on('end', test.done); + }); + }, + dontAddMatchedDirectoriesThatArentReallyAdded: function(test) { + // This is a regression test for a bug I ran into where a matching directory would be reported + // added when a non-matching file was created along side it. This only happens if the + // directory name doesn't occur in $PWD. + test.expect(1); + gaze('**/*', function(err, watcher) { + setTimeout(function() { + test.ok(true, 'Ended without adding a file.'); + watcher.close(); + }, 1000); + this.on('added', function(filepath) { + test.notEqual(path.relative(process.cwd(), filepath), path.join('nested', 'sub2')); + }); + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'nested', '.tmp'), 'Wake up!'); + watcher.on('end', test.done); + }); + }, + deleted: function(test) { + test.expect(1); + var tmpfile = path.resolve(__dirname, 'fixtures', 'sub', 'deleted.js'); + fs.writeFileSync(tmpfile, 'var tmp = true;'); + gaze('**/*', function(err, watcher) { + watcher.on('deleted', function(filepath) { + test.equal(path.join('sub', 'deleted.js'), path.relative(process.cwd(), filepath)); + watcher.close(); + }); + this.on('changed', function() { test.ok(false, 'changed event should not have emitted.'); }); + this.on('added', function() { test.ok(false, 'added event should not have emitted.'); }); + fs.unlinkSync(tmpfile); + watcher.on('end', test.done); + }); + }, + dontEmitTwice: function(test) { + test.expect(2); + gaze('**/*', function(err, watcher) { + watcher.on('all', function(status, filepath) { + var expected = path.relative(process.cwd(), filepath); + test.equal(path.join('sub', 'one.js'), expected); + test.equal(status, 'changed'); + fs.readFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'one.js')); + setTimeout(function() { + fs.readFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'one.js')); + }, 1000); + // Give some time to accidentally emit before we close + setTimeout(function() { watcher.close(); }, 5000); + }); + setTimeout(function() { + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'one.js'), 'var one = true;'); + }, 1000); + watcher.on('end', test.done); + }); + }, + emitTwice: function(test) { + test.expect(2); + var times = 0; + gaze('**/*', function(err, watcher) { + watcher.on('all', function(status, filepath) { + test.equal(status, 'changed'); + times++; + setTimeout(function() { + if (times < 2) { + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'one.js'), 'var one = true;'); + } else { + watcher.close(); + } + }, 1000); + }); + setTimeout(function() { + fs.writeFileSync(path.resolve(__dirname, 'fixtures', 'sub', 'one.js'), 'var one = true;'); + }, 1000); + watcher.on('end', test.done); + }); + }, + nonExistent: function(test) { + test.expect(1); + gaze('non/existent/**/*', function(err, watcher) { + test.ok(true); + test.done(); + }); + }, + differentCWD: function(test) { + test.expect(1); + var cwd = path.resolve(__dirname, 'fixtures', 'sub'); + gaze('two.js', { + cwd: cwd + }, function(err, watcher) { + watcher.on('changed', function(filepath) { + test.deepEqual(this.relative(), {'.':['two.js']}); + watcher.close(); + }); + fs.writeFileSync(path.resolve(cwd, 'two.js'), 'var two = true;'); + watcher.on('end', test.done); + }); + }, + addedEmitInSubFolders: function(test) { + test.expect(4); + var adds = [ + { pattern: '**/*', file: path.resolve(__dirname, 'fixtures', 'nested', 'sub', 'added.js') }, + { pattern: '**/*', file: path.resolve(__dirname, 'fixtures', 'added.js') }, + { pattern: 'nested/**/*', file: path.resolve(__dirname, 'fixtures', 'nested', 'added.js') }, + { pattern: 'nested/sub/*.js', file: path.resolve(__dirname, 'fixtures', 'nested', 'sub', 'added.js') }, + ]; + grunt.util.async.forEachSeries(adds, function(add, next) { + new gaze.Gaze(add.pattern, function(err, watcher) { + watcher.on('added', function(filepath) { + test.equal('added.js', path.basename(filepath)); + fs.unlinkSync(filepath); + watcher.close(); + next(); + }); + watcher.on('changed', function() { test.ok(false, 'changed event should not have emitted.'); }); + watcher.on('deleted', function() { test.ok(false, 'deleted event should not have emitted.'); }); + fs.writeFileSync(add.file, 'var added = true;'); + }); + }, function() { + test.done(); + }); + }, + multipleWatchersSimultaneously: function(test) { + test.expect(2); + var did = 0; + var ready = 0; + var cwd = path.resolve(__dirname, 'fixtures', 'sub'); + var watchers = []; + var timeout = setTimeout(function() { + test.ok(false, "Only " + did + " of " + ready + " watchers fired."); + test.done(); + watchers.forEach(function(watcher) { + watcher.close(); + }); + }, 1000); + + function isReady() { + ready++; + if (ready > 1) { + fs.writeFileSync(path.resolve(cwd, 'one.js'), 'var one = true;'); + } + } + function isDone() { + did++; + if (did > 1) { + clearTimeout(timeout); + watchers.forEach(function(watcher) { + watcher.close(); + }); + test.done(); + } + } + function changed(filepath) { + test.equal(path.join('sub', 'one.js'), path.relative(process.cwd(), filepath)); + isDone(); + } + for (var i = 0; i < 2; i++) { + watchers[i] = new gaze.Gaze('sub/one.js'); + watchers[i].on('changed', changed); + watchers[i].on('ready', isReady); + } + }, + mkdirThenAddFile: function(test) { + test.expect(2); + + var expected = [ + 'new_dir', + 'new_dir/other.js', + ]; + + gaze('**/*.js', function(err, watcher) { + watcher.on('all', function(status, filepath) { + + var expect = expected.shift(); + test.equal(path.relative(process.cwd(), filepath), expect); + + if (expected.length === 1) { + // Ensure the new folder is being watched correctly after initial add + setTimeout(function() { + fs.writeFileSync('new_dir/dontmatch.txt', ''); + setTimeout(function() { + fs.writeFileSync('new_dir/other.js', ''); + }, 1000); + }, 1000); + } + + if (expected.length < 1) { watcher.close(); } + }); + + + fs.mkdirSync('new_dir'); //fs.mkdirSync([folder]) seems to behave differently than grunt.file.write('[folder]/[file]') + + + watcher.on('end', test.done); + }); + }, + mkdirThenAddFileWithGruntFileWrite: function(test) { + test.expect(3); + + var expected = [ + 'new_dir', + 'new_dir/tmp.js', + 'new_dir/other.js', + ]; + + gaze('**/*.js', function(err, watcher) { + watcher.on('all', function(status, filepath) { + + var expect = expected.shift(); + test.equal(path.relative(process.cwd(), filepath), expect); + + if (expected.length === 1) { + // Ensure the new folder is being watched correctly after initial add + setTimeout(function() { + fs.writeFileSync('new_dir/dontmatch.txt', ''); + setTimeout(function() { + fs.writeFileSync('new_dir/other.js', ''); + }, 1000); + }, 1000); + } + + if (expected.length < 1) { watcher.close(); } + }); + + grunt.file.write('new_dir/tmp.js', ''); + + watcher.on('end', test.done); + }); + }, +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/.npmignore b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/.npmignore new file mode 100644 index 0000000..1e107f5 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/.npmignore @@ -0,0 +1 @@ +examples diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/.travis.yml b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/.travis.yml new file mode 100644 index 0000000..baa0031 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - 0.8 diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/bin/tiny-lr b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/bin/tiny-lr new file mode 100755 index 0000000..2663446 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/bin/tiny-lr @@ -0,0 +1,68 @@ +#!/usr/bin/env node + +var fs = require('fs'); +var path = require('path'); + +// default DEBUG if not set already +process.env.DEBUG = process.env.DEBUG || 'tinylr tinylr:*'; + +var Server = require('..').Server; +var noptify = require('noptify'); + +var program = noptify(process.argv, { program: 'tiny-lr' }) + .version('0.0.1') + .option('port', '-p', 'Port to listen on (default: 35729)', Number) + .option('pid', 'Path to the generated PID file (default: ./tiny-lr.pid)', String); + +var opts = program.parse(); +opts.port = opts.port || 35729; +opts.pid = opts.pid || path.resolve('tiny-lr.pid'); + +// if it was required, don't start the server and expose the Server object. +if (module.parent) { + module.exports = Server; + return; +} + +// Server + +// Thanks to @FGRibreau for his very simple and very handy gist: +// https://gist.github.com/1846952 + +process.title = 'tiny-lr'; + +process.on('exit', function() { + console.log('... Closing server ...'); + console.log('... Removing pid file (%s) ...', opts.pid); + fs.unlinkSync(opts.pid); +}); + +process.on('SIGTERM', function() { + return process.exit(0); +}); + +process.on('SIGINT', function() { + return process.exit(0); +}); + + +var srv = new Server(opts); + +srv.on('close', function() { + process.nextTick(function() { + process.exit(); + }); +}); + +console.log(); +srv.listen(opts.port, function(err) { + fs.writeFile(opts.pid, process.pid, function(err) { + if(err) { + console.log('... Cannot write pid file: %s', opts.pid); + process.exit(1) + } + + console.log('... Listening on %s (pid: %s) ...', opts.port, process.pid); + console.log('... pid file: %s', opts.pid); + }); +}); diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/bin/update-livereload b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/bin/update-livereload new file mode 100755 index 0000000..b0d6c85 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/bin/update-livereload @@ -0,0 +1,13 @@ +#!/usr/bin/env node + +var fs = require('fs'); +var path = require('path'); +var request = require('request'); + +var file = path.join(__dirname, '..', 'lib/public/livereload.js'); +var url = process.argv.slice(2)[0] || 'https://raw.github.com/livereload/livereload-js/master/dist/livereload.js'; + +console.error('Updating livereload.js %s from %s', file, url); +request(url) + .pipe(fs.createWriteStream(file)) + .on('close', console.log.bind(console, 'Done')); diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/lib/client.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/lib/client.js new file mode 100644 index 0000000..f484d30 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/lib/client.js @@ -0,0 +1,81 @@ + +var util = require('util'); +var events = require('events'); +var WebSocket = require('faye-websocket'); + +module.exports = Client; + +function Client(req, socket, head) { + this.ws = new WebSocket(req, socket, head); + this.ws.onmessage = this.message.bind(this); + this.ws.onclose = this.close.bind(this); + this.id = this.uniqueId('ws'); +} + +util.inherits(Client, events.EventEmitter); + +Client.prototype.message = function message(event) { + // console.log('... Incoming %s ...', event.type); + var data = this.data(event); + if(this[data.command]) return this[data.command](data); +}; + +Client.prototype.close = function close(event) { + if(this.ws) { + this.ws.close(); + this.ws = null; + } + + this.emit('end', event); +}; + +// Commands + +Client.prototype.hello = function hello() { + this.send({ + command: 'hello', + protocols: [ + 'http://livereload.com/protocols/official-7' + ], + serverName: 'tiny-lr' + }); +}; + +Client.prototype.info = function info(data) { + this.plugins = data.plugins; + this.url = data.url; +}; + +// Server commands + +Client.prototype.reload = function reload(files) { + files.forEach(function(file) { + console.log('... Reload %s ...', file); + this.send({ + command: 'reload', + path: file, + liveCss: true, + liveJs: true + }); + }, this); +}; + +// Utilities + +Client.prototype.data = function _data(event) { + var data = {}; + try { + data = JSON.parse(event.data); + } catch (e) {} + return data; +}; + +Client.prototype.send = function send(data) { + this.ws.send(JSON.stringify(data)); +}; + +var idCounter = 0; +Client.prototype.uniqueId = function uniqueId(prefix) { + var id = idCounter++; + return prefix ? prefix + id : id; +}; diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/lib/index.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/lib/index.js new file mode 100644 index 0000000..1420629 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/lib/index.js @@ -0,0 +1,22 @@ + +var Server = require('./server'); +var Client = require('./client'); + +module.exports = tinylr; +tinylr.Server = Server; +tinylr.Client = Client; + +tinylr.middleware = middleware; + +function tinylr(opts) { + return new Server(opts); +} + +var util = require('util'); + +function middleware(opts) { + var srv = new Server(opts); + return function tinylr(req, res, next) { + srv.handler(req, res, next); + }; +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/lib/public/livereload.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/lib/public/livereload.js new file mode 100644 index 0000000..edb2802 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/lib/public/livereload.js @@ -0,0 +1,1055 @@ +(function() { +var __customevents = {}, __protocol = {}, __connector = {}, __timer = {}, __options = {}, __reloader = {}, __livereload = {}, __less = {}, __startup = {}; + +// customevents +var CustomEvents; +CustomEvents = { + bind: function(element, eventName, handler) { + if (element.addEventListener) { + return element.addEventListener(eventName, handler, false); + } else if (element.attachEvent) { + element[eventName] = 1; + return element.attachEvent('onpropertychange', function(event) { + if (event.propertyName === eventName) { + return handler(); + } + }); + } else { + throw new Error("Attempt to attach custom event " + eventName + " to something which isn't a DOMElement"); + } + }, + fire: function(element, eventName) { + var event; + if (element.addEventListener) { + event = document.createEvent('HTMLEvents'); + event.initEvent(eventName, true, true); + return document.dispatchEvent(event); + } else if (element.attachEvent) { + if (element[eventName]) { + return element[eventName]++; + } + } else { + throw new Error("Attempt to fire custom event " + eventName + " on something which isn't a DOMElement"); + } + } +}; +__customevents.bind = CustomEvents.bind; +__customevents.fire = CustomEvents.fire; + +// protocol +var PROTOCOL_6, PROTOCOL_7, Parser, ProtocolError; +var __indexOf = Array.prototype.indexOf || function(item) { + for (var i = 0, l = this.length; i < l; i++) { + if (this[i] === item) return i; + } + return -1; +}; +__protocol.PROTOCOL_6 = PROTOCOL_6 = 'http://livereload.com/protocols/official-6'; +__protocol.PROTOCOL_7 = PROTOCOL_7 = 'http://livereload.com/protocols/official-7'; +__protocol.ProtocolError = ProtocolError = (function() { + function ProtocolError(reason, data) { + this.message = "LiveReload protocol error (" + reason + ") after receiving data: \"" + data + "\"."; + } + return ProtocolError; +})(); +__protocol.Parser = Parser = (function() { + function Parser(handlers) { + this.handlers = handlers; + this.reset(); + } + Parser.prototype.reset = function() { + return this.protocol = null; + }; + Parser.prototype.process = function(data) { + var command, message, options, _ref; + try { + if (!(this.protocol != null)) { + if (data.match(/^!!ver:([\d.]+)$/)) { + this.protocol = 6; + } else if (message = this._parseMessage(data, ['hello'])) { + if (!message.protocols.length) { + throw new ProtocolError("no protocols specified in handshake message"); + } else if (__indexOf.call(message.protocols, PROTOCOL_7) >= 0) { + this.protocol = 7; + } else if (__indexOf.call(message.protocols, PROTOCOL_6) >= 0) { + this.protocol = 6; + } else { + throw new ProtocolError("no supported protocols found"); + } + } + return this.handlers.connected(this.protocol); + } else if (this.protocol === 6) { + message = JSON.parse(data); + if (!message.length) { + throw new ProtocolError("protocol 6 messages must be arrays"); + } + command = message[0], options = message[1]; + if (command !== 'refresh') { + throw new ProtocolError("unknown protocol 6 command"); + } + return this.handlers.message({ + command: 'reload', + path: options.path, + liveCSS: (_ref = options.apply_css_live) != null ? _ref : true + }); + } else { + message = this._parseMessage(data, ['reload', 'alert']); + return this.handlers.message(message); + } + } catch (e) { + if (e instanceof ProtocolError) { + return this.handlers.error(e); + } else { + throw e; + } + } + }; + Parser.prototype._parseMessage = function(data, validCommands) { + var message, _ref; + try { + message = JSON.parse(data); + } catch (e) { + throw new ProtocolError('unparsable JSON', data); + } + if (!message.command) { + throw new ProtocolError('missing "command" key', data); + } + if (_ref = message.command, __indexOf.call(validCommands, _ref) < 0) { + throw new ProtocolError("invalid command '" + message.command + "', only valid commands are: " + (validCommands.join(', ')) + ")", data); + } + return message; + }; + return Parser; +})(); + +// connector +// Generated by CoffeeScript 1.3.3 +var Connector, PROTOCOL_6, PROTOCOL_7, Parser, Version, _ref; + +_ref = __protocol, Parser = _ref.Parser, PROTOCOL_6 = _ref.PROTOCOL_6, PROTOCOL_7 = _ref.PROTOCOL_7; + +Version = '2.0.8'; + +__connector.Connector = Connector = (function() { + + function Connector(options, WebSocket, Timer, handlers) { + var _this = this; + this.options = options; + this.WebSocket = WebSocket; + this.Timer = Timer; + this.handlers = handlers; + this._uri = "ws://" + this.options.host + ":" + this.options.port + "/livereload"; + this._nextDelay = this.options.mindelay; + this._connectionDesired = false; + this.protocol = 0; + this.protocolParser = new Parser({ + connected: function(protocol) { + _this.protocol = protocol; + _this._handshakeTimeout.stop(); + _this._nextDelay = _this.options.mindelay; + _this._disconnectionReason = 'broken'; + return _this.handlers.connected(protocol); + }, + error: function(e) { + _this.handlers.error(e); + return _this._closeOnError(); + }, + message: function(message) { + return _this.handlers.message(message); + } + }); + this._handshakeTimeout = new Timer(function() { + if (!_this._isSocketConnected()) { + return; + } + _this._disconnectionReason = 'handshake-timeout'; + return _this.socket.close(); + }); + this._reconnectTimer = new Timer(function() { + if (!_this._connectionDesired) { + return; + } + return _this.connect(); + }); + this.connect(); + } + + Connector.prototype._isSocketConnected = function() { + return this.socket && this.socket.readyState === this.WebSocket.OPEN; + }; + + Connector.prototype.connect = function() { + var _this = this; + this._connectionDesired = true; + if (this._isSocketConnected()) { + return; + } + this._reconnectTimer.stop(); + this._disconnectionReason = 'cannot-connect'; + this.protocolParser.reset(); + this.handlers.connecting(); + this.socket = new this.WebSocket(this._uri); + this.socket.onopen = function(e) { + return _this._onopen(e); + }; + this.socket.onclose = function(e) { + return _this._onclose(e); + }; + this.socket.onmessage = function(e) { + return _this._onmessage(e); + }; + return this.socket.onerror = function(e) { + return _this._onerror(e); + }; + }; + + Connector.prototype.disconnect = function() { + this._connectionDesired = false; + this._reconnectTimer.stop(); + if (!this._isSocketConnected()) { + return; + } + this._disconnectionReason = 'manual'; + return this.socket.close(); + }; + + Connector.prototype._scheduleReconnection = function() { + if (!this._connectionDesired) { + return; + } + if (!this._reconnectTimer.running) { + this._reconnectTimer.start(this._nextDelay); + return this._nextDelay = Math.min(this.options.maxdelay, this._nextDelay * 2); + } + }; + + Connector.prototype.sendCommand = function(command) { + if (this.protocol == null) { + return; + } + return this._sendCommand(command); + }; + + Connector.prototype._sendCommand = function(command) { + return this.socket.send(JSON.stringify(command)); + }; + + Connector.prototype._closeOnError = function() { + this._handshakeTimeout.stop(); + this._disconnectionReason = 'error'; + return this.socket.close(); + }; + + Connector.prototype._onopen = function(e) { + var hello; + this.handlers.socketConnected(); + this._disconnectionReason = 'handshake-failed'; + hello = { + command: 'hello', + protocols: [PROTOCOL_6, PROTOCOL_7] + }; + hello.ver = Version; + if (this.options.ext) { + hello.ext = this.options.ext; + } + if (this.options.extver) { + hello.extver = this.options.extver; + } + if (this.options.snipver) { + hello.snipver = this.options.snipver; + } + this._sendCommand(hello); + return this._handshakeTimeout.start(this.options.handshake_timeout); + }; + + Connector.prototype._onclose = function(e) { + this.protocol = 0; + this.handlers.disconnected(this._disconnectionReason, this._nextDelay); + return this._scheduleReconnection(); + }; + + Connector.prototype._onerror = function(e) {}; + + Connector.prototype._onmessage = function(e) { + return this.protocolParser.process(e.data); + }; + + return Connector; + +})(); + +// timer +var Timer; +var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; +__timer.Timer = Timer = (function() { + function Timer(func) { + this.func = func; + this.running = false; + this.id = null; + this._handler = __bind(function() { + this.running = false; + this.id = null; + return this.func(); + }, this); + } + Timer.prototype.start = function(timeout) { + if (this.running) { + clearTimeout(this.id); + } + this.id = setTimeout(this._handler, timeout); + return this.running = true; + }; + Timer.prototype.stop = function() { + if (this.running) { + clearTimeout(this.id); + this.running = false; + return this.id = null; + } + }; + return Timer; +})(); +Timer.start = function(timeout, func) { + return setTimeout(func, timeout); +}; + +// options +var Options; +__options.Options = Options = (function() { + function Options() { + this.host = null; + this.port = 35729; + this.snipver = null; + this.ext = null; + this.extver = null; + this.mindelay = 1000; + this.maxdelay = 60000; + this.handshake_timeout = 5000; + } + Options.prototype.set = function(name, value) { + switch (typeof this[name]) { + case 'undefined': + break; + case 'number': + return this[name] = +value; + default: + return this[name] = value; + } + }; + return Options; +})(); +Options.extract = function(document) { + var element, keyAndValue, m, mm, options, pair, src, _i, _j, _len, _len2, _ref, _ref2; + _ref = document.getElementsByTagName('script'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + element = _ref[_i]; + if ((src = element.src) && (m = src.match(/^[^:]+:\/\/(.*)\/z?livereload\.js(?:\?(.*))?$/))) { + options = new Options(); + if (mm = m[1].match(/^([^\/:]+)(?::(\d+))?$/)) { + options.host = mm[1]; + if (mm[2]) { + options.port = parseInt(mm[2], 10); + } + } + if (m[2]) { + _ref2 = m[2].split('&'); + for (_j = 0, _len2 = _ref2.length; _j < _len2; _j++) { + pair = _ref2[_j]; + if ((keyAndValue = pair.split('=')).length > 1) { + options.set(keyAndValue[0].replace(/-/g, '_'), keyAndValue.slice(1).join('=')); + } + } + } + return options; + } + } + return null; +}; + +// reloader +// Generated by CoffeeScript 1.3.1 +(function() { + var IMAGE_STYLES, Reloader, numberOfMatchingSegments, pathFromUrl, pathsMatch, pickBestMatch, splitUrl; + + splitUrl = function(url) { + var hash, index, params; + if ((index = url.indexOf('#')) >= 0) { + hash = url.slice(index); + url = url.slice(0, index); + } else { + hash = ''; + } + if ((index = url.indexOf('?')) >= 0) { + params = url.slice(index); + url = url.slice(0, index); + } else { + params = ''; + } + return { + url: url, + params: params, + hash: hash + }; + }; + + pathFromUrl = function(url) { + var path; + url = splitUrl(url).url; + if (url.indexOf('file://') === 0) { + path = url.replace(/^file:\/\/(localhost)?/, ''); + } else { + path = url.replace(/^([^:]+:)?\/\/([^:\/]+)(:\d*)?\//, '/'); + } + return decodeURIComponent(path); + }; + + pickBestMatch = function(path, objects, pathFunc) { + var bestMatch, object, score, _i, _len; + bestMatch = { + score: 0 + }; + for (_i = 0, _len = objects.length; _i < _len; _i++) { + object = objects[_i]; + score = numberOfMatchingSegments(path, pathFunc(object)); + if (score > bestMatch.score) { + bestMatch = { + object: object, + score: score + }; + } + } + if (bestMatch.score > 0) { + return bestMatch; + } else { + return null; + } + }; + + numberOfMatchingSegments = function(path1, path2) { + var comps1, comps2, eqCount, len; + path1 = path1.replace(/^\/+/, '').toLowerCase(); + path2 = path2.replace(/^\/+/, '').toLowerCase(); + if (path1 === path2) { + return 10000; + } + comps1 = path1.split('/').reverse(); + comps2 = path2.split('/').reverse(); + len = Math.min(comps1.length, comps2.length); + eqCount = 0; + while (eqCount < len && comps1[eqCount] === comps2[eqCount]) { + ++eqCount; + } + return eqCount; + }; + + pathsMatch = function(path1, path2) { + return numberOfMatchingSegments(path1, path2) > 0; + }; + + IMAGE_STYLES = [ + { + selector: 'background', + styleNames: ['backgroundImage'] + }, { + selector: 'border', + styleNames: ['borderImage', 'webkitBorderImage', 'MozBorderImage'] + } + ]; + + __reloader.Reloader = Reloader = (function() { + + Reloader.name = 'Reloader'; + + function Reloader(window, console, Timer) { + this.window = window; + this.console = console; + this.Timer = Timer; + this.document = this.window.document; + this.importCacheWaitPeriod = 200; + this.plugins = []; + } + + Reloader.prototype.addPlugin = function(plugin) { + return this.plugins.push(plugin); + }; + + Reloader.prototype.analyze = function(callback) { + return results; + }; + + Reloader.prototype.reload = function(path, options) { + var plugin, _base, _i, _len, _ref; + this.options = options; + if ((_base = this.options).stylesheetReloadTimeout == null) { + _base.stylesheetReloadTimeout = 15000; + } + _ref = this.plugins; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + plugin = _ref[_i]; + if (plugin.reload && plugin.reload(path, options)) { + return; + } + } + if (options.liveCSS) { + if (path.match(/\.css$/i)) { + if (this.reloadStylesheet(path)) { + return; + } + } + } + if (options.liveImg) { + if (path.match(/\.(jpe?g|png|gif)$/i)) { + this.reloadImages(path); + return; + } + } + return this.reloadPage(); + }; + + Reloader.prototype.reloadPage = function() { + return this.window.document.location.reload(); + }; + + Reloader.prototype.reloadImages = function(path) { + var expando, img, selector, styleNames, styleSheet, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3, _results; + expando = this.generateUniqueString(); + _ref = this.document.images; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + img = _ref[_i]; + if (pathsMatch(path, pathFromUrl(img.src))) { + img.src = this.generateCacheBustUrl(img.src, expando); + } + } + if (this.document.querySelectorAll) { + for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) { + _ref1 = IMAGE_STYLES[_j], selector = _ref1.selector, styleNames = _ref1.styleNames; + _ref2 = this.document.querySelectorAll("[style*=" + selector + "]"); + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + img = _ref2[_k]; + this.reloadStyleImages(img.style, styleNames, path, expando); + } + } + } + if (this.document.styleSheets) { + _ref3 = this.document.styleSheets; + _results = []; + for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { + styleSheet = _ref3[_l]; + _results.push(this.reloadStylesheetImages(styleSheet, path, expando)); + } + return _results; + } + }; + + Reloader.prototype.reloadStylesheetImages = function(styleSheet, path, expando) { + var rule, rules, styleNames, _i, _j, _len, _len1; + try { + rules = styleSheet != null ? styleSheet.cssRules : void 0; + } catch (e) { + + } + if (!rules) { + return; + } + for (_i = 0, _len = rules.length; _i < _len; _i++) { + rule = rules[_i]; + switch (rule.type) { + case CSSRule.IMPORT_RULE: + this.reloadStylesheetImages(rule.styleSheet, path, expando); + break; + case CSSRule.STYLE_RULE: + for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) { + styleNames = IMAGE_STYLES[_j].styleNames; + this.reloadStyleImages(rule.style, styleNames, path, expando); + } + break; + case CSSRule.MEDIA_RULE: + this.reloadStylesheetImages(rule, path, expando); + } + } + }; + + Reloader.prototype.reloadStyleImages = function(style, styleNames, path, expando) { + var newValue, styleName, value, _i, _len, + _this = this; + for (_i = 0, _len = styleNames.length; _i < _len; _i++) { + styleName = styleNames[_i]; + value = style[styleName]; + if (typeof value === 'string') { + newValue = value.replace(/\burl\s*\(([^)]*)\)/, function(match, src) { + if (pathsMatch(path, pathFromUrl(src))) { + return "url(" + (_this.generateCacheBustUrl(src, expando)) + ")"; + } else { + return match; + } + }); + if (newValue !== value) { + style[styleName] = newValue; + } + } + } + }; + + Reloader.prototype.reloadStylesheet = function(path) { + var imported, link, links, match, style, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, + _this = this; + links = (function() { + var _i, _len, _ref, _results; + _ref = this.document.getElementsByTagName('link'); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + if (link.rel === 'stylesheet' && !link.__LiveReload_pendingRemoval) { + _results.push(link); + } + } + return _results; + }).call(this); + imported = []; + _ref = this.document.getElementsByTagName('style'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + style = _ref[_i]; + if (style.sheet) { + this.collectImportedStylesheets(style, style.sheet, imported); + } + } + for (_j = 0, _len1 = links.length; _j < _len1; _j++) { + link = links[_j]; + this.collectImportedStylesheets(link, link.sheet, imported); + } + if (this.window.StyleFix && this.document.querySelectorAll) { + _ref1 = this.document.querySelectorAll('style[data-href]'); + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + style = _ref1[_k]; + links.push(style); + } + } + this.console.log("LiveReload found " + links.length + " LINKed stylesheets, " + imported.length + " @imported stylesheets"); + match = pickBestMatch(path, links.concat(imported), function(l) { + return pathFromUrl(_this.linkHref(l)); + }); + if (match) { + if (match.object.rule) { + this.console.log("LiveReload is reloading imported stylesheet: " + match.object.href); + this.reattachImportedRule(match.object); + } else { + this.console.log("LiveReload is reloading stylesheet: " + (this.linkHref(match.object))); + this.reattachStylesheetLink(match.object); + } + } else { + this.console.log("LiveReload will reload all stylesheets because path '" + path + "' did not match any specific one"); + for (_l = 0, _len3 = links.length; _l < _len3; _l++) { + link = links[_l]; + this.reattachStylesheetLink(link); + } + } + return true; + }; + + Reloader.prototype.collectImportedStylesheets = function(link, styleSheet, result) { + var index, rule, rules, _i, _len; + try { + rules = styleSheet != null ? styleSheet.cssRules : void 0; + } catch (e) { + + } + if (rules && rules.length) { + for (index = _i = 0, _len = rules.length; _i < _len; index = ++_i) { + rule = rules[index]; + switch (rule.type) { + case CSSRule.CHARSET_RULE: + continue; + case CSSRule.IMPORT_RULE: + result.push({ + link: link, + rule: rule, + index: index, + href: rule.href + }); + this.collectImportedStylesheets(link, rule.styleSheet, result); + break; + default: + break; + } + } + } + }; + + Reloader.prototype.waitUntilCssLoads = function(clone, func) { + var callbackExecuted, executeCallback, poll, + _this = this; + callbackExecuted = false; + executeCallback = function() { + if (callbackExecuted) { + return; + } + callbackExecuted = true; + return func(); + }; + clone.onload = function() { + console.log("onload!"); + _this.knownToSupportCssOnLoad = true; + return executeCallback(); + }; + if (!this.knownToSupportCssOnLoad) { + (poll = function() { + if (clone.sheet) { + console.log("polling!"); + return executeCallback(); + } else { + return _this.Timer.start(50, poll); + } + })(); + } + return this.Timer.start(this.options.stylesheetReloadTimeout, executeCallback); + }; + + Reloader.prototype.linkHref = function(link) { + return link.href || link.getAttribute('data-href'); + }; + + Reloader.prototype.reattachStylesheetLink = function(link) { + var clone, parent, + _this = this; + if (link.__LiveReload_pendingRemoval) { + return; + } + link.__LiveReload_pendingRemoval = true; + if (link.tagName === 'STYLE') { + clone = this.document.createElement('link'); + clone.rel = 'stylesheet'; + clone.media = link.media; + clone.disabled = link.disabled; + } else { + clone = link.cloneNode(false); + } + clone.href = this.generateCacheBustUrl(this.linkHref(link)); + parent = link.parentNode; + if (parent.lastChild === link) { + parent.appendChild(clone); + } else { + parent.insertBefore(clone, link.nextSibling); + } + return this.waitUntilCssLoads(clone, function() { + var additionalWaitingTime; + if (/AppleWebKit/.test(navigator.userAgent)) { + additionalWaitingTime = 5; + } else { + additionalWaitingTime = 200; + } + return _this.Timer.start(additionalWaitingTime, function() { + var _ref; + if (!link.parentNode) { + return; + } + link.parentNode.removeChild(link); + clone.onreadystatechange = null; + return (_ref = _this.window.StyleFix) != null ? _ref.link(clone) : void 0; + }); + }); + }; + + Reloader.prototype.reattachImportedRule = function(_arg) { + var href, index, link, media, newRule, parent, rule, tempLink, + _this = this; + rule = _arg.rule, index = _arg.index, link = _arg.link; + parent = rule.parentStyleSheet; + href = this.generateCacheBustUrl(rule.href); + media = rule.media.length ? [].join.call(rule.media, ', ') : ''; + newRule = "@import url(\"" + href + "\") " + media + ";"; + rule.__LiveReload_newHref = href; + tempLink = this.document.createElement("link"); + tempLink.rel = 'stylesheet'; + tempLink.href = href; + tempLink.__LiveReload_pendingRemoval = true; + if (link.parentNode) { + link.parentNode.insertBefore(tempLink, link); + } + return this.Timer.start(this.importCacheWaitPeriod, function() { + if (tempLink.parentNode) { + tempLink.parentNode.removeChild(tempLink); + } + if (rule.__LiveReload_newHref !== href) { + return; + } + parent.insertRule(newRule, index); + parent.deleteRule(index + 1); + rule = parent.cssRules[index]; + rule.__LiveReload_newHref = href; + return _this.Timer.start(_this.importCacheWaitPeriod, function() { + if (rule.__LiveReload_newHref !== href) { + return; + } + parent.insertRule(newRule, index); + return parent.deleteRule(index + 1); + }); + }); + }; + + Reloader.prototype.generateUniqueString = function() { + return 'livereload=' + Date.now(); + }; + + Reloader.prototype.generateCacheBustUrl = function(url, expando) { + var hash, oldParams, params, _ref; + if (expando == null) { + expando = this.generateUniqueString(); + } + _ref = splitUrl(url), url = _ref.url, hash = _ref.hash, oldParams = _ref.params; + if (this.options.overrideURL) { + if (url.indexOf(this.options.serverURL) < 0) { + url = this.options.serverURL + this.options.overrideURL + "?url=" + encodeURIComponent(url); + } + } + params = oldParams.replace(/(\?|&)livereload=(\d+)/, function(match, sep) { + return "" + sep + expando; + }); + if (params === oldParams) { + if (oldParams.length === 0) { + params = "?" + expando; + } else { + params = "" + oldParams + "&" + expando; + } + } + return url + params + hash; + }; + + return Reloader; + + })(); + +}).call(this); + +// livereload +var Connector, LiveReload, Options, Reloader, Timer; + +Connector = __connector.Connector; + +Timer = __timer.Timer; + +Options = __options.Options; + +Reloader = __reloader.Reloader; + +__livereload.LiveReload = LiveReload = (function() { + + function LiveReload(window) { + var _this = this; + this.window = window; + this.listeners = {}; + this.plugins = []; + this.pluginIdentifiers = {}; + this.console = this.window.location.href.match(/LR-verbose/) && this.window.console && this.window.console.log && this.window.console.error ? this.window.console : { + log: function() {}, + error: function() {} + }; + if (!(this.WebSocket = this.window.WebSocket || this.window.MozWebSocket)) { + console.error("LiveReload disabled because the browser does not seem to support web sockets"); + return; + } + if (!(this.options = Options.extract(this.window.document))) { + console.error("LiveReload disabled because it could not find its own + + + + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/examples/ws.html b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/examples/ws.html new file mode 100644 index 0000000..e322f2a --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/examples/ws.html @@ -0,0 +1,44 @@ + + + + + WebSocket test + + + +

      WebSocket test

      +
        + + + + + + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/eventsource.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/eventsource.js new file mode 100644 index 0000000..eab3a46 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/eventsource.js @@ -0,0 +1,110 @@ +var API = require('./websocket/api'), + Event = require('./websocket/api/event'); + +var isSecureConnection = function(request) { + if (request.headers['x-forwarded-proto']) { + return request.headers['x-forwarded-proto'] === 'https'; + } else { + return (request.connection && request.connection.authorized !== undefined) || + (request.socket && request.socket.secure); + } +}; + +var EventSource = function(request, response, options) { + options = options || {}; + + this._request = request; + this._response = response; + this._stream = response.socket; + this._ping = options.ping || this.DEFAULT_PING; + this._retry = options.retry || this.DEFAULT_RETRY; + + var scheme = isSecureConnection(request) ? 'https:' : 'http:'; + this.url = scheme + '//' + request.headers.host + request.url; + + this.lastEventId = request.headers['last-event-id'] || ''; + + var self = this; + this.readyState = API.CONNECTING; + this._sendBuffer = []; + process.nextTick(function() { self._open() }); + + var handshake = 'HTTP/1.1 200 OK\r\n' + + 'Content-Type: text/event-stream\r\n' + + 'Cache-Control: no-cache, no-store\r\n' + + 'Connection: close\r\n' + + '\r\n\r\n' + + 'retry: ' + Math.floor(this._retry * 1000) + '\r\n\r\n'; + + this.readyState = API.OPEN; + + if (this._ping) + this._pingLoop = setInterval(function() { self.ping() }, this._ping * 1000); + + if (!this._stream || !this._stream.writable) return; + + this._stream.setTimeout(0); + this._stream.setNoDelay(true); + + try { this._stream.write(handshake, 'utf8') } catch (e) {} + + ['close', 'end', 'error'].forEach(function(event) { + self._stream.addListener(event, function() { self.close() }); + }); +}; + +EventSource.isEventSource = function(request) { + var accept = (request.headers.accept || '').split(/\s*,\s*/); + return accept.indexOf('text/event-stream') >= 0; +}; + +var instance = { + DEFAULT_PING: 10, + DEFAULT_RETRY: 5, + + send: function(message, options) { + if (this.readyState !== API.OPEN) return false; + + message = String(message).replace(/(\r\n|\r|\n)/g, '$1data: '); + options = options || {}; + + var frame = ''; + if (options.event) frame += 'event: ' + options.event + '\r\n'; + if (options.id) frame += 'id: ' + options.id + '\r\n'; + frame += 'data: ' + message + '\r\n\r\n'; + + try { + this._stream.write(frame, 'utf8'); + return true; + } catch (e) { + return false; + } + }, + + ping: function() { + try { + this._stream.write(':\r\n\r\n', 'utf8'); + return true; + } catch (e) { + return false; + } + }, + + close: function() { + if (this.readyState === API.CLOSING || this.readyState === API.CLOSED) + return; + + this.readyState = API.CLOSED; + clearInterval(this._pingLoop); + this._response.end(); + + var event = new Event('close'); + event.initEvent('close', false, false); + this.dispatchEvent(event); + } +}; + +for (var key in API) EventSource.prototype[key] = API[key]; +for (var key in instance) EventSource.prototype[key] = instance[key]; +module.exports = EventSource; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket.js new file mode 100644 index 0000000..bbf9d29 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket.js @@ -0,0 +1,93 @@ +// API and protocol references: +// +// * http://dev.w3.org/html5/websockets/ +// * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#interface-eventtarget +// * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#interface-event +// * http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75 +// * http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76 +// * http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17 + +var Draft75Parser = require('./websocket/draft75_parser'), + Draft76Parser = require('./websocket/draft76_parser'), + HybiParser = require('./websocket/hybi_parser'), + API = require('./websocket/api'), + Event = require('./websocket/api/event'); + +var getParser = function(request) { + var headers = request.headers; + return headers['sec-websocket-version'] + ? HybiParser + : (headers['sec-websocket-key1'] && headers['sec-websocket-key2']) + ? Draft76Parser + : Draft75Parser; +}; + +var isSecureConnection = function(request) { + if (request.headers['x-forwarded-proto']) { + return request.headers['x-forwarded-proto'] === 'https'; + } else { + return (request.connection && request.connection.authorized !== undefined) || + (request.socket && request.socket.secure); + } +}; + +var WebSocket = function(request, socket, head, supportedProtos, options) { + this.request = request; + this._stream = request.socket; + this._ping = options && options.ping; + this._pingId = 0; + + var scheme = isSecureConnection(request) ? 'wss:' : 'ws:'; + this.url = scheme + '//' + request.headers.host + request.url; + this.readyState = API.CONNECTING; + this.bufferedAmount = 0; + + var Parser = getParser(request); + this._parser = new Parser(this, {protocols: supportedProtos}); + + var self = this; + this._sendBuffer = []; + process.nextTick(function() { self._open() }); + + var handshake = this._parser.handshakeResponse(head); + if (this._parser.isOpen()) this.readyState = API.OPEN; + + if (this._ping) + this._pingLoop = setInterval(function() { + self._pingId += 1; + self.ping(self._pingId.toString()); + }, this._ping * 1000); + + this.protocol = this._parser.protocol || ''; + this.version = this._parser.getVersion(); + + if (!this._stream || !this._stream.writable) return; + + this._stream.setTimeout(0); + this._stream.setNoDelay(true); + + try { this._stream.write(handshake, 'binary') } catch (e) {} + + this._stream.addListener('data', function(data) { + var response = self._parser.parse(data); + if (!response) return; + try { self._stream.write(response, 'binary') } catch (e) {} + self._open(); + }); + ['close', 'end', 'error'].forEach(function(event) { + self._stream.addListener(event, function() { self.close(1006, '', false) }); + }); +}; + +WebSocket.prototype.ping = function(message, callback, context) { + if (!this._parser.ping) return false; + return this._parser.ping(message, callback, context); +}; + +for (var key in API) WebSocket.prototype[key] = API[key]; + +WebSocket.WebSocket = WebSocket; +WebSocket.Client = require('./websocket/client'); +WebSocket.EventSource = require('./eventsource'); +module.exports = WebSocket; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/api.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/api.js new file mode 100644 index 0000000..6c37e27 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/api.js @@ -0,0 +1,88 @@ +var EventTarget = require('./api/event_target'), + Event = require('./api/event'); + +var API = { + CONNECTING: 0, + OPEN: 1, + CLOSING: 2, + CLOSED: 3, + + _open: function() { + if (this._parser && !this._parser.isOpen()) return; + this.readyState = API.OPEN; + + var buffer = this._sendBuffer || [], + message; + + while (message = buffer.shift()) + this.send.apply(this, message); + + var event = new Event('open'); + event.initEvent('open', false, false); + this.dispatchEvent(event); + }, + + receive: function(data) { + if (this.readyState !== API.OPEN) return false; + var event = new Event('message'); + event.initEvent('message', false, false); + event.data = data; + this.dispatchEvent(event); + }, + + send: function(data, type, errorType) { + if (this.readyState === API.CONNECTING) { + if (this._sendBuffer) { + this._sendBuffer.push(arguments); + return true; + } else { + throw new Error('Cannot call send(), socket is not open yet'); + } + } + + if (this.readyState === API.CLOSED) + return false; + + if (!(data instanceof Buffer)) data = String(data); + + var frame = this._parser.frame(data, type, errorType); + try { + this._stream.write(frame, 'binary'); + return true; + } catch (e) { + return false; + } + }, + + close: function(code, reason, ack) { + if (this.readyState === API.CLOSED) return; + if (this.readyState === API.CLOSING && ack !== false) return; + + var finalize = function() { + this.readyState = API.CLOSED; + if (this._pingLoop) clearInterval(this._pingLoop); + if (this._stream) this._stream.end(); + var event = new Event('close', {code: code || 1000, reason: reason || ''}); + event.initEvent('close', false, false); + this.dispatchEvent(event); + }; + + if (this.readyState === API.CONNECTING) + return finalize.call(this); + + this.readyState = API.CLOSING; + + if (ack === false) { + if (this._parser.close) this._parser.close(code, reason); + finalize.call(this); + } else { + if (this._parser.close) this._parser.close(code, reason, finalize, this); + else finalize.call(this); + } + } +}; + +for (var key in EventTarget) API[key] = EventTarget[key]; + +module.exports = API; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/api/event.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/api/event.js new file mode 100644 index 0000000..2f707d8 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/api/event.js @@ -0,0 +1,21 @@ +var Event = function(eventType, options) { + this.type = eventType; + for (var key in options) + this[key] = options[key]; +}; + +Event.prototype.initEvent = function(eventType, canBubble, cancelable) { + this.type = eventType; + this.bubbles = canBubble; + this.cancelable = cancelable; +}; + +Event.prototype.stopPropagation = function() {}; +Event.prototype.preventDefault = function() {}; + +Event.CAPTURING_PHASE = 1; +Event.AT_TARGET = 2; +Event.BUBBLING_PHASE = 3; + +module.exports = Event; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/api/event_target.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/api/event_target.js new file mode 100644 index 0000000..056a8f4 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/api/event_target.js @@ -0,0 +1,47 @@ +var Event = require('./event'); + +var EventTarget = { + onopen: null, + onmessage: null, + onerror: null, + onclose: null, + + addEventListener: function(eventType, listener, useCapture) { + this._listeners = this._listeners || {}; + var list = this._listeners[eventType] = this._listeners[eventType] || []; + list.push(listener); + }, + + removeEventListener: function(eventType, listener, useCapture) { + if (!this._listeners || !this._listeners[eventType]) return; + + if (!listener) { + delete this._listeners[eventType]; + return; + } + var list = this._listeners[eventType], + i = list.length; + + while (i--) { + if (listener !== list[i]) continue; + list.splice(i,1); + } + }, + + dispatchEvent: function(event) { + event.target = event.currentTarget = this; + event.eventPhase = Event.AT_TARGET; + + if (this['on' + event.type]) + this['on' + event.type](event); + + if (!this._listeners || !this._listeners[event.type]) return; + + this._listeners[event.type].forEach(function(listener) { + listener(event); + }, this); + } +}; + +module.exports = EventTarget; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/client.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/client.js new file mode 100644 index 0000000..cde0002 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/client.js @@ -0,0 +1,86 @@ +var net = require('net'), + tls = require('tls'); + +var HybiParser = require('./hybi_parser'), + API = require('./api'), + Event = require('./api/event'); + +var Client = function(url, protocols, options) { + this.url = url; + this._uri = require('url').parse(url); + + this.protocol = ''; + this.readyState = API.CONNECTING; + this.bufferedAmount = 0; + + var secure = (this._uri.protocol === 'wss:'), + self = this, + onConnect = function() { self._onConnect() }, + tlsOptions = {}; + + if (options && options.verify === false) tlsOptions.rejectUnauthorized = false; + + var connection = secure + ? tls.connect(this._uri.port || 443, this._uri.hostname, tlsOptions, onConnect) + : net.createConnection(this._uri.port || 80, this._uri.hostname); + + this._parser = new HybiParser(this, {masking: true, protocols: protocols}); + this._stream = connection; + + this._stream.setTimeout(0); + this._stream.setNoDelay(true); + + if (!secure) connection.addListener('connect', onConnect); + + connection.addListener('data', function(data) { + self._onData(data); + }); + ['close', 'end', 'error'].forEach(function(event) { + connection.addListener(event, function() { self.close(1006, '', false) }); + }); +}; + +Client.prototype._onConnect = function() { + this._handshake = this._parser.createHandshake(this._uri, this._stream); + this._message = []; + try { + this._stream.write(this._handshake.requestData(), 'binary'); + } catch (e) {} +}; + +Client.prototype._onData = function(data) { + switch (this.readyState) { + case API.CONNECTING: + var bytes = this._handshake.parse(data); + for (var i = 0, n = bytes.length; i < n; i++) + this._message.push(bytes[i]); + + if (!this._handshake.isComplete()) return; + + if (this._handshake.isValid()) { + this.protocol = this._handshake.protocol || ''; + this.readyState = API.OPEN; + var event = new Event('open'); + event.initEvent('open', false, false); + this.dispatchEvent(event); + + this._parser.parse(this._message); + + } else { + this.readyState = API.CLOSED; + var event = new Event('close', {code: 1006, reason: ''}); + event.initEvent('close', false, false); + this.dispatchEvent(event); + } + break; + + case API.OPEN: + case API.CLOSING: + this._parser.parse(data); + } +}; + +for (var key in API) Client.prototype[key] = API[key]; + +module.exports = Client; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/draft75_parser.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/draft75_parser.js new file mode 100644 index 0000000..b4e00aa --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/draft75_parser.js @@ -0,0 +1,98 @@ +var Draft75Parser = function(webSocket) { + this._socket = webSocket; + this._stage = 0; +}; + +var instance = { + getVersion: function() { + return 'hixie-75'; + }, + + handshakeResponse: function() { + return new Buffer('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' + + 'Upgrade: WebSocket\r\n' + + 'Connection: Upgrade\r\n' + + 'WebSocket-Origin: ' + this._socket.request.headers.origin + '\r\n' + + 'WebSocket-Location: ' + this._socket.url + '\r\n\r\n', + 'utf8'); + }, + + isOpen: function() { + return true; + }, + + parse: function(buffer) { + var data, message, value; + for (var i = 0, n = buffer.length; i < n; i++) { + data = buffer[i]; + + switch (this._stage) { + case 0: + this._parseLeadingByte(data); + break; + + case 1: + value = (data & 0x7F); + this._length = value + 128 * this._length; + + if (this._closing && this._length === 0) { + this._socket.close(null, null, false); + } + else if ((0x80 & data) !== 0x80) { + if (this._length === 0) { + this._socket.receive(''); + this._stage = 0; + } + else { + this._buffer = []; + this._stage = 2; + } + } + break; + + case 2: + if (data === 0xFF) { + message = new Buffer(this._buffer); + this._socket.receive(message.toString('utf8', 0, this._buffer.length)); + this._stage = 0; + } + else { + this._buffer.push(data); + if (this._length && this._buffer.length === this._length) + this._stage = 0; + } + break; + } + } + }, + + _parseLeadingByte: function(data) { + if ((0x80 & data) === 0x80) { + this._length = 0; + this._stage = 1; + } else { + delete this._length; + this._buffer = []; + this._stage = 2; + } + }, + + frame: function(data) { + if (Buffer.isBuffer(data)) return data; + + var buffer = new Buffer(data, 'utf8'), + frame = new Buffer(buffer.length + 2); + + frame[0] = 0x00; + frame[buffer.length + 1] = 0xFF; + buffer.copy(frame, 1); + + return frame; + } +}; + +for (var key in instance) + Draft75Parser.prototype[key] = instance[key]; + +module.exports = Draft75Parser; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/draft76_parser.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/draft76_parser.js new file mode 100644 index 0000000..82da1a0 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/draft76_parser.js @@ -0,0 +1,99 @@ +var crypto = require('crypto'), + Draft75Parser = require('./draft75_parser'), + Draft76Parser = function() { Draft75Parser.apply(this, arguments) }; + +var bridge = function() {}; +bridge.prototype = Draft75Parser.prototype; +Draft76Parser.prototype = new bridge(); + +var numberFromKey = function(key) { + return parseInt(key.match(/[0-9]/g).join(''), 10); +}; + +var spacesInKey = function(key) { + return key.match(/ /g).length; +}; + +var bigEndian = function(number) { + var string = ''; + [24,16,8,0].forEach(function(offset) { + string += String.fromCharCode(number >> offset & 0xFF); + }); + return string; +}; + +Draft76Parser.prototype.getVersion = function() { + return 'hixie-76'; +}; + +Draft76Parser.prototype.handshakeResponse = function(head) { + var request = this._socket.request, tmp; + + var response = new Buffer('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' + + 'Upgrade: WebSocket\r\n' + + 'Connection: Upgrade\r\n' + + 'Sec-WebSocket-Origin: ' + request.headers.origin + '\r\n' + + 'Sec-WebSocket-Location: ' + this._socket.url + '\r\n\r\n', + 'binary'); + + var signature = this.handshakeSignature(head); + if (signature) { + tmp = new Buffer(response.length + signature.length); + response.copy(tmp, 0); + signature.copy(tmp, response.length); + response = tmp; + } + + return response; +}; + +Draft76Parser.prototype.isOpen = function() { + return !!this._handshakeComplete; +}; + +Draft76Parser.prototype.handshakeSignature = function(head) { + if (head.length === 0) return null; + + var request = this._socket.request, + + key1 = request.headers['sec-websocket-key1'], + value1 = numberFromKey(key1) / spacesInKey(key1), + + key2 = request.headers['sec-websocket-key2'], + value2 = numberFromKey(key2) / spacesInKey(key2), + + MD5 = crypto.createHash('md5'); + + MD5.update(bigEndian(value1)); + MD5.update(bigEndian(value2)); + MD5.update(head.toString('binary')); + + this._handshakeComplete = true; + return new Buffer(MD5.digest('binary'), 'binary'); +}; + +Draft76Parser.prototype.parse = function(data) { + if (this._handshakeComplete) + return Draft75Parser.prototype.parse.call(this, data); + + return this.handshakeSignature(data); +}; + +Draft76Parser.prototype._parseLeadingByte = function(data) { + if (data !== 0xFF) + return Draft75Parser.prototype._parseLeadingByte.call(this, data); + + this._closing = true; + this._length = 0; + this._stage = 1; +}; + +Draft76Parser.prototype.close = function(code, reason, callback, context) { + if (this._closed) return; + if (this._closing) this._socket.send(new Buffer([0xFF, 0x00])); + this._closed = true; + if (callback) callback.call(context); +}; + +module.exports = Draft76Parser; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/hybi_parser.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/hybi_parser.js new file mode 100644 index 0000000..57464da --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/hybi_parser.js @@ -0,0 +1,355 @@ +var crypto = require('crypto'), + Handshake = require('./hybi_parser/handshake'), + Reader = require('./hybi_parser/stream_reader'); + +var HybiParser = function(webSocket, options) { + this._reset(); + this._socket = webSocket; + this._reader = new Reader(); + this._stage = 0; + this._masking = options && options.masking; + this._protocols = options && options.protocols; + + this._pingCallbacks = {}; + + if (typeof this._protocols === 'string') + this._protocols = this._protocols.split(/\s*,\s*/); +}; + +HybiParser.mask = function(payload, mask, offset) { + if (mask.length === 0) return payload; + offset = offset || 0; + + for (var i = 0, n = payload.length - offset; i < n; i++) { + payload[offset + i] = payload[offset + i] ^ mask[i % 4]; + } + return payload; +}; + +var instance = { + BYTE: 255, + FIN: 128, + MASK: 128, + RSV1: 64, + RSV2: 32, + RSV3: 16, + OPCODE: 15, + LENGTH: 127, + + OPCODES: { + continuation: 0, + text: 1, + binary: 2, + close: 8, + ping: 9, + pong: 10 + }, + + ERRORS: { + normal_closure: 1000, + going_away: 1001, + protocol_error: 1002, + unacceptable: 1003, + encoding_error: 1007, + policy_violation: 1008, + too_large: 1009, + extension_error: 1010, + unexpected_condition: 1011 + }, + + FRAGMENTED_OPCODES: [0,1,2], + OPENING_OPCODES: [1,2], + + ERROR_CODES: [1000,1001,1002,1003,1007,1008,1009,1010,1011], + + UTF8_MATCH: /^([\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})*$/, + + getVersion: function() { + var version = this._socket.request.headers['sec-websocket-version']; + return 'hybi-' + version; + }, + + handshakeResponse: function() { + var secKey = this._socket.request.headers['sec-websocket-key']; + if (!secKey) return null; + + var SHA1 = crypto.createHash('sha1'); + SHA1.update(secKey + Handshake.GUID); + + var accept = SHA1.digest('base64'), + protos = this._socket.request.headers['sec-websocket-protocol'], + supported = this._protocols, + proto, + + headers = [ + 'HTTP/1.1 101 Switching Protocols', + 'Upgrade: websocket', + 'Connection: Upgrade', + 'Sec-WebSocket-Accept: ' + accept + ]; + + if (protos !== undefined && supported !== undefined) { + if (typeof protos === 'string') protos = protos.split(/\s*,\s*/); + proto = protos.filter(function(p) { return supported.indexOf(p) >= 0 })[0]; + if (proto) { + this.protocol = proto; + headers.push('Sec-WebSocket-Protocol: ' + proto); + } + } + + return new Buffer(headers.concat('','').join('\r\n'), 'utf8'); + }, + + isOpen: function() { + return true; + }, + + createHandshake: function(uri) { + return new Handshake(uri, this._protocols); + }, + + parse: function(data) { + this._reader.put(data); + var buffer = true; + while (buffer) { + switch (this._stage) { + case 0: + buffer = this._reader.read(1); + if (buffer) this._parseOpcode(buffer[0]); + break; + + case 1: + buffer = this._reader.read(1); + if (buffer) this._parseLength(buffer[0]); + break; + + case 2: + buffer = this._reader.read(this._lengthSize); + if (buffer) this._parseExtendedLength(buffer); + break; + + case 3: + buffer = this._reader.read(4); + if (buffer) { + this._mask = buffer; + this._stage = 4; + } + break; + + case 4: + buffer = this._reader.read(this._length); + if (buffer) { + this._payload = buffer; + this._emitFrame(); + this._stage = 0; + } + break; + } + } + }, + + _parseOpcode: function(data) { + var rsvs = [this.RSV1, this.RSV2, this.RSV3].filter(function(rsv) { + return (data & rsv) === rsv; + }, this); + + if (rsvs.length > 0) return this._socket.close(this.ERRORS.protocol_error, null, false); + + this._final = (data & this.FIN) === this.FIN; + this._opcode = (data & this.OPCODE); + this._mask = []; + this._payload = []; + + var valid = false; + + for (var key in this.OPCODES) { + if (this.OPCODES[key] === this._opcode) + valid = true; + } + if (!valid) return this._socket.close(this.ERRORS.protocol_error, null, false); + + if (this.FRAGMENTED_OPCODES.indexOf(this._opcode) < 0 && !this._final) + return this._socket.close(this.ERRORS.protocol_error, null, false); + + if (this._mode && this.OPENING_OPCODES.indexOf(this._opcode) >= 0) + return this._socket.close(this.ERRORS.protocol_error, null, false); + + this._stage = 1; + }, + + _parseLength: function(data) { + this._masked = (data & this.MASK) === this.MASK; + this._length = (data & this.LENGTH); + + if (this._length >= 0 && this._length <= 125) { + this._stage = this._masked ? 3 : 4; + } else { + this._lengthBuffer = []; + this._lengthSize = (this._length === 126 ? 2 : 8); + this._stage = 2; + } + }, + + _parseExtendedLength: function(buffer) { + this._length = this._getInteger(buffer); + this._stage = this._masked ? 3 : 4; + }, + + frame: function(data, type, code) { + if (this._closed) return null; + + var isText = (typeof data === 'string'), + opcode = this.OPCODES[type || (isText ? 'text' : 'binary')], + buffer = isText ? new Buffer(data, 'utf8') : data, + insert = code ? 2 : 0, + length = buffer.length + insert, + header = (length <= 125) ? 2 : (length <= 65535 ? 4 : 10), + offset = header + (this._masking ? 4 : 0), + masked = this._masking ? this.MASK : 0, + frame = new Buffer(length + offset), + BYTE = this.BYTE, + mask, i; + + frame[0] = this.FIN | opcode; + + if (length <= 125) { + frame[1] = masked | length; + } else if (length <= 65535) { + frame[1] = masked | 126; + frame[2] = Math.floor(length / 256); + frame[3] = length & BYTE; + } else { + frame[1] = masked | 127; + frame[2] = Math.floor(length / Math.pow(2,56)) & BYTE; + frame[3] = Math.floor(length / Math.pow(2,48)) & BYTE; + frame[4] = Math.floor(length / Math.pow(2,40)) & BYTE; + frame[5] = Math.floor(length / Math.pow(2,32)) & BYTE; + frame[6] = Math.floor(length / Math.pow(2,24)) & BYTE; + frame[7] = Math.floor(length / Math.pow(2,16)) & BYTE; + frame[8] = Math.floor(length / Math.pow(2,8)) & BYTE; + frame[9] = length & BYTE; + } + + if (code) { + frame[offset] = Math.floor(code / 256) & BYTE; + frame[offset+1] = code & BYTE; + } + buffer.copy(frame, offset + insert); + + if (this._masking) { + mask = [Math.floor(Math.random() * 256), Math.floor(Math.random() * 256), + Math.floor(Math.random() * 256), Math.floor(Math.random() * 256)]; + new Buffer(mask).copy(frame, header); + HybiParser.mask(frame, mask, offset); + } + + return frame; + }, + + ping: function(message, callback, context) { + message = message || ''; + if (callback) this._pingCallbacks[message] = [callback, context]; + return this._socket.send(message, 'ping'); + }, + + close: function(code, reason, callback, context) { + if (this._closed) return; + if (callback) this._closingCallback = [callback, context]; + this._socket.send(reason || '', 'close', code || this.ERRORS.normal_closure); + this._closed = true; + }, + + buffer: function(fragment) { + for (var i = 0, n = fragment.length; i < n; i++) + this._buffer.push(fragment[i]); + }, + + _emitFrame: function() { + var payload = HybiParser.mask(this._payload, this._mask), + opcode = this._opcode; + + if (opcode === this.OPCODES.continuation) { + if (!this._mode) return this._socket.close(this.ERRORS.protocol_error, null, false); + this.buffer(payload); + if (this._final) { + var message = new Buffer(this._buffer); + if (this._mode === 'text') message = this._encode(message); + this._reset(); + if (message !== null) this._socket.receive(message); + else this._socket.close(this.ERRORS.encoding_error, null, false); + } + } + else if (opcode === this.OPCODES.text) { + if (this._final) { + var message = this._encode(payload); + if (message !== null) this._socket.receive(message); + else this._socket.close(this.ERRORS.encoding_error, null, false); + } else { + this._mode = 'text'; + this.buffer(payload); + } + } + else if (opcode === this.OPCODES.binary) { + if (this._final) { + this._socket.receive(payload); + } else { + this._mode = 'binary'; + this.buffer(payload); + } + } + else if (opcode === this.OPCODES.close) { + var code = (payload.length >= 2) ? 256 * payload[0] + payload[1] : null, + reason = (payload.length > 2) ? this._encode(payload.slice(2)) : null; + + if (!(payload.length === 0) && + !(code !== null && code >= 3000 && code < 5000) && + this.ERROR_CODES.indexOf(code) < 0) + code = this.ERRORS.protocol_error; + + if (payload.length > 125 || (payload.length > 2 && !reason)) + code = this.ERRORS.protocol_error; + + this._socket.close(code, (payload.length > 2) ? reason : null, false); + if (this._closingCallback) + this._closingCallback[0].call(this._closingCallback[1]); + } + else if (opcode === this.OPCODES.ping) { + if (payload.length > 125) return this._socket.close(this.ERRORS.protocol_error, null, false); + this._socket.send(payload, 'pong'); + } + else if (opcode === this.OPCODES.pong) { + var callbacks = this._pingCallbacks, + message = this._encode(payload), + callback = callbacks[message]; + + delete callbacks[message]; + if (callback) callback[0].call(callback[1]); + } + }, + + _reset: function() { + this._mode = null; + this._buffer = []; + }, + + _encode: function(buffer) { + try { + var string = buffer.toString('binary', 0, buffer.length); + if (!this.UTF8_MATCH.test(string)) return null; + } catch (e) {} + return buffer.toString('utf8', 0, buffer.length); + }, + + _getInteger: function(bytes) { + var number = 0; + for (var i = 0, n = bytes.length; i < n; i++) + number += bytes[i] << (8 * (n - 1 - i)); + return number; + } +}; + +for (var key in instance) + HybiParser.prototype[key] = instance[key]; + +module.exports = HybiParser; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/hybi_parser/handshake.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/hybi_parser/handshake.js new file mode 100644 index 0000000..0a75191 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/hybi_parser/handshake.js @@ -0,0 +1,91 @@ +var crypto = require('crypto'); + +var Handshake = function(uri, protocols) { + this._uri = uri; + this._protocols = protocols; + + var buffer = new Buffer(16), i = 16; + while (i--) buffer[i] = Math.floor(Math.random() * 256); + this._key = buffer.toString('base64'); + + var SHA1 = crypto.createHash('sha1'); + SHA1.update(this._key + Handshake.GUID); + this._accept = SHA1.digest('base64'); + + var HTTPParser = process.binding('http_parser').HTTPParser, + parser = new HTTPParser(HTTPParser.RESPONSE || 'response'), + current = null, + self = this; + + this._nodeVersion = HTTPParser.RESPONSE ? 6 : 4; + this._complete = false; + this._headers = {}; + this._parser = parser; + + parser.onHeaderField = function(b, start, length) { + current = b.toString('utf8', start, start + length); + }; + parser.onHeaderValue = function(b, start, length) { + self._headers[current] = b.toString('utf8', start, start + length); + }; + parser.onHeadersComplete = function(info) { + self._status = info.statusCode; + var headers = info.headers; + if (!headers) return; + for (var i = 0, n = headers.length; i < n; i += 2) + self._headers[headers[i]] = headers[i+1]; + }; + parser.onMessageComplete = function() { + self._complete = true; + }; +}; + +Handshake.GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'; + +Handshake.prototype.requestData = function() { + var u = this._uri; + + var headers = [ + 'GET ' + (u.pathname || '/') + (u.search || '') + ' HTTP/1.1', + 'Host: ' + u.hostname + (u.port ? ':' + u.port : ''), + 'Upgrade: websocket', + 'Connection: Upgrade', + 'Sec-WebSocket-Key: ' + this._key, + 'Sec-WebSocket-Version: 13' + ]; + + if (this._protocols) + headers.push('Sec-WebSocket-Protocol: ' + this._protocols.join(', ')); + + return new Buffer(headers.concat('','').join('\r\n'), 'utf8'); +}; + +Handshake.prototype.parse = function(data) { + var consumed = this._parser.execute(data, 0, data.length), + offset = (this._nodeVersion < 6) ? 1 : 0; + + return (consumed === data.length) ? [] : data.slice(consumed + offset); +}; + +Handshake.prototype.isComplete = function() { + return this._complete; +}; + +Handshake.prototype.isValid = function() { + if (this._status !== 101) return false; + + var upgrade = this._headers.Upgrade, + connection = this._headers.Connection, + protocol = this._headers['Sec-WebSocket-Protocol']; + + this.protocol = this._protocols && this._protocols.indexOf(protocol) >= 0 + ? protocol + : null; + + return upgrade && /^websocket$/i.test(upgrade) && + connection && connection.split(/\s*,\s*/).indexOf('Upgrade') >= 0 && + ((!this._protocols && !protocol) || this.protocol) && + this._headers['Sec-WebSocket-Accept'] === this._accept; +}; + +module.exports = Handshake; diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/hybi_parser/stream_reader.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/hybi_parser/stream_reader.js new file mode 100644 index 0000000..01e607f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/lib/faye/websocket/hybi_parser/stream_reader.js @@ -0,0 +1,43 @@ +var StreamReader = function() { + this._queue = []; + this._cursor = 0; +}; + +StreamReader.prototype.read = function(bytes) { + return this._readBuffer(bytes); +}; + +StreamReader.prototype.put = function(buffer) { + if (!buffer || buffer.length === 0) return; + if (!buffer.copy) buffer = new Buffer(buffer); + this._queue.push(buffer); +}; + +StreamReader.prototype._readBuffer = function(length) { + var buffer = new Buffer(length), + queue = this._queue, + remain = length, + n = queue.length, + i = 0, + chunk, offset, size; + + if (remain === 0) return buffer; + + while (remain > 0 && i < n) { + chunk = queue[i]; + offset = (i === 0) ? this._cursor : 0; + size = Math.min(remain, chunk.length - offset); + chunk.copy(buffer, length - remain, offset, offset + size); + remain -= size; + i += 1; + } + + if (remain > 0) return null; + + queue.splice(0, i-1); + this._cursor = (i === 1 ? this._cursor : 0) + size; + + return buffer; +}; + +module.exports = StreamReader; diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/package.json b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/package.json new file mode 100644 index 0000000..126573f --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/package.json @@ -0,0 +1,53 @@ +{ + "name": "faye-websocket", + "description": "Standards-compliant WebSocket server and client", + "homepage": "http://github.com/faye/faye-websocket-node", + "author": { + "name": "James Coglan", + "email": "jcoglan@gmail.com", + "url": "http://jcoglan.com/" + }, + "keywords": [ + "websocket", + "eventsource" + ], + "version": "0.4.4", + "engines": { + "node": ">=0.4.0" + }, + "main": "./lib/faye/websocket", + "devDependencies": { + "jsclass": "", + "pace": "" + }, + "scripts": { + "test": "node spec/runner.js" + }, + "bugs": { + "url": "http://github.com/faye/faye-websocket-node/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "http://www.opensource.org/licenses/mit-license.php" + } + ], + "repositories": [ + { + "type": "git", + "url": "git://github.com/faye/faye-websocket-node.git" + } + ], + "readme": "# faye-websocket\n\n* Travis CI build: [](http://travis-ci.org/faye/faye-websocket-node)\n* Autobahn tests: [server](http://faye.jcoglan.com/autobahn/servers/), [client](http://faye.jcoglan.com/autobahn/clients/)\n\nThis is a robust, general-purpose WebSocket implementation extracted from the\n[Faye](http://faye.jcoglan.com) project. It provides classes for easily building\nWebSocket servers and clients in Node. It does not provide a server itself, but\nrather makes it easy to handle WebSocket connections within an existing\n[Node](http://nodejs.org/) application. It does not provide any abstraction\nother than the standard [WebSocket API](http://dev.w3.org/html5/websockets/).\n\nIt also provides an abstraction for handling [EventSource](http://dev.w3.org/html5/eventsource/)\nconnections, which are one-way connections that allow the server to push data to\nthe client. They are based on streaming HTTP responses and can be easier to\naccess via proxies than WebSockets.\n\nThe server-side socket can process [draft-75](http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75),\n[draft-76](http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76),\n[hybi-07](http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-07)\nand later versions of the protocol. It selects protocol versions automatically,\nsupports both `text` and `binary` messages, and transparently handles `ping`,\n`pong`, `close` and fragmented messages.\n\n\n## Handling WebSocket connections in Node\n\nYou can handle WebSockets on the server side by listening for HTTP Upgrade\nrequests, and creating a new socket for the request. This socket object exposes\nthe usual WebSocket methods for receiving and sending messages. For example this\nis how you'd implement an echo server:\n\n```js\nvar WebSocket = require('faye-websocket'),\n http = require('http');\n\nvar server = http.createServer();\n\nserver.addListener('upgrade', function(request, socket, head) {\n var ws = new WebSocket(request, socket, head);\n \n ws.onmessage = function(event) {\n ws.send(event.data);\n };\n \n ws.onclose = function(event) {\n console.log('close', event.code, event.reason);\n ws = null;\n };\n});\n\nserver.listen(8000);\n```\n\nNote that under certain circumstances (notably a draft-76 client connecting\nthrough an HTTP proxy), the WebSocket handshake will not be complete after you\ncall `new WebSocket()` because the server will not have received the entire\nhandshake from the client yet. In this case, calls to `ws.send()` will buffer\nthe message in memory until the handshake is complete, at which point any\nbuffered messages will be sent to the client.\n\nIf you need to detect when the WebSocket handshake is complete, you can use the\n`onopen` event.\n\nIf the connection's protocol version supports it, you can call `ws.ping()` to\nsend a ping message and wait for the client's response. This method takes a\nmessage string, and an optional callback that fires when a matching pong message\nis received. It returns `true` iff a ping message was sent. If the client does\nnot support ping/pong, this method sends no data and returns `false`.\n\n```js\nws.ping('Mic check, one, two', function() {\n // fires when pong is received\n});\n```\n\n\n## Using the WebSocket client\n\nThe client supports both the plain-text `ws` protocol and the encrypted `wss`\nprotocol, and has exactly the same interface as a socket you would use in a web\nbrowser. On the wire it identifies itself as hybi-13.\n\n```js\nvar WebSocket = require('faye-websocket'),\n ws = new WebSocket.Client('ws://www.example.com/');\n\nws.onopen = function(event) {\n console.log('open');\n ws.send('Hello, world!');\n};\n\nws.onmessage = function(event) {\n console.log('message', event.data);\n};\n\nws.onclose = function(event) {\n console.log('close', event.code, event.reason);\n ws = null;\n};\n```\n\n\n## Subprotocol negotiation\n\nThe WebSocket protocol allows peers to select and identify the application\nprotocol to use over the connection. On the client side, you can set which\nprotocols the client accepts by passing a list of protocol names when you\nconstruct the socket:\n\n```js\nvar ws = new WebSocket.Client('ws://www.example.com/', ['irc', 'amqp']);\n```\n\nOn the server side, you can likewise pass in the list of protocols the server\nsupports after the other constructor arguments:\n\n```js\nvar ws = new WebSocket(request, socket, head, ['irc', 'amqp']);\n```\n\nIf the client and server agree on a protocol, both the client- and server-side\nsocket objects expose the selected protocol through the `ws.protocol` property.\nIf they cannot agree on a protocol to use, the client closes the connection.\n\n\n## WebSocket API\n\nThe WebSocket API consists of several event handlers and a method for sending\nmessages.\n\n* onopen fires when the socket connection is established. Event\n has no attributes.\n* onerror fires when the connection attempt fails. Event has no\n attributes.\n* onmessage fires when the socket receives a message. Event has\n one attribute, data, which is either a `String` (for text\n frames) or a `Buffer` (for binary frames).\n* onclose fires when either the client or the server closes the\n connection. Event has two optional attributes, code and\n reason, that expose the status code and message sent by the\n peer that closed the connection.\n* send(message) accepts either a `String` or a `Buffer` and\n sends a text or binary message over the connection to the other peer.\n* close(code, reason) closes the connection, sending the given\n status code and reason text, both of which are optional.\n* protocol is a string (which may be empty) identifying the\n subprotocol the socket is using.\n\n\n## Handling EventSource connections in Node\n\nEventSource connections provide a very similar interface, although because they\nonly allow the server to send data to the client, there is no `onmessage` API.\nEventSource allows the server to push text messages to the client, where each\nmessage has an optional event-type and ID.\n\n```js\nvar WebSocket = require('faye-websocket'),\n EventSource = WebSocket.EventSource,\n http = require('http');\n\nvar server = http.createServer();\n\nserver.addListener('request', function(request, response) {\n if (EventSource.isEventSource(request)) {\n var es = new EventSource(request, response);\n console.log('open', es.url, es.lastEventId);\n \n // Periodically send messages\n var loop = setInterval(function() { es.send('Hello') }, 1000);\n \n es.onclose = function() {\n clearInterval(loop);\n es = null;\n };\n \n } else {\n // Normal HTTP request\n response.writeHead(200, {'Content-Type': 'text/plain'});\n response.write('Hello');\n response.end();\n }\n});\n\nserver.listen(8000);\n```\n\nThe `send` method takes two optional parameters, `event` and `id`. The default\nevent-type is `'message'` with no ID. For example, to send a `notification`\nevent with ID `99`:\n\n```js\nes.send('Breaking News!', {event: 'notification', id: '99'});\n```\n\nThe `EventSource` object exposes the following properties:\n\n* url is a string containing the URL the client used to create\n the EventSource.\n* lastEventId is a string containing the last event ID\n received by the client. You can use this when the client reconnects after a\n dropped connection to determine which messages need resending.\n\nWhen you initialize an EventSource with ` new EventSource()`, you can pass\nconfiguration options after the `response` parameter. Available options are:\n\n* retry is a number that tells the client how long (in seconds)\n it should wait after a dropped connection before attempting to reconnect.\n* ping is a number that tells the server how often (in seconds)\n to send 'ping' packets to the client to keep the connection open, to defeat\n timeouts set by proxies. The client will ignore these messages.\n\nFor example, this creates a connection that pings every 15 seconds and is\nretryable every 10 seconds if the connection is broken:\n\n```js\nvar es = new EventSource(request, response, {ping: 15, retry: 10});\n```\n\nYou can send a ping message at any time by calling `es.ping()`. Unlike WebSocket,\nthe client does not send a response to this; it is merely to send some data over\nthe wire to keep the connection alive.\n\n\n## License\n\n(The MIT License)\n\nCopyright (c) 2009-2013 James Coglan\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the 'Software'), to deal in\nthe Software without restriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell copies of the\nSoftware, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n", + "readmeFilename": "README.markdown", + "repository": { + "type": "git", + "url": "git://github.com/faye/faye-websocket-node.git" + }, + "_id": "faye-websocket@0.4.4", + "dist": { + "shasum": "3b01a2b716103cab5e5b3202e973b9702096d17e" + }, + "_from": "faye-websocket@~0.4.3", + "_resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.4.4.tgz" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/client_spec.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/client_spec.js new file mode 100644 index 0000000..e9aa6bc --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/client_spec.js @@ -0,0 +1,175 @@ +var Client = require('../../../lib/faye/websocket/client') + +JS.ENV.WebSocketSteps = JS.Test.asyncSteps({ + server: function(port, secure, callback) { + this._adapter = new EchoServer() + this._adapter.listen(port, secure) + this._port = port + setTimeout(callback, 100) + }, + + stop: function(callback) { + this._adapter.stop() + setTimeout(callback, 100) + }, + + open_socket: function(url, protocols, callback) { + var done = false, + self = this, + + resume = function(open) { + if (done) return + done = true + self._open = open + callback() + } + + this._ws = new Client(url, protocols, {verify: false}) + + this._ws.onopen = function() { resume(true) } + this._ws.onclose = function() { resume(false) } + }, + + close_socket: function(callback) { + var self = this + this._ws.onclose = function() { + self._open = false + callback() + } + this._ws.close() + }, + + check_open: function(callback) { + this.assert( this._open ) + callback() + }, + + check_closed: function(callback) { + this.assert( !this._open ) + callback() + }, + + check_protocol: function(protocol, callback) { + this.assertEqual( protocol, this._ws.protocol ) + callback() + }, + + listen_for_message: function(callback) { + var self = this + this._ws.addEventListener('message', function(message) { self._message = message.data }) + callback() + }, + + send_message: function(message, callback) { + this._ws.send(message) + setTimeout(callback, 100) + }, + + check_response: function(message, callback) { + this.assertEqual( message, this._message ) + callback() + }, + + check_no_response: function(callback) { + this.assert( !this._message ) + callback() + } +}) + + +JS.ENV.ClientSpec = JS.Test.describe("Client", function() { with(this) { + include(WebSocketSteps) + + before(function() { + this.protocols = ["foo", "echo"] + this.plain_text_url = "ws://localhost:8000/bayeux" + this.secure_url = "wss://localhost:8000/bayeux" + }) + + sharedBehavior("socket client", function() { with(this) { + it("can open a connection", function() { with(this) { + open_socket(socket_url, protocols) + check_open() + check_protocol("echo") + }}) + + it("cannot open a connection with unacceptable protocols", function() { with(this) { + open_socket(socket_url, ["foo"]) + check_closed() + }}) + + it("can close the connection", function() { with(this) { + open_socket(socket_url, protocols) + close_socket() + check_closed() + }}) + + describe("in the OPEN state", function() { with(this) { + before(function() { with(this) { + open_socket(socket_url, protocols) + }}) + + it("can send and receive messages", function() { with(this) { + listen_for_message() + send_message("I expect this to be echoed") + check_response("I expect this to be echoed") + }}) + + it("sends numbers as strings", function() { with(this) { + listen_for_message() + send_message(13) + check_response("13") + }}) + + it("sends booleans as strings", function() { with(this) { + listen_for_message() + send_message(false) + check_response("false") + }}) + + it("sends arrays as strings", function() { with(this) { + listen_for_message() + send_message([13,14,15]) + check_response("13,14,15") + }}) + }}) + + describe("in the CLOSED state", function() { with(this) { + before(function() { with(this) { + open_socket(socket_url, protocols) + close_socket() + }}) + + it("cannot send and receive messages", function() { with(this) { + listen_for_message() + send_message("I expect this to be echoed") + check_no_response() + }}) + }}) + }}) + + describe("with a plain-text server", function() { with(this) { + before(function() { + this.socket_url = this.plain_text_url + this.blocked_url = this.secure_url + }) + + before(function() { this.server(8000, false) }) + after (function() { this.stop() }) + + behavesLike("socket client") + }}) + + describe("with a secure server", function() { with(this) { + before(function() { + this.socket_url = this.secure_url + this.blocked_url = this.plain_text_url + }) + + before(function() { this.server(8000, true) }) + after (function() { this.stop() }) + + behavesLike("socket client") + }}) +}}) + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/draft75parser_spec.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/draft75parser_spec.js new file mode 100644 index 0000000..6197193 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/draft75parser_spec.js @@ -0,0 +1,72 @@ +var Draft75Parser = require('../../../lib/faye/websocket/draft75_parser') + +JS.ENV.Draft75ParserSpec = JS.Test.describe("Draft75Parser", function() { with(this) { + before(function() { with(this) { + this.webSocket = {dispatchEvent: function() {}} + this.parser = new Draft75Parser(webSocket) + }}) + + describe("parse", function() { with(this) { + sharedBehavior("draft-75 parser", function() { with(this) { + it("parses text frames", function() { with(this) { + expect(webSocket, "receive").given("Hello") + parser.parse([0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff]) + }}) + + it("parses multiple frames from the same packet", function() { with(this) { + expect(webSocket, "receive").given("Hello").exactly(2) + parser.parse([0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff]) + }}) + + it("parses text frames beginning 0x00-0x7F", function() { with(this) { + expect(webSocket, "receive").given("Hello") + parser.parse([0x66, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff]) + }}) + + it("ignores frames with a length header", function() { with(this) { + expect(webSocket, "receive").exactly(0) + parser.parse([0x80, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f]) + }}) + + it("parses text following an ignored block", function() { with(this) { + expect(webSocket, "receive").given("Hello") + parser.parse([0x80, 0x02, 0x48, 0x65, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff]) + }}) + + it("parses multibyte text frames", function() { with(this) { + expect(webSocket, "receive").given("Apple = ") + parser.parse([0x00, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff]) + }}) + + it("parses frames received in several packets", function() { with(this) { + expect(webSocket, "receive").given("Apple = ") + parser.parse([0x00, 0x41, 0x70, 0x70, 0x6c, 0x65]) + parser.parse([0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff]) + }}) + + it("parses fragmented frames", function() { with(this) { + expect(webSocket, "receive").given("Hello") + parser.parse([0x00, 0x48, 0x65, 0x6c]) + parser.parse([0x6c, 0x6f, 0xff]) + }}) + }}) + + behavesLike("draft-75 parser") + + it("does not close the socket if a 76 close frame is received", function() { with(this) { + expect(webSocket, "close").exactly(0) + expect(webSocket, "receive").given("") + parser.parse([0xFF, 0x00]) + }}) + }}) + + describe("frame", function() { with(this) { + it("returns the given string formatted as a WebSocket frame", function() { with(this) { + assertBufferEqual( [0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff], parser.frame("Hello") ) + }}) + + it("encodes multibyte characters correctly", function() { with(this) { + assertBufferEqual( [0x00, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff], parser.frame("Apple = ") ) + }}) + }}) +}}) diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/draft76parser_spec.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/draft76parser_spec.js new file mode 100644 index 0000000..775c1e3 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/draft76parser_spec.js @@ -0,0 +1,28 @@ +var Draft76Parser = require('../../../lib/faye/websocket/draft76_parser') + +JS.ENV.Draft76ParserSpec = JS.Test.describe("Draft76Parser", function() { with(this) { + before(function() { with(this) { + this.webSocket = {dispatchEvent: function() {}} + this.parser = new Draft76Parser(webSocket) + parser._handshakeComplete = true + }}) + + describe("parse", function() { with(this) { + behavesLike("draft-75 parser") + + it("closes the socket if a close frame is received", function() { with(this) { + expect(webSocket, "close") + parser.parse([0xFF, 0x00]) + }}) + }}) + + describe("frame", function() { with(this) { + it("returns the given string formatted as a WebSocket frame", function() { with(this) { + assertBufferEqual( [0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff], parser.frame("Hello") ) + }}) + + it("encodes multibyte characters correctly", function() { with(this) { + assertBufferEqual( [0x00, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff], parser.frame("Apple = ") ) + }}) + }}) +}}) diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/hybi_parser_spec.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/hybi_parser_spec.js new file mode 100644 index 0000000..5531b9d --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/faye/websocket/hybi_parser_spec.js @@ -0,0 +1,148 @@ +var HybiParser = require('../../../lib/faye/websocket/hybi_parser') + +JS.ENV.HybiParserSpec = JS.Test.describe("HybiParser", function() { with(this) { + before(function() { with(this) { + this.webSocket = {dispatchEvent: function() {}} + this.parser = new HybiParser(webSocket) + }}) + + define("parse", function() { + var bytes = []; + for (var i = 0, n = arguments.length; i < n; i++) bytes = bytes.concat(arguments[i]) + this.parser.parse(new Buffer(bytes)) + }) + + define("buffer", function(string) { + return { + equals: function(buffer) { + return buffer.toString('utf8', 0, buffer.length) === string + } + } + }) + + describe("parse", function() { with(this) { + define("mask", function() { + return this._mask = this._mask || [1,2,3,4].map(function() { return Math.floor(Math.random() * 255) }) + }) + + define("maskMessage", function(bytes) { + var output = [] + Array.prototype.forEach.call(bytes, function(b, i) { + output[i] = bytes[i] ^ this.mask()[i % 4] + }, this) + return output + }) + + it("parses unmasked text frames", function() { with(this) { + expect(webSocket, "receive").given("Hello") + parse([0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f]) + }}) + + it("parses multiple frames from the same packet", function() { with(this) { + expect(webSocket, "receive").given("Hello").exactly(2) + parse([0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f]) + }}) + + it("parses empty text frames", function() { with(this) { + expect(webSocket, "receive").given("") + parse([0x81, 0x00]) + }}) + + it("parses fragmented text frames", function() { with(this) { + expect(webSocket, "receive").given("Hello") + parse([0x01, 0x03, 0x48, 0x65, 0x6c]) + parse([0x80, 0x02, 0x6c, 0x6f]) + }}) + + it("parses masked text frames", function() { with(this) { + expect(webSocket, "receive").given("Hello") + parse([0x81, 0x85], mask(), maskMessage([0x48, 0x65, 0x6c, 0x6c, 0x6f])) + }}) + + it("parses masked empty text frames", function() { with(this) { + expect(webSocket, "receive").given("") + parse([0x81, 0x80], mask(), maskMessage([])) + }}) + + it("parses masked fragmented text frames", function() { with(this) { + expect(webSocket, "receive").given("Hello") + parse([0x01, 0x81], mask(), maskMessage([0x48])) + parse([0x80, 0x84], mask(), maskMessage([0x65, 0x6c, 0x6c, 0x6f])) + }}) + + it("closes the socket if the frame has an unrecognized opcode", function() { with(this) { + expect(webSocket, "close").given(1002, null, false) + parse([0x83, 0x00]) + }}) + + it("closes the socket if a close frame is received", function() { with(this) { + expect(webSocket, "close").given(1000, "Hello", false) + parse([0x88, 0x07, 0x03, 0xe8, 0x48, 0x65, 0x6c, 0x6c, 0x6f]) + }}) + + it("parses unmasked multibyte text frames", function() { with(this) { + expect(webSocket, "receive").given("Apple = ") + parse([0x81, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf]) + }}) + + it("parses frames received in several packets", function() { with(this) { + expect(webSocket, "receive").given("Apple = ") + parse([0x81, 0x0b, 0x41, 0x70, 0x70, 0x6c]) + parse([0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf]) + }}) + + it("parses fragmented multibyte text frames", function() { with(this) { + expect(webSocket, "receive").given("Apple = ") + parse([0x01, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3]) + parse([0x80, 0x01, 0xbf]) + }}) + + it("parses masked multibyte text frames", function() { with(this) { + expect(webSocket, "receive").given("Apple = ") + parse([0x81, 0x8b], mask(), maskMessage([0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf])) + }}) + + it("parses masked fragmented multibyte text frames", function() { with(this) { + expect(webSocket, "receive").given("Apple = ") + parse([0x01, 0x8a], mask(), maskMessage([0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3])) + parse([0x80, 0x81], mask(), maskMessage([0xbf])) + }}) + + it("parses unmasked medium-length text frames", function() { with(this) { + expect(webSocket, "receive").given("HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello") + parse([129, 126, 0, 200, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111]) + }}) + + it("parses masked medium-length text frames", function() { with(this) { + expect(webSocket, "receive").given("HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello") + parse([129, 254, 0, 200], mask(), maskMessage([72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111])) + }}) + + it("replies to pings with a pong", function() { with(this) { + expect(webSocket, "send").given(buffer("OHAI"), "pong") + parse([0x89, 0x04, 0x4f, 0x48, 0x41, 0x49]) + }}) + }}) + + describe("frame", function() { with(this) { + it("returns the given string formatted as a WebSocket frame", function() { with(this) { + assertBufferEqual( [0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f], parser.frame("Hello") ) + }}) + + it("encodes multibyte characters correctly", function() { with(this) { + assertBufferEqual( [0x81, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf], parser.frame("Apple = ") ) + }}) + + it("encodes medium-length strings using extra length bytes", function() { with(this) { + assertBufferEqual( [129, 126, 0, 200, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111, 72, 101, 108, 108, 111], parser.frame("HelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHelloHello") ) + }}) + + it("encodes close frames with an error code", function() { with(this) { + assertBufferEqual( [0x88, 0x07, 0x03, 0xea, 0x48, 0x65, 0x6c, 0x6c, 0x6f], parser.frame("Hello", "close", 1002) ) + }}) + + it("encodes pong frames", function() { with(this) { + assertBufferEqual( [0x8a, 0x00], parser.frame("", "pong") ) + }}) + }}) +}}) diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/runner.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/runner.js new file mode 100644 index 0000000..68ad93e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/runner.js @@ -0,0 +1,54 @@ +require('jsclass') + +var WebSocket = require('../lib/faye/websocket'), + fs = require('fs'), + http = require('http'), + https = require('https') + + +JS.ENV.EchoServer = function() {} +EchoServer.prototype.listen = function(port, ssl) { + var server = ssl + ? https.createServer({ + key: fs.readFileSync(__dirname + '/server.key'), + cert: fs.readFileSync(__dirname + '/server.crt') + }) + : http.createServer() + + server.addListener('upgrade', function(request, socket, head) { + var ws = new WebSocket(request, socket, head, ["echo"]) + ws.onmessage = function(event) { + ws.send(event.data) + } + }) + this._httpServer = server + server.listen(port) +} +EchoServer.prototype.stop = function(callback, scope) { + this._httpServer.addListener('close', function() { + if (callback) callback.call(scope); + }); + this._httpServer.close(); +} + + +JS.Packages(function() { with(this) { + autoload(/.*Spec/, {from: 'spec/faye/websocket'}) +}}) + + +JS.require('JS.Test', function() { + JS.Test.Unit.Assertions.define("assertBufferEqual", function(array, buffer) { + this.assertEqual(array.length, buffer.length); + var ary = [], n = buffer.length; + while (n--) ary[n] = buffer[n]; + this.assertEqual(array, ary); + }) + + JS.require( 'ClientSpec', + 'Draft75ParserSpec', + 'Draft76ParserSpec', + 'HybiParserSpec', + JS.Test.method('autorun')) +}) + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/server.crt b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/server.crt new file mode 100644 index 0000000..ade70de --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/server.crt @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICZTCCAc4CCQDxyrJZrFA0vjANBgkqhkiG9w0BAQUFADB3MQswCQYDVQQGEwJV +SzEPMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDTALBgNVBAoTBEZh +eWUxFTATBgNVBAMTDEphbWVzIENvZ2xhbjEgMB4GCSqGSIb3DQEJARYRamNvZ2xh +bkBnbWFpbC5jb20wHhcNMTEwODMwMTIzOTM2WhcNMTIwODI5MTIzOTM2WjB3MQsw +CQYDVQQGEwJVSzEPMA0GA1UECBMGTG9uZG9uMQ8wDQYDVQQHEwZMb25kb24xDTAL +BgNVBAoTBEZheWUxFTATBgNVBAMTDEphbWVzIENvZ2xhbjEgMB4GCSqGSIb3DQEJ +ARYRamNvZ2xhbkBnbWFpbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB +AMDjU5fAK7fvUCZIYHcGXDZD/m9bY+B/UcwGcowk0hMQGYNlLKrpiK7xXBmZpDb6 +r8n+7L/epBeSumbRIm4TDzeNHhuQGYLIeGQy7JNLoPBr6GxubjuJhKOOBnCqcupR +CLGG7Zw5oL4UvtZVH6kL9XnjyokQQbxxeoV9DqtqOaHHAgMBAAEwDQYJKoZIhvcN +AQEFBQADgYEAvQjSpzE1ahaeH1CmbLwckTxvWMZfxcZOrxTruK1po3cNnDOjGqFQ +KEkNj3K5WfwTBD4QgUdYDykhDX2m6HaMz4JEbgrwQv8M8FiswIA3dyGsbOifOk8H +r3GPNKMzm4o6vrn6RGOpt9q6bsWUBUHfNpP93uU2C9QEwDua3cFjDA0= +-----END CERTIFICATE----- diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/server.key b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/server.key new file mode 100644 index 0000000..85aba2d --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/faye-websocket/spec/server.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXAIBAAKBgQDA41OXwCu371AmSGB3Blw2Q/5vW2Pgf1HMBnKMJNITEBmDZSyq +6Yiu8VwZmaQ2+q/J/uy/3qQXkrpm0SJuEw83jR4bkBmCyHhkMuyTS6Dwa+hsbm47 +iYSjjgZwqnLqUQixhu2cOaC+FL7WVR+pC/V548qJEEG8cXqFfQ6rajmhxwIDAQAB +AoGABlk1DiCQD8y7mZb2PdSiwlJ4lFewsNnf6lQn/v7TPzdfb5ir4LAxBHkDLACH +jBuyH3bZefMs+W2l3u5xMKhF7uJqYcUlJdH2UwRfNG54Hn4SGAjQOK3ONer99sUf +USlsWSX1HjAAFMCBwUfKxMZA3VNQfYKTPdm0jSVf85kHO1ECQQD3s6ksm3QpfD0L +eG9EoDrqmwnEfpKoWPpz1O0i5tY9VcmhmLwS5Zpd7lB1qjTqzZk4RygU73T/BseJ +azehIHK5AkEAx1mSXt+ec8RfzVi/io6oqi2vOcACXRbOG4NQmqUWPnumdwsJjsjR +RzEoDFC2lu6448p9sgEq+CkbmgVeiyp4fwJAQnmgySve/NMuvslPcyddKGD7OhSN +30ghzrwx98/jZwqC1i9bKeccimDOjwVitjD/Ea9m/ldVGqwDGMoBX+iJYQJAEIOO +CYfyw1pQKV2huGOq+zX/nwQV7go2lrbhFX55gkGR/6iNaSOfmosq6yJAje5GqLAc +i4NnQNl+7NpnA5ZIFwJBAI1+OsZyjbRI99pYkTdOpa5IPlIb3j3JbSfjAWHLxlRY +0HLvN3Q1mE9kbB+uKH6syF/S7nALgsLgq7eHYvIaE/A= +-----END RSA PRIVATE KEY----- diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/.npmignore b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/.npmignore new file mode 100644 index 0000000..2e84c13 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/.npmignore @@ -0,0 +1 @@ +.travis.yml diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/actions/collectable.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/actions/collectable.js new file mode 100644 index 0000000..f8fe9ee --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/actions/collectable.js @@ -0,0 +1,94 @@ + +var fs = require('fs'); + +// Collectable Mixin +// +// Provides utility methods to read from stdin and remaining arguments. +var collectable = module.exports; + +// XXX: tomdocify, generate in readme + +collectable.stdin = function stdin(force, done) { + if(!done) done = force, force = false; + var argv = this.nopt.argv; + var self = this; + done = done || function(err) { err && self.emit('error', err); }; + + this._readFromStdin = true; + + // not parsed, register done to be read when parse is called + if(!argv) { + this.once('stdin', done); + return this; + } + + // only read from stdin when no reamining args and not forced + if(!argv.remain.length || force) { + this.readStdin(done); + } + + return this; +}; + +// Read files from remaining args, concat the result and call back the `done` +// function with the concatanated result and the list of files. +collectable.files = function files(done) { + var argv = this.nopt.argv; + var self = this; + done = done || function(err) { err && self.emit('error', err); }; + + // not parsed, register done to be read when parse is called + if(!argv) { + this.once('files', done); + return this; + } + + // only read files when we actually have files to read from + if(argv.remain.length) { + this.readFiles(argv.remain, done); + } + + return this; +}; + +collectable.readStdin = function readStdin(done) { + var data = ''; + var self = this; + process.stdin.setEncoding('utf8'); + process.stdin.on('error', done); + process.stdin.on('data', function(chunk){ + data += chunk; + self.emit('stdin:data', chunk); + }).on('end', function(){ + self.emit('stdin', null, data); + done(null, data); + }).resume(); + return this; +}; + +// Asynchronous walk of the remaining args, reading the content and returns +// the concatanated result. +collectable.readFiles = function readFiles(filepaths, done) { + var data = ''; + var self = this; + var files = filepaths.slice(0); + (function read(file) { + if(!file) { + self.emit('files', null, data, filepaths); + return done(null, data, filepaths); + } + fs.readFile(file, 'utf8', function(err, body) { + if(err) return done(err); + data += body; + self.emit('files:data', body); + read(files.shift()); + }); + })(files.shift()); + return this; +}; + +// Collect data either from stdin or the list of remaining args +collectable.collect = function collect(done) { + return this.stdin(done).files(done); +}; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/actions/commandable.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/actions/commandable.js new file mode 100644 index 0000000..60d3e5c --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/actions/commandable.js @@ -0,0 +1,68 @@ +var nopt = require('nopt'); + +// Commandable Mixin +// +// Provides API to route arbitrary routes or register command / sub commands / +// sub programs. +var commandable = module.exports; + +// XXX: tomdocify, generate in readme + +commandable.cmd = +commandable.command = function command(name, fn) { + this._commands[name] = fn; + var commandable = fn && fn.command && fn.route && fn.parse; + this.on(name, commandable ? function(args, opts, position) { + fn.parse(args, position); + } : fn); + return this; +}; + +commandable.route = function route(pattern, fn) { + pattern = pattern instanceof RegExp ? pattern : new RegExp('^' + pattern + '$'); + this._routes.push({ + pattern: pattern, + fn: fn + }); + return this; +}; + +commandable.routeCommand = function routeCommand(opts) { + opts = opts || this.nopt; + var args = opts.argv.remain; + var commands = Object.keys(this._commands); + + // firt try to find a route, then fallback to command + var route = this._routes.filter(function(route) { + return route.pattern.test(args.join(' ')); + }); + + if(route.length) return route[0].fn(); + + var first = 0 + var registered = args.filter(function(arg, i) { + var match = ~commands.indexOf(arg); + if(match) first = first || i; + return match; + }); + + if(!registered[0]) return this.run(); + + opts.argv.remain = args.slice(0, first); + registered.forEach(function(command) { + var position = opts.argv.original.indexOf(command) + 1; + var options = nopt({}, {}, opts.argv.original, position); + this.emit(command, options.argv.original, options, position); + }, this); +}; + + +commandable.registered = function(args) { + var commands = Object.keys(this._commands); + var registered = args.filter(function(arg, i) { + return ~commands.indexOf(arg); + }); + + return registered.length ? this._commands[registered] : false; +}; + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/index.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/index.js new file mode 100644 index 0000000..0469cf8 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/index.js @@ -0,0 +1,253 @@ + +var fs = require('fs'); +var path = require('path'); +var nopt = require('nopt'); +var util = require('./util'); +var events = require('events'); + +var collectable = require('./actions/collectable'); +var commandable = require('./actions/commandable'); + +module.exports = noptify; +noptify.Noptify = Noptify; + +// noptify is a little wrapper around `nopt` module adding a more expressive, +// commander-like, API and few helpers. +// +// Examples +// +// var program = noptify(process.argv, { program: 'name' }) +// .version('0.0.1') +// .option('port', '-p', 'Port to listen on (default: 35729)', Number) +// .option('pid', 'Path to the generated PID file', String) +// +// var opts = program.parse(); +// +// Returns an instance of `Noptify` +function noptify(args, options) { + return new Noptify(args, options); +} + +// Noptify provides the API to parse out option, shorthands and generate the +// proper generic help output. +// +// - args - The Array of arguments to parse (default: `process.argv`); +// - options - An hash of options with the following properties +// - program - The program name to use in usage output +// +// Every noptify instance is created with two options, `-h, --help` and `-v, +// --version`. +function Noptify(args, options) { + events.EventEmitter.call(this); + options = this.options = options || {}; + this.args = args || process.argv; + this._program = options.program || (path.basename(this.args[this.args[0] === 'node' ? 1 : 0])); + + this._shorthands = {}; + this._commands = {}; + this._routes = []; + this._steps = []; + this.nopt = {}; + + this.option('help', '-h', 'Show help usage'); + this.option('version', '-v', 'Show package version'); +} + +util.inherits(Noptify, events.EventEmitter); + +// Inherits from each actions' mixins +// +// XXX: consider making it optional? with a `.use()` method? +util.extend(Noptify.prototype, collectable); +util.extend(Noptify.prototype, commandable); + + +// Parse the provided options and shorthands, pass them through `nopt` and +// return the result. +// +// When `opts.help` is set, the help output is displayed and `help` +// event is emitted. The process exists with `0` status, the help output is +// automatically displayed and the `help` event is emitted. +// +// Examples +// +// var program = noptify(['foo', '--help']) +// .on('help', function() { +// console.log('Examples'); +// console.log(''); +// console.log(' foo bar --baz > foo.txt'); +// }); +// +// var opts = program.parse(); +// // ... Help output ... +// // ... Custom help output ... +// // ... Exit ... +// +// +Noptify.prototype.parse = function parse(argv, position) { + argv = argv || this.args; + var options = this._options.reduce(function(opts, opt) { + opts[opt.name] = opt.type; + return opts; + }, {}); + + this._options.forEach(function(opt) { + if(!opt.shorthand) return; + this.shorthand(opt.shorthand, '--' + opt.name); + }, this); + + var opts = nopt(options, this._shorthands, argv, position); + if(opts.version) { + console.log(this._version); + process.exit(0); + } + + var registered = this.registered(opts.argv.remain); + if(opts.help) { + if(registered && registered.help) { + registered.help().emit('help'); + } else { + this.help().emit('help'); + } + + process.exit(0); + } + + this.nopt = opts; + + // check remaining args and registered command, for each match, remove the + // argument from remaining args and trigger the handler, ideally the handler + // can be another subprogram, for now simple functions + + if(this.routeCommand) process.nextTick(this.routeCommand.bind(this)); + if(this.stdin && this._readFromStdin) process.nextTick(this.stdin.bind(this)); + return opts; +}; + +// Define the program version. +Noptify.prototype.version = function version(ver) { + this._version = ver; + return this; +}; + +// Define the program property. +Noptify.prototype.program = function program(value) { + this._program = value || ''; + return this; +}; + +// Define `name` option with optional shorthands, optional description and optional type. +Noptify.prototype.option = function option(name, shorthand, description, type) { + this._options = this._options || []; + if(!description) { + description = shorthand; + shorthand = ''; + } + + if(!type) { + if(typeof description === 'function') { + type = description; + description = shorthand; + shorthand = ''; + } else { + type = String; + } + } + + shorthand = shorthand.replace(/^-*/, ''), + + this._options.push({ + name: name, + shorthand: shorthand.replace(/^-*/, ''), + description: description || (name + ': ' + type.name), + usage: (shorthand ? '-' + shorthand + ', ': '' ) + '--' + name, + type: type + }); + + return this; +}; + +// Stores the given `shorthands` Hash of options to be `parse()`-d by nopt +// later on. + +Noptify.prototype.shorthand = +Noptify.prototype.shorthands = function shorthands(options, value) { + if(typeof options === 'string' && value) { + this._shorthands[options] = value; + return this; + } + + Object.keys(options).forEach(function(shorthand) { + this._shorthands[shorthand] = options[shorthand]; + }, this); + return this; +}; + +// Simply output to stdout the Usage and Help output. +Noptify.prototype.help = function help() { + var buf = ''; + buf += '\n Usage: ' + this._program + ' [options]'; + buf += '\n'; + buf += '\n Options:\n'; + + var maxln = Math.max.apply(Math, this._options.map(function(opts) { + return opts.usage.length; + })); + + var options = this._options.map(function(opts) { + return ' ' + pad(opts.usage, maxln + 5) + '\t- ' + opts.description; + }); + + buf += options.join('\n'); + + // part of help input ? --list-shorthands ? + var shorthands = Object.keys(this._shorthands); + if(shorthands.length) { + buf += '\n\n Shorthands:\n'; + maxln = Math.max.apply(Math, Object.keys(this._shorthands).map(function(key) { + return key.length; + })); + buf += Object.keys(this._shorthands).map(function(shorthand) { + return ' --' + pad(shorthand, maxln + 1) + '\t\t' + this._shorthands[shorthand]; + }, this).join('\n'); + } + + buf += '\n'; + + console.log(buf); + return this; +}; + +// Helpers + +// command API + +Noptify.prototype.run = function run(fn) { + if(fn) { + this._steps.push(fn); + return this; + } + + if(!this.nopt.argv) return this.parse(); + + var steps = this._steps; + var self = this; + (function next(step) { + if(!step) return; + var async = /function\s*\(\w+/.test(step + ''); + if(!async) { + step(); + return next(steps.shift()); + } + + step(function(err) { + if(err) return self.emit('error', err); + next(steps.shift()); + }); + })(steps.shift()); +}; + +function pad(str, max) { + var ln = max - str.length; + return ln > 0 ? str + new Array(ln).join(' ') : str; +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/.bin/nopt b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/.bin/nopt new file mode 120000 index 0000000..6b6566e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/.bin/nopt @@ -0,0 +1 @@ +../nopt/bin/nopt.js \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/.npmignore b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/.npmignore new file mode 100644 index 0000000..e69de29 diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/LICENSE b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The 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. diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/README.md b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/README.md new file mode 100644 index 0000000..f290da8 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/README.md @@ -0,0 +1,210 @@ +If you want to write an option parser, and have it be good, there are +two ways to do it. The Right Way, and the Wrong Way. + +The Wrong Way is to sit down and write an option parser. We've all done +that. + +The Right Way is to write some complex configurable program with so many +options that you go half-insane just trying to manage them all, and put +it off with duct-tape solutions until you see exactly to the core of the +problem, and finally snap and write an awesome option parser. + +If you want to write an option parser, don't write an option parser. +Write a package manager, or a source control system, or a service +restarter, or an operating system. You probably won't end up with a +good one of those, but if you don't give up, and you are relentless and +diligent enough in your procrastination, you may just end up with a very +nice option parser. + +## USAGE + + // my-program.js + var nopt = require("nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + , "many" : [String, Array] + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag"] + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + console.log(parsed) + +This would give you support for any of the following: + +```bash +$ node my-program.js --foo "blerp" --no-flag +{ "foo" : "blerp", "flag" : false } + +$ node my-program.js ---bar 7 --foo "Mr. Hand" --flag +{ bar: 7, foo: "Mr. Hand", flag: true } + +$ node my-program.js --foo "blerp" -f -----p +{ foo: "blerp", flag: true, pick: true } + +$ node my-program.js -fp --foofoo +{ foo: "Mr. Foo", flag: true, pick: true } + +$ node my-program.js --foofoo -- -fp # -- stops the flag parsing. +{ foo: "Mr. Foo", argv: { remain: ["-fp"] } } + +$ node my-program.js --blatzk 1000 -fp # unknown opts are ok. +{ blatzk: 1000, flag: true, pick: true } + +$ node my-program.js --blatzk true -fp # but they need a value +{ blatzk: true, flag: true, pick: true } + +$ node my-program.js --no-blatzk -fp # unless they start with "no-" +{ blatzk: false, flag: true, pick: true } + +$ node my-program.js --baz b/a/z # known paths are resolved. +{ baz: "/Users/isaacs/b/a/z" } + +# if Array is one of the types, then it can take many +# values, and will always be an array. The other types provided +# specify what types are allowed in the list. + +$ node my-program.js --many 1 --many null --many foo +{ many: ["1", "null", "foo"] } + +$ node my-program.js --many foo +{ many: ["foo"] } +``` + +Read the tests at the bottom of `lib/nopt.js` for more examples of +what this puppy can do. + +## Types + +The following types are supported, and defined on `nopt.typeDefs` + +* String: A normal string. No parsing is done. +* path: A file system path. Gets resolved against cwd if not absolute. +* url: A url. If it doesn't parse, it isn't accepted. +* Number: Must be numeric. +* Date: Must parse as a date. If it does, and `Date` is one of the options, + then it will return a Date object, not a string. +* Boolean: Must be either `true` or `false`. If an option is a boolean, + then it does not need a value, and its presence will imply `true` as + the value. To negate boolean flags, do `--no-whatever` or `--whatever + false` +* NaN: Means that the option is strictly not allowed. Any value will + fail. +* Stream: An object matching the "Stream" class in node. Valuable + for use when validating programmatically. (npm uses this to let you + supply any WriteStream on the `outfd` and `logfd` config options.) +* Array: If `Array` is specified as one of the types, then the value + will be parsed as a list of options. This means that multiple values + can be specified, and that the value will always be an array. + +If a type is an array of values not on this list, then those are +considered valid values. For instance, in the example above, the +`--bloo` option can only be one of `"big"`, `"medium"`, or `"small"`, +and any other value will be rejected. + +When parsing unknown fields, `"true"`, `"false"`, and `"null"` will be +interpreted as their JavaScript equivalents, and numeric values will be +interpreted as a number. + +You can also mix types and values, or multiple types, in a list. For +instance `{ blah: [Number, null] }` would allow a value to be set to +either a Number or null. When types are ordered, this implies a +preference, and the first type that can be used to properly interpret +the value will be used. + +To define a new type, add it to `nopt.typeDefs`. Each item in that +hash is an object with a `type` member and a `validate` method. The +`type` member is an object that matches what goes in the type list. The +`validate` method is a function that gets called with `validate(data, +key, val)`. Validate methods should assign `data[key]` to the valid +value of `val` if it can be handled properly, or return boolean +`false` if it cannot. + +You can also call `nopt.clean(data, types, typeDefs)` to clean up a +config object and remove its invalid properties. + +## Error Handling + +By default, nopt outputs a warning to standard error when invalid +options are found. You can change this behavior by assigning a method +to `nopt.invalidHandler`. This method will be called with +the offending `nopt.invalidHandler(key, val, types)`. + +If no `nopt.invalidHandler` is assigned, then it will console.error +its whining. If it is assigned to boolean `false` then the warning is +suppressed. + +## Abbreviations + +Yes, they are supported. If you define options like this: + +```javascript +{ "foolhardyelephants" : Boolean +, "pileofmonkeys" : Boolean } +``` + +Then this will work: + +```bash +node program.js --foolhar --pil +node program.js --no-f --pileofmon +# etc. +``` + +## Shorthands + +Shorthands are a hash of shorter option names to a snippet of args that +they expand to. + +If multiple one-character shorthands are all combined, and the +combination does not unambiguously match any other option or shorthand, +then they will be broken up into their constituent parts. For example: + +```json +{ "s" : ["--loglevel", "silent"] +, "g" : "--global" +, "f" : "--force" +, "p" : "--parseable" +, "l" : "--long" +} +``` + +```bash +npm ls -sgflp +# just like doing this: +npm ls --loglevel silent --global --force --long --parseable +``` + +## The Rest of the args + +The config object returned by nopt is given a special member called +`argv`, which is an object with the following fields: + +* `remain`: The remaining args after all the parsing has occurred. +* `original`: The args as they originally appeared. +* `cooked`: The args after flags and shorthands are expanded. + +## Slicing + +Node programs are called with more or less the exact argv as it appears +in C land, after the v8 and node-specific options have been plucked off. +As such, `argv[0]` is always `node` and `argv[1]` is always the +JavaScript program being run. + +That's usually not very useful to you. So they're sliced off by +default. If you want them, then you can pass in `0` as the last +argument, or any other number that you'd like to slice off the start of +the list. diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/bin/nopt.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/bin/nopt.js new file mode 100755 index 0000000..df90c72 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/bin/nopt.js @@ -0,0 +1,44 @@ +#!/usr/bin/env node +var nopt = require("../lib/nopt") + , types = { num: Number + , bool: Boolean + , help: Boolean + , list: Array + , "num-list": [Number, Array] + , "str-list": [String, Array] + , "bool-list": [Boolean, Array] + , str: String } + , shorthands = { s: [ "--str", "astring" ] + , b: [ "--bool" ] + , nb: [ "--no-bool" ] + , tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ] + , "?": ["--help"] + , h: ["--help"] + , H: ["--help"] + , n: [ "--num", "125" ] } + , parsed = nopt( types + , shorthands + , process.argv + , 2 ) + +console.log("parsed", parsed) + +if (parsed.help) { + console.log("") + console.log("nopt cli tester") + console.log("") + console.log("types") + console.log(Object.keys(types).map(function M (t) { + var type = types[t] + if (Array.isArray(type)) { + return [t, type.map(function (type) { return type.name })] + } + return [t, type && type.name] + }).reduce(function (s, i) { + s[i[0]] = i[1] + return s + }, {})) + console.log("") + console.log("shorthands") + console.log(shorthands) +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/examples/my-program.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/examples/my-program.js new file mode 100755 index 0000000..142447e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/examples/my-program.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node + +//process.env.DEBUG_NOPT = 1 + +// my-program.js +var nopt = require("../lib/nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag", "true"] + , "g" : ["--flag"] + , "s" : "--flag" + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + +console.log("parsed =\n"+ require("util").inspect(parsed)) diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/lib/nopt.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/lib/nopt.js new file mode 100644 index 0000000..5763860 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/lib/nopt.js @@ -0,0 +1,555 @@ +// info about each config option. + +var debug = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG + ? function () { console.error.apply(console, arguments) } + : function () {} + +var url = require("url") + , path = require("path") + , Stream = require("stream").Stream + , abbrev = require("abbrev") + +module.exports = exports = nopt +exports.clean = clean + +exports.typeDefs = + { String : { type: String, validate: validateString } + , Boolean : { type: Boolean, validate: validateBoolean } + , url : { type: url, validate: validateUrl } + , Number : { type: Number, validate: validateNumber } + , path : { type: path, validate: validatePath } + , Stream : { type: Stream, validate: validateStream } + , Date : { type: Date, validate: validateDate } + } + +function nopt (types, shorthands, args, slice) { + args = args || process.argv + types = types || {} + shorthands = shorthands || {} + if (typeof slice !== "number") slice = 2 + + debug(types, shorthands, args, slice) + + args = args.slice(slice) + var data = {} + , key + , remain = [] + , cooked = args + , original = args.slice(0) + + parse(args, data, remain, types, shorthands) + // now data is full + clean(data, types, exports.typeDefs) + data.argv = {remain:remain,cooked:cooked,original:original} + Object.defineProperty(data.argv, 'toString', { value: function () { + return this.original.map(JSON.stringify).join(" ") + }, enumerable: false }) + return data +} + +function clean (data, types, typeDefs) { + typeDefs = typeDefs || exports.typeDefs + var remove = {} + , typeDefault = [false, true, null, String, Number] + + Object.keys(data).forEach(function (k) { + if (k === "argv") return + var val = data[k] + , isArray = Array.isArray(val) + , type = types[k] + if (!isArray) val = [val] + if (!type) type = typeDefault + if (type === Array) type = typeDefault.concat(Array) + if (!Array.isArray(type)) type = [type] + + debug("val=%j", val) + debug("types=", type) + val = val.map(function (val) { + // if it's an unknown value, then parse false/true/null/numbers/dates + if (typeof val === "string") { + debug("string %j", val) + val = val.trim() + if ((val === "null" && ~type.indexOf(null)) + || (val === "true" && + (~type.indexOf(true) || ~type.indexOf(Boolean))) + || (val === "false" && + (~type.indexOf(false) || ~type.indexOf(Boolean)))) { + val = JSON.parse(val) + debug("jsonable %j", val) + } else if (~type.indexOf(Number) && !isNaN(val)) { + debug("convert to number", val) + val = +val + } else if (~type.indexOf(Date) && !isNaN(Date.parse(val))) { + debug("convert to date", val) + val = new Date(val) + } + } + + if (!types.hasOwnProperty(k)) { + return val + } + + // allow `--no-blah` to set 'blah' to null if null is allowed + if (val === false && ~type.indexOf(null) && + !(~type.indexOf(false) || ~type.indexOf(Boolean))) { + val = null + } + + var d = {} + d[k] = val + debug("prevalidated val", d, val, types[k]) + if (!validate(d, k, val, types[k], typeDefs)) { + if (exports.invalidHandler) { + exports.invalidHandler(k, val, types[k], data) + } else if (exports.invalidHandler !== false) { + debug("invalid: "+k+"="+val, types[k]) + } + return remove + } + debug("validated val", d, val, types[k]) + return d[k] + }).filter(function (val) { return val !== remove }) + + if (!val.length) delete data[k] + else if (isArray) { + debug(isArray, data[k], val) + data[k] = val + } else data[k] = val[0] + + debug("k=%s val=%j", k, val, data[k]) + }) +} + +function validateString (data, k, val) { + data[k] = String(val) +} + +function validatePath (data, k, val) { + data[k] = path.resolve(String(val)) + return true +} + +function validateNumber (data, k, val) { + debug("validate Number %j %j %j", k, val, isNaN(val)) + if (isNaN(val)) return false + data[k] = +val +} + +function validateDate (data, k, val) { + debug("validate Date %j %j %j", k, val, Date.parse(val)) + var s = Date.parse(val) + if (isNaN(s)) return false + data[k] = new Date(val) +} + +function validateBoolean (data, k, val) { + if (val instanceof Boolean) val = val.valueOf() + else if (typeof val === "string") { + if (!isNaN(val)) val = !!(+val) + else if (val === "null" || val === "false") val = false + else val = true + } else val = !!val + data[k] = val +} + +function validateUrl (data, k, val) { + val = url.parse(String(val)) + if (!val.host) return false + data[k] = val.href +} + +function validateStream (data, k, val) { + if (!(val instanceof Stream)) return false + data[k] = val +} + +function validate (data, k, val, type, typeDefs) { + // arrays are lists of types. + if (Array.isArray(type)) { + for (var i = 0, l = type.length; i < l; i ++) { + if (type[i] === Array) continue + if (validate(data, k, val, type[i], typeDefs)) return true + } + delete data[k] + return false + } + + // an array of anything? + if (type === Array) return true + + // NaN is poisonous. Means that something is not allowed. + if (type !== type) { + debug("Poison NaN", k, val, type) + delete data[k] + return false + } + + // explicit list of values + if (val === type) { + debug("Explicitly allowed %j", val) + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + return true + } + + // now go through the list of typeDefs, validate against each one. + var ok = false + , types = Object.keys(typeDefs) + for (var i = 0, l = types.length; i < l; i ++) { + debug("test type %j %j %j", k, val, types[i]) + var t = typeDefs[types[i]] + if (t && type === t.type) { + var d = {} + ok = false !== t.validate(d, k, val) + val = d[k] + if (ok) { + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + break + } + } + } + debug("OK? %j (%j %j %j)", ok, k, val, types[i]) + + if (!ok) delete data[k] + return ok +} + +function parse (args, data, remain, types, shorthands) { + debug("parse", args, data, remain) + + var key = null + , abbrevs = abbrev(Object.keys(types)) + , shortAbbr = abbrev(Object.keys(shorthands)) + + for (var i = 0; i < args.length; i ++) { + var arg = args[i] + debug("arg", arg) + + if (arg.match(/^-{2,}$/)) { + // done with keys. + // the rest are args. + remain.push.apply(remain, args.slice(i + 1)) + args[i] = "--" + break + } + var hadEq = false + if (arg.charAt(0) === "-") { + if (arg.indexOf("=") !== -1) { + hadEq = true + var v = arg.split("=") + arg = v.shift() + v = v.join("=") + args.splice.apply(args, [i, 1].concat([arg, v])) + } + // see if it's a shorthand + // if so, splice and back up to re-parse it. + var shRes = resolveShort(arg, shorthands, shortAbbr, abbrevs) + debug("arg=%j shRes=%j", arg, shRes) + if (shRes) { + debug(arg, shRes) + args.splice.apply(args, [i, 1].concat(shRes)) + if (arg !== shRes[0]) { + i -- + continue + } + } + arg = arg.replace(/^-+/, "") + var no = null + while (arg.toLowerCase().indexOf("no-") === 0) { + no = !no + arg = arg.substr(3) + } + + if (abbrevs[arg]) arg = abbrevs[arg] + + var isArray = types[arg] === Array || + Array.isArray(types[arg]) && types[arg].indexOf(Array) !== -1 + + var val + , la = args[i + 1] + + var isBool = typeof no === 'boolean' || + types[arg] === Boolean || + Array.isArray(types[arg]) && types[arg].indexOf(Boolean) !== -1 || + (typeof types[arg] === 'undefined' && !hadEq) || + (la === "false" && + (types[arg] === null || + Array.isArray(types[arg]) && ~types[arg].indexOf(null))) + + if (isBool) { + // just set and move along + val = !no + // however, also support --bool true or --bool false + if (la === "true" || la === "false") { + val = JSON.parse(la) + la = null + if (no) val = !val + i ++ + } + + // also support "foo":[Boolean, "bar"] and "--foo bar" + if (Array.isArray(types[arg]) && la) { + if (~types[arg].indexOf(la)) { + // an explicit type + val = la + i ++ + } else if ( la === "null" && ~types[arg].indexOf(null) ) { + // null allowed + val = null + i ++ + } else if ( !la.match(/^-{2,}[^-]/) && + !isNaN(la) && + ~types[arg].indexOf(Number) ) { + // number + val = +la + i ++ + } else if ( !la.match(/^-[^-]/) && ~types[arg].indexOf(String) ) { + // string + val = la + i ++ + } + } + + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + continue + } + + if (la && la.match(/^-{2,}$/)) { + la = undefined + i -- + } + + val = la === undefined ? true : la + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + i ++ + continue + } + remain.push(arg) + } +} + +function resolveShort (arg, shorthands, shortAbbr, abbrevs) { + // handle single-char shorthands glommed together, like + // npm ls -glp, but only if there is one dash, and only if + // all of the chars are single-char shorthands, and it's + // not a match to some other abbrev. + arg = arg.replace(/^-+/, '') + if (abbrevs[arg] && !shorthands[arg]) { + return null + } + if (shortAbbr[arg]) { + arg = shortAbbr[arg] + } else { + var singles = shorthands.___singles + if (!singles) { + singles = Object.keys(shorthands).filter(function (s) { + return s.length === 1 + }).reduce(function (l,r) { l[r] = true ; return l }, {}) + shorthands.___singles = singles + } + var chrs = arg.split("").filter(function (c) { + return singles[c] + }) + if (chrs.join("") === arg) return chrs.map(function (c) { + return shorthands[c] + }).reduce(function (l, r) { + return l.concat(r) + }, []) + } + + if (shorthands[arg] && !Array.isArray(shorthands[arg])) { + shorthands[arg] = shorthands[arg].split(/\s+/) + } + return shorthands[arg] +} + +if (module === require.main) { +var assert = require("assert") + , util = require("util") + + , shorthands = + { s : ["--loglevel", "silent"] + , d : ["--loglevel", "info"] + , dd : ["--loglevel", "verbose"] + , ddd : ["--loglevel", "silly"] + , noreg : ["--no-registry"] + , reg : ["--registry"] + , "no-reg" : ["--no-registry"] + , silent : ["--loglevel", "silent"] + , verbose : ["--loglevel", "verbose"] + , h : ["--usage"] + , H : ["--usage"] + , "?" : ["--usage"] + , help : ["--usage"] + , v : ["--version"] + , f : ["--force"] + , desc : ["--description"] + , "no-desc" : ["--no-description"] + , "local" : ["--no-global"] + , l : ["--long"] + , p : ["--parseable"] + , porcelain : ["--parseable"] + , g : ["--global"] + } + + , types = + { aoa: Array + , nullstream: [null, Stream] + , date: Date + , str: String + , browser : String + , cache : path + , color : ["always", Boolean] + , depth : Number + , description : Boolean + , dev : Boolean + , editor : path + , force : Boolean + , global : Boolean + , globalconfig : path + , group : [String, Number] + , gzipbin : String + , logfd : [Number, Stream] + , loglevel : ["silent","win","error","warn","info","verbose","silly"] + , long : Boolean + , "node-version" : [false, String] + , npaturl : url + , npat : Boolean + , "onload-script" : [false, String] + , outfd : [Number, Stream] + , parseable : Boolean + , pre: Boolean + , prefix: path + , proxy : url + , "rebuild-bundle" : Boolean + , registry : url + , searchopts : String + , searchexclude: [null, String] + , shell : path + , t: [Array, String] + , tag : String + , tar : String + , tmp : path + , "unsafe-perm" : Boolean + , usage : Boolean + , user : String + , username : String + , userconfig : path + , version : Boolean + , viewer: path + , _exit : Boolean + } + +; [["-v", {version:true}, []] + ,["---v", {version:true}, []] + ,["ls -s --no-reg connect -d", + {loglevel:"info",registry:null},["ls","connect"]] + ,["ls ---s foo",{loglevel:"silent"},["ls","foo"]] + ,["ls --registry blargle", {}, ["ls"]] + ,["--no-registry", {registry:null}, []] + ,["--no-color true", {color:false}, []] + ,["--no-color false", {color:true}, []] + ,["--no-color", {color:false}, []] + ,["--color false", {color:false}, []] + ,["--color --logfd 7", {logfd:7,color:true}, []] + ,["--color=true", {color:true}, []] + ,["--logfd=10", {logfd:10}, []] + ,["--tmp=/tmp -tar=gtar",{tmp:"/tmp",tar:"gtar"},[]] + ,["--tmp=tmp -tar=gtar", + {tmp:path.resolve(process.cwd(), "tmp"),tar:"gtar"},[]] + ,["--logfd x", {}, []] + ,["a -true -- -no-false", {true:true},["a","-no-false"]] + ,["a -no-false", {false:false},["a"]] + ,["a -no-no-true", {true:true}, ["a"]] + ,["a -no-no-no-false", {false:false}, ["a"]] + ,["---NO-no-No-no-no-no-nO-no-no"+ + "-No-no-no-no-no-no-no-no-no"+ + "-no-no-no-no-NO-NO-no-no-no-no-no-no"+ + "-no-body-can-do-the-boogaloo-like-I-do" + ,{"body-can-do-the-boogaloo-like-I-do":false}, []] + ,["we are -no-strangers-to-love "+ + "--you-know=the-rules --and=so-do-i "+ + "---im-thinking-of=a-full-commitment "+ + "--no-you-would-get-this-from-any-other-guy "+ + "--no-gonna-give-you-up "+ + "-no-gonna-let-you-down=true "+ + "--no-no-gonna-run-around false "+ + "--desert-you=false "+ + "--make-you-cry false "+ + "--no-tell-a-lie "+ + "--no-no-and-hurt-you false" + ,{"strangers-to-love":false + ,"you-know":"the-rules" + ,"and":"so-do-i" + ,"you-would-get-this-from-any-other-guy":false + ,"gonna-give-you-up":false + ,"gonna-let-you-down":false + ,"gonna-run-around":false + ,"desert-you":false + ,"make-you-cry":false + ,"tell-a-lie":false + ,"and-hurt-you":false + },["we", "are"]] + ,["-t one -t two -t three" + ,{t: ["one", "two", "three"]} + ,[]] + ,["-t one -t null -t three four five null" + ,{t: ["one", "null", "three"]} + ,["four", "five", "null"]] + ,["-t foo" + ,{t:["foo"]} + ,[]] + ,["--no-t" + ,{t:["false"]} + ,[]] + ,["-no-no-t" + ,{t:["true"]} + ,[]] + ,["-aoa one -aoa null -aoa 100" + ,{aoa:["one", null, 100]} + ,[]] + ,["-str 100" + ,{str:"100"} + ,[]] + ,["--color always" + ,{color:"always"} + ,[]] + ,["--no-nullstream" + ,{nullstream:null} + ,[]] + ,["--nullstream false" + ,{nullstream:null} + ,[]] + ,["--notadate=2011-01-25" + ,{notadate: "2011-01-25"} + ,[]] + ,["--date 2011-01-25" + ,{date: new Date("2011-01-25")} + ,[]] + ].forEach(function (test) { + var argv = test[0].split(/\s+/) + , opts = test[1] + , rem = test[2] + , actual = nopt(types, shorthands, argv, 0) + , parsed = actual.argv + delete actual.argv + console.log(util.inspect(actual, false, 2, true), parsed.remain) + for (var i in opts) { + var e = JSON.stringify(opts[i]) + , a = JSON.stringify(actual[i] === undefined ? null : actual[i]) + if (e && typeof e === "object") { + assert.deepEqual(e, a) + } else { + assert.equal(e, a) + } + } + assert.deepEqual(rem, parsed.remain) + }) +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/LICENSE b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/LICENSE new file mode 100644 index 0000000..05a4010 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/LICENSE @@ -0,0 +1,23 @@ +Copyright 2009, 2010, 2011 Isaac Z. Schlueter. +All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The 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. diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/README.md b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/README.md new file mode 100644 index 0000000..99746fe --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/README.md @@ -0,0 +1,23 @@ +# abbrev-js + +Just like [ruby's Abbrev](http://apidock.com/ruby/Abbrev). + +Usage: + + var abbrev = require("abbrev"); + abbrev("foo", "fool", "folding", "flop"); + + // returns: + { fl: 'flop' + , flo: 'flop' + , flop: 'flop' + , fol: 'folding' + , fold: 'folding' + , foldi: 'folding' + , foldin: 'folding' + , folding: 'folding' + , foo: 'foo' + , fool: 'fool' + } + +This is handy for command-line scripts, or other cases where you want to be able to accept shorthands. diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/lib/abbrev.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/lib/abbrev.js new file mode 100644 index 0000000..bee4132 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/lib/abbrev.js @@ -0,0 +1,111 @@ + +module.exports = exports = abbrev.abbrev = abbrev + +abbrev.monkeyPatch = monkeyPatch + +function monkeyPatch () { + Object.defineProperty(Array.prototype, 'abbrev', { + value: function () { return abbrev(this) }, + enumerable: false, configurable: true, writable: true + }) + + Object.defineProperty(Object.prototype, 'abbrev', { + value: function () { return abbrev(Object.keys(this)) }, + enumerable: false, configurable: true, writable: true + }) +} + +function abbrev (list) { + if (arguments.length !== 1 || !Array.isArray(list)) { + list = Array.prototype.slice.call(arguments, 0) + } + for (var i = 0, l = list.length, args = [] ; i < l ; i ++) { + args[i] = typeof list[i] === "string" ? list[i] : String(list[i]) + } + + // sort them lexicographically, so that they're next to their nearest kin + args = args.sort(lexSort) + + // walk through each, seeing how much it has in common with the next and previous + var abbrevs = {} + , prev = "" + for (var i = 0, l = args.length ; i < l ; i ++) { + var current = args[i] + , next = args[i + 1] || "" + , nextMatches = true + , prevMatches = true + if (current === next) continue + for (var j = 0, cl = current.length ; j < cl ; j ++) { + var curChar = current.charAt(j) + nextMatches = nextMatches && curChar === next.charAt(j) + prevMatches = prevMatches && curChar === prev.charAt(j) + if (!nextMatches && !prevMatches) { + j ++ + break + } + } + prev = current + if (j === cl) { + abbrevs[current] = current + continue + } + for (var a = current.substr(0, j) ; j <= cl ; j ++) { + abbrevs[a] = current + a += current.charAt(j) + } + } + return abbrevs +} + +function lexSort (a, b) { + return a === b ? 0 : a > b ? 1 : -1 +} + + +// tests +if (module === require.main) { + +var assert = require("assert") +var util = require("util") + +console.log("running tests") +function test (list, expect) { + var actual = abbrev(list) + assert.deepEqual(actual, expect, + "abbrev("+util.inspect(list)+") === " + util.inspect(expect) + "\n"+ + "actual: "+util.inspect(actual)) + actual = abbrev.apply(exports, list) + assert.deepEqual(abbrev.apply(exports, list), expect, + "abbrev("+list.map(JSON.stringify).join(",")+") === " + util.inspect(expect) + "\n"+ + "actual: "+util.inspect(actual)) +} + +test([ "ruby", "ruby", "rules", "rules", "rules" ], +{ rub: 'ruby' +, ruby: 'ruby' +, rul: 'rules' +, rule: 'rules' +, rules: 'rules' +}) +test(["fool", "foom", "pool", "pope"], +{ fool: 'fool' +, foom: 'foom' +, poo: 'pool' +, pool: 'pool' +, pop: 'pope' +, pope: 'pope' +}) +test(["a", "ab", "abc", "abcd", "abcde", "acde"], +{ a: 'a' +, ab: 'ab' +, abc: 'abc' +, abcd: 'abcd' +, abcde: 'abcde' +, ac: 'acde' +, acd: 'acde' +, acde: 'acde' +}) + +console.log("pass") + +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/package.json b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/package.json new file mode 100644 index 0000000..2190dd4 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/node_modules/abbrev/package.json @@ -0,0 +1,29 @@ +{ + "name": "abbrev", + "version": "1.0.4", + "description": "Like ruby's abbrev module, but in js", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me" + }, + "main": "./lib/abbrev.js", + "scripts": { + "test": "node lib/abbrev.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/isaacs/abbrev-js" + }, + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/abbrev-js/raw/master/LICENSE" + }, + "readme": "# abbrev-js\n\nJust like [ruby's Abbrev](http://apidock.com/ruby/Abbrev).\n\nUsage:\n\n var abbrev = require(\"abbrev\");\n abbrev(\"foo\", \"fool\", \"folding\", \"flop\");\n \n // returns:\n { fl: 'flop'\n , flo: 'flop'\n , flop: 'flop'\n , fol: 'folding'\n , fold: 'folding'\n , foldi: 'folding'\n , foldin: 'folding'\n , folding: 'folding'\n , foo: 'foo'\n , fool: 'fool'\n }\n\nThis is handy for command-line scripts, or other cases where you want to be able to accept shorthands.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/abbrev-js/issues" + }, + "homepage": "https://github.com/isaacs/abbrev-js", + "_id": "abbrev@1.0.4", + "_from": "abbrev@1" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/package.json b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/package.json new file mode 100644 index 0000000..75cdeb6 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/node_modules/nopt/package.json @@ -0,0 +1,40 @@ +{ + "name": "nopt", + "version": "2.0.0", + "description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "main": "lib/nopt.js", + "scripts": { + "test": "node lib/nopt.js" + }, + "repository": { + "type": "git", + "url": "http://github.com/isaacs/nopt" + }, + "bin": { + "nopt": "./bin/nopt.js" + }, + "license": { + "type": "MIT", + "url": "https://github.com/isaacs/nopt/raw/master/LICENSE" + }, + "dependencies": { + "abbrev": "1" + }, + "readme": "If you want to write an option parser, and have it be good, there are\ntwo ways to do it. The Right Way, and the Wrong Way.\n\nThe Wrong Way is to sit down and write an option parser. We've all done\nthat.\n\nThe Right Way is to write some complex configurable program with so many\noptions that you go half-insane just trying to manage them all, and put\nit off with duct-tape solutions until you see exactly to the core of the\nproblem, and finally snap and write an awesome option parser.\n\nIf you want to write an option parser, don't write an option parser.\nWrite a package manager, or a source control system, or a service\nrestarter, or an operating system. You probably won't end up with a\ngood one of those, but if you don't give up, and you are relentless and\ndiligent enough in your procrastination, you may just end up with a very\nnice option parser.\n\n## USAGE\n\n // my-program.js\n var nopt = require(\"nopt\")\n , Stream = require(\"stream\").Stream\n , path = require(\"path\")\n , knownOpts = { \"foo\" : [String, null]\n , \"bar\" : [Stream, Number]\n , \"baz\" : path\n , \"bloo\" : [ \"big\", \"medium\", \"small\" ]\n , \"flag\" : Boolean\n , \"pick\" : Boolean\n , \"many\" : [String, Array]\n }\n , shortHands = { \"foofoo\" : [\"--foo\", \"Mr. Foo\"]\n , \"b7\" : [\"--bar\", \"7\"]\n , \"m\" : [\"--bloo\", \"medium\"]\n , \"p\" : [\"--pick\"]\n , \"f\" : [\"--flag\"]\n }\n // everything is optional.\n // knownOpts and shorthands default to {}\n // arg list defaults to process.argv\n // slice defaults to 2\n , parsed = nopt(knownOpts, shortHands, process.argv, 2)\n console.log(parsed)\n\nThis would give you support for any of the following:\n\n```bash\n$ node my-program.js --foo \"blerp\" --no-flag\n{ \"foo\" : \"blerp\", \"flag\" : false }\n\n$ node my-program.js ---bar 7 --foo \"Mr. Hand\" --flag\n{ bar: 7, foo: \"Mr. Hand\", flag: true }\n\n$ node my-program.js --foo \"blerp\" -f -----p\n{ foo: \"blerp\", flag: true, pick: true }\n\n$ node my-program.js -fp --foofoo\n{ foo: \"Mr. Foo\", flag: true, pick: true }\n\n$ node my-program.js --foofoo -- -fp # -- stops the flag parsing.\n{ foo: \"Mr. Foo\", argv: { remain: [\"-fp\"] } }\n\n$ node my-program.js --blatzk 1000 -fp # unknown opts are ok.\n{ blatzk: 1000, flag: true, pick: true }\n\n$ node my-program.js --blatzk true -fp # but they need a value\n{ blatzk: true, flag: true, pick: true }\n\n$ node my-program.js --no-blatzk -fp # unless they start with \"no-\"\n{ blatzk: false, flag: true, pick: true }\n\n$ node my-program.js --baz b/a/z # known paths are resolved.\n{ baz: \"/Users/isaacs/b/a/z\" }\n\n# if Array is one of the types, then it can take many\n# values, and will always be an array. The other types provided\n# specify what types are allowed in the list.\n\n$ node my-program.js --many 1 --many null --many foo\n{ many: [\"1\", \"null\", \"foo\"] }\n\n$ node my-program.js --many foo\n{ many: [\"foo\"] }\n```\n\nRead the tests at the bottom of `lib/nopt.js` for more examples of\nwhat this puppy can do.\n\n## Types\n\nThe following types are supported, and defined on `nopt.typeDefs`\n\n* String: A normal string. No parsing is done.\n* path: A file system path. Gets resolved against cwd if not absolute.\n* url: A url. If it doesn't parse, it isn't accepted.\n* Number: Must be numeric.\n* Date: Must parse as a date. If it does, and `Date` is one of the options,\n then it will return a Date object, not a string.\n* Boolean: Must be either `true` or `false`. If an option is a boolean,\n then it does not need a value, and its presence will imply `true` as\n the value. To negate boolean flags, do `--no-whatever` or `--whatever\n false`\n* NaN: Means that the option is strictly not allowed. Any value will\n fail.\n* Stream: An object matching the \"Stream\" class in node. Valuable\n for use when validating programmatically. (npm uses this to let you\n supply any WriteStream on the `outfd` and `logfd` config options.)\n* Array: If `Array` is specified as one of the types, then the value\n will be parsed as a list of options. This means that multiple values\n can be specified, and that the value will always be an array.\n\nIf a type is an array of values not on this list, then those are\nconsidered valid values. For instance, in the example above, the\n`--bloo` option can only be one of `\"big\"`, `\"medium\"`, or `\"small\"`,\nand any other value will be rejected.\n\nWhen parsing unknown fields, `\"true\"`, `\"false\"`, and `\"null\"` will be\ninterpreted as their JavaScript equivalents, and numeric values will be\ninterpreted as a number.\n\nYou can also mix types and values, or multiple types, in a list. For\ninstance `{ blah: [Number, null] }` would allow a value to be set to\neither a Number or null. When types are ordered, this implies a\npreference, and the first type that can be used to properly interpret\nthe value will be used.\n\nTo define a new type, add it to `nopt.typeDefs`. Each item in that\nhash is an object with a `type` member and a `validate` method. The\n`type` member is an object that matches what goes in the type list. The\n`validate` method is a function that gets called with `validate(data,\nkey, val)`. Validate methods should assign `data[key]` to the valid\nvalue of `val` if it can be handled properly, or return boolean\n`false` if it cannot.\n\nYou can also call `nopt.clean(data, types, typeDefs)` to clean up a\nconfig object and remove its invalid properties.\n\n## Error Handling\n\nBy default, nopt outputs a warning to standard error when invalid\noptions are found. You can change this behavior by assigning a method\nto `nopt.invalidHandler`. This method will be called with\nthe offending `nopt.invalidHandler(key, val, types)`.\n\nIf no `nopt.invalidHandler` is assigned, then it will console.error\nits whining. If it is assigned to boolean `false` then the warning is\nsuppressed.\n\n## Abbreviations\n\nYes, they are supported. If you define options like this:\n\n```javascript\n{ \"foolhardyelephants\" : Boolean\n, \"pileofmonkeys\" : Boolean }\n```\n\nThen this will work:\n\n```bash\nnode program.js --foolhar --pil\nnode program.js --no-f --pileofmon\n# etc.\n```\n\n## Shorthands\n\nShorthands are a hash of shorter option names to a snippet of args that\nthey expand to.\n\nIf multiple one-character shorthands are all combined, and the\ncombination does not unambiguously match any other option or shorthand,\nthen they will be broken up into their constituent parts. For example:\n\n```json\n{ \"s\" : [\"--loglevel\", \"silent\"]\n, \"g\" : \"--global\"\n, \"f\" : \"--force\"\n, \"p\" : \"--parseable\"\n, \"l\" : \"--long\"\n}\n```\n\n```bash\nnpm ls -sgflp\n# just like doing this:\nnpm ls --loglevel silent --global --force --long --parseable\n```\n\n## The Rest of the args\n\nThe config object returned by nopt is given a special member called\n`argv`, which is an object with the following fields:\n\n* `remain`: The remaining args after all the parsing has occurred.\n* `original`: The args as they originally appeared.\n* `cooked`: The args after flags and shorthands are expanded.\n\n## Slicing\n\nNode programs are called with more or less the exact argv as it appears\nin C land, after the v8 and node-specific options have been plucked off.\nAs such, `argv[0]` is always `node` and `argv[1]` is always the\nJavaScript program being run.\n\nThat's usually not very useful to you. So they're sliced off by\ndefault. If you want them, then you can pass in `0` as the last\nargument, or any other number that you'd like to slice off the start of\nthe list.\n", + "readmeFilename": "README.md", + "bugs": { + "url": "https://github.com/isaacs/nopt/issues" + }, + "homepage": "https://github.com/isaacs/nopt", + "_id": "nopt@2.0.0", + "dist": { + "shasum": "6531807c0340e194e1bbea058fb31cc7ba64e77b" + }, + "_from": "nopt@~2.0.0", + "_resolved": "https://registry.npmjs.org/nopt/-/nopt-2.0.0.tgz" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/package.json b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/package.json new file mode 100644 index 0000000..1116905 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/package.json @@ -0,0 +1,33 @@ +{ + "author": { + "name": "mklabs" + }, + "name": "noptify", + "description": "nopt wrapper with commander-like API", + "version": "0.0.3", + "repository": { + "type": "git", + "url": "git://github.com/mklabs/noptify.git" + }, + "dependencies": { + "nopt": "~2.0.0" + }, + "devDependencies": { + "mocha": "~1.8.1" + }, + "scripts": { + "test": "mocha --reporter spec" + }, + "readme": "### noptify\n\nnoptify is a little wrapper around `nopt` module adding a more expressive,\ncommander-like, API and few helpers.\n\nExamples\n\n var program = noptify(process.argv, { program: 'name' })\n .version('0.0.1')\n .option('port', '-p', 'Port to listen on (default: 35729)', Number)\n .option('pid', 'Path to the generated PID file', String)\n\n var opts = program.parse();\n\nReturns an instance of `Noptify`\n\n### Noptify\n\nNoptify provides the API to parse out option, shorthands and generate the\nproper generic help output.\n\n- args - The Array of arguments to parse (default: `process.argv`);\n- options - An hash of options with the following properties\n - program - The program name to use in usage output\n\nEvery noptify instance is created with two options, `-h, --help` and `-v,\n--version`.\n\n### Noptify#parse\n\nParse the provided options and shorthands, pass them through `nopt` and\nreturn the result.\n\nWhen `opts.help` is set, the help output is displayed and `help`\nevent is emitted. The process exists with `0` status, the help output is\nautomatically displayed and the `help` event is emitted.\n\nExamples\n\n var program = noptify(['foo', '--help'])\n .on('help', function() {\n console.log('Examples');\n console.log('');\n console.log(' foo bar --baz > foo.txt');\n });\n\n var opts = program.parse();\n // ... Help output ...\n // ... Custom help output ...\n // ... Exit ...\n\n\n\n### Noptify#version\n\nDefine the program version.\n\n### Noptify#option\n\nDefine `name` option with optional shorthands, optional description and optional type.\n\n### Noptify#help\n\nSimply output to stdout the Usage and Help output.\n\n---\n\n*Mocha generated documentation*\n\n- [API](#api)\n- [Collectable](#collectable)\n- [Commandable](#commandable)\n - [Parses remaining arguments and route to the appropriate command](#commandable-parses-remaining-arguments-and-route-to-the-appropriate-command)\n\n\n\n\n## API\nreturns an instanceof Noptify.\n\n```js\nassert.ok(noptify() instanceof noptify.Noptify);\n```\n\nis typically used like so.\n\n```js\nvar program = noptify(['node', 'file.js', '-d', '--dirname', './', '-p', '3000', 'app.js', 'base.js'])\n .option('debug', '-d', 'Enabled debug output', Boolean)\n .option('dirname', 'The path to the output directory')\n .option('port', '-p', 'The port you wish to listen on', Number)\n\n// opts => nopt result\nvar opts = program.parse();\n\nassert.deepEqual(opts, {\n port: 3000,\n debug: true,\n dirname: './',\n argv: {\n remain: ['app.js', 'base.js'],\n cooked: ['--debug', '--dirname', './', '--port', '3000', 'app.js', 'base.js'],\n original: ['-d', '--dirname', './', '-p', '3000', 'app.js', 'base.js']\n }\n});\n```\n\nallows definitiion of shorthands separately.\n\n```js\nvar opts = noptify(['node', 'file.js', '-lc'])\n .option('line-comment', 'Ouputs with debugging information', Boolean)\n .shorthand('lc', '--line-comment')\n .parse();\n\nassert.equal(opts['line-comment'], true);\n```\n\n\n## Collectable\nprovides the helper method to read from stdin.\n\n```js\nvar program = noptify();\nassert.ok(typeof program.stdin === 'function', 'stdin defined');\n```\n\nis invoked only when .parse() is called.\n\n```js\nvar program = noptify(['', '']);\nvar str = 'testing out stdin helper';\nprogram.stdin(function(err, res) {\n assert.equal(res, str);\n done();\n});\n\nprogram.parse();\n\nprocess.nextTick(function() {\n process.stdin.emit('data', str);\n process.stdin.emit('end');\n});\n```\n\n\n## Commandable\nprovides the .command() utility.\n\n```js\nassert.ok(typeof noptify().command === 'function');\n```\n\n\n## Parses remaining arguments and route to the appropriate command\ncan be a simple function.\n\n```js\nvar program = noptify(['', '', 'init', '--debug', 'foo']).option('debug', 'an option');\n\nprogram.command('init', function(args, opts) {\n // args ==> sliced args at command position\n // opts ==> nopt parsed object\n assert.deepEqual(args, ['--debug', 'foo']);\n assert.equal(opts.debug, true);\n assert.equal(opts.argv.remain[0], 'foo');\n done();\n});\n\nprogram.parse();\n```\n\nor another program, an Noptify instance.\n\n```js\nvar args = ['', '', 'init', '--debug', 'myapp', 'foo'];\n\nvar init = noptify(args)\n .option('debug', 'Debug output')\n .command('myapp', done.bind(null, null));\n\nnoptify(args).command('init', init).parse();\n```\n\n", + "readmeFilename": "readme.md", + "bugs": { + "url": "https://github.com/mklabs/noptify/issues" + }, + "homepage": "https://github.com/mklabs/noptify", + "_id": "noptify@0.0.3", + "dist": { + "shasum": "58f654a73d9753df0c51d9686dc92104a67f4bbb" + }, + "_from": "noptify@latest", + "_resolved": "https://registry.npmjs.org/noptify/-/noptify-0.0.3.tgz" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/readme.md b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/readme.md new file mode 100644 index 0000000..6e41adb --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/readme.md @@ -0,0 +1,184 @@ +### noptify + +noptify is a little wrapper around `nopt` module adding a more expressive, +commander-like, API and few helpers. + +Examples + + var program = noptify(process.argv, { program: 'name' }) + .version('0.0.1') + .option('port', '-p', 'Port to listen on (default: 35729)', Number) + .option('pid', 'Path to the generated PID file', String) + + var opts = program.parse(); + +Returns an instance of `Noptify` + +### Noptify + +Noptify provides the API to parse out option, shorthands and generate the +proper generic help output. + +- args - The Array of arguments to parse (default: `process.argv`); +- options - An hash of options with the following properties + - program - The program name to use in usage output + +Every noptify instance is created with two options, `-h, --help` and `-v, +--version`. + +### Noptify#parse + +Parse the provided options and shorthands, pass them through `nopt` and +return the result. + +When `opts.help` is set, the help output is displayed and `help` +event is emitted. The process exists with `0` status, the help output is +automatically displayed and the `help` event is emitted. + +Examples + + var program = noptify(['foo', '--help']) + .on('help', function() { + console.log('Examples'); + console.log(''); + console.log(' foo bar --baz > foo.txt'); + }); + + var opts = program.parse(); + // ... Help output ... + // ... Custom help output ... + // ... Exit ... + + + +### Noptify#version + +Define the program version. + +### Noptify#option + +Define `name` option with optional shorthands, optional description and optional type. + +### Noptify#help + +Simply output to stdout the Usage and Help output. + +--- + +*Mocha generated documentation* + +- [API](#api) +- [Collectable](#collectable) +- [Commandable](#commandable) + - [Parses remaining arguments and route to the appropriate command](#commandable-parses-remaining-arguments-and-route-to-the-appropriate-command) + + + + +## API +returns an instanceof Noptify. + +```js +assert.ok(noptify() instanceof noptify.Noptify); +``` + +is typically used like so. + +```js +var program = noptify(['node', 'file.js', '-d', '--dirname', './', '-p', '3000', 'app.js', 'base.js']) + .option('debug', '-d', 'Enabled debug output', Boolean) + .option('dirname', 'The path to the output directory') + .option('port', '-p', 'The port you wish to listen on', Number) + +// opts => nopt result +var opts = program.parse(); + +assert.deepEqual(opts, { + port: 3000, + debug: true, + dirname: './', + argv: { + remain: ['app.js', 'base.js'], + cooked: ['--debug', '--dirname', './', '--port', '3000', 'app.js', 'base.js'], + original: ['-d', '--dirname', './', '-p', '3000', 'app.js', 'base.js'] + } +}); +``` + +allows definitiion of shorthands separately. + +```js +var opts = noptify(['node', 'file.js', '-lc']) + .option('line-comment', 'Ouputs with debugging information', Boolean) + .shorthand('lc', '--line-comment') + .parse(); + +assert.equal(opts['line-comment'], true); +``` + + +## Collectable +provides the helper method to read from stdin. + +```js +var program = noptify(); +assert.ok(typeof program.stdin === 'function', 'stdin defined'); +``` + +is invoked only when .parse() is called. + +```js +var program = noptify(['', '']); +var str = 'testing out stdin helper'; +program.stdin(function(err, res) { + assert.equal(res, str); + done(); +}); + +program.parse(); + +process.nextTick(function() { + process.stdin.emit('data', str); + process.stdin.emit('end'); +}); +``` + + +## Commandable +provides the .command() utility. + +```js +assert.ok(typeof noptify().command === 'function'); +``` + + +## Parses remaining arguments and route to the appropriate command +can be a simple function. + +```js +var program = noptify(['', '', 'init', '--debug', 'foo']).option('debug', 'an option'); + +program.command('init', function(args, opts) { + // args ==> sliced args at command position + // opts ==> nopt parsed object + assert.deepEqual(args, ['--debug', 'foo']); + assert.equal(opts.debug, true); + assert.equal(opts.argv.remain[0], 'foo'); + done(); +}); + +program.parse(); +``` + +or another program, an Noptify instance. + +```js +var args = ['', '', 'init', '--debug', 'myapp', 'foo']; + +var init = noptify(args) + .option('debug', 'Debug output') + .command('myapp', done.bind(null, null)); + +noptify(args).command('init', init).parse(); +``` + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/api.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/api.js new file mode 100644 index 0000000..e022850 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/api.js @@ -0,0 +1,53 @@ +var noptify = require('..'); +var assert = require('assert'); + +describe('API', function() { + + it('returns an instanceof Noptify', function() { + assert.ok(noptify() instanceof noptify.Noptify); + }); + + + it('is typically used like so', function() { + var program = noptify(['node', 'file.js', '-d', '--dirname', './', '-p', '3000', 'app.js', 'base.js']) + .option('debug', '-d', 'Enabled debug output', Boolean) + .option('dirname', 'The path to the output directory') + .option('port', '-p', 'The port you wish to listen on', Number) + + // opts => nopt result + var opts = program.parse(); + + assert.deepEqual(opts, { + port: 3000, + debug: true, + dirname: './', + argv: { + remain: ['app.js', 'base.js'], + cooked: ['--debug', '--dirname', './', '--port', '3000', 'app.js', 'base.js'], + original: ['-d', '--dirname', './', '-p', '3000', 'app.js', 'base.js'] + } + }); + }); + + it('allows definitiion of shorthands separately', function() { + var opts = noptify(['node', 'file.js', '-lc']) + .option('line-comment', 'Ouputs with debugging information', Boolean) + .shorthand('lc', '--line-comment') + .parse(); + + assert.equal(opts['line-comment'], true); + }); + + // hmm, keep this one for the very last, or do another way, process exit + // prevent other tests from running + it.skip('outputs help and exit the process with --help', function() { + var program = noptify(['', '', '--help']) + assert.throws(function() { + throw new Error('parse() must be called for this to happen'); + }); + + program.parse(); + throw new Error('I\'m sad, I\'ll never throw :('); + }); + +}); diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/collectable.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/collectable.js new file mode 100644 index 0000000..02d578a --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/collectable.js @@ -0,0 +1,40 @@ +var noptify = require('..'); +var assert = require('assert'); + + +describe('Collectable', function() { + + it('provides the helper method to read from stdin', function() { + var program = noptify(); + assert.ok(typeof program.stdin === 'function', 'stdin defined'); + }); + + it('is invoked only when .parse() is called', function(done) { + var program = noptify(['', '']); + var str = 'testing out stdin helper'; + program.stdin(function(err, res) { + assert.equal(res, str); + done(); + }); + + program.parse(); + + process.nextTick(function() { + process.stdin.emit('data', str); + process.stdin.emit('end'); + }); + }); + + + it('.files()', function(done) { + var program = noptify(['', '', 'test/fixtures/a.js', 'test/fixtures/b.js']); + program.parse(); + + program.files(function(err, data) { + assert.equal(data, 'a\nb\n'); + done(); + }); + + }); + +}); diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/commandable.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/commandable.js new file mode 100644 index 0000000..39610f7 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/commandable.js @@ -0,0 +1,40 @@ +var noptify = require('..'); +var assert = require('assert'); + +describe('Commandable', function() { + + it('provides the .command() utility', function() { + assert.ok(typeof noptify().command === 'function'); + }); + + + describe('Parses remaining arguments and route to the appropriate command', function() { + + it('can be a simple function', function(done) { + var program = noptify(['', '', 'init', '--debug', 'foo']).option('debug', 'an option'); + + program.command('init', function(args, opts) { + // args ==> sliced args at command position + // opts ==> nopt parsed object + assert.deepEqual(args, ['--debug', 'foo']); + assert.equal(opts.debug, true); + assert.equal(opts.argv.remain[0], 'foo'); + done(); + }); + + program.parse(); + }); + + it('or another program, an Noptify instance', function(done) { + var args = ['', '', 'init', '--debug', 'myapp', 'foo']; + + var init = noptify(args) + .option('debug', 'Debug output') + .command('myapp', done.bind(null, null)); + + noptify(args).command('init', init).parse(); + }); + }); + + +}); diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/fixtures/a.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/fixtures/a.js new file mode 100644 index 0000000..7898192 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/fixtures/a.js @@ -0,0 +1 @@ +a diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/fixtures/b.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/fixtures/b.js new file mode 100644 index 0000000..6178079 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/test/fixtures/b.js @@ -0,0 +1 @@ +b diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/util/extend.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/util/extend.js new file mode 100644 index 0000000..d7e717c --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/util/extend.js @@ -0,0 +1,15 @@ + + +// Simple extend utility method + +module.exports = function extend(obj) { + var args = Array.prototype.slice.call(arguments, 1); + + args.forEach(function(o) { + Object.keys(o).forEach(function(prop) { + obj[prop] = o[prop]; + }); + }); + + return obj; +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/util/index.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/util/index.js new file mode 100644 index 0000000..115ead5 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/noptify/util/index.js @@ -0,0 +1,6 @@ + +// Common interface to utility methods, exposing the standard `util` core module +var util = module.exports = require('util'); + +// and augmenting it +util.extend = require('./extend'); diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/.gitmodules b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/.gitmodules new file mode 100644 index 0000000..49e31da --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/.gitmodules @@ -0,0 +1,6 @@ +[submodule "support/expresso"] + path = support/expresso + url = git://github.com/visionmedia/expresso.git +[submodule "support/should"] + path = support/should + url = git://github.com/visionmedia/should.js.git diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/.npmignore b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/.npmignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/.travis.yml b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/.travis.yml new file mode 100644 index 0000000..2c0a8f6 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - 0.6 + - 0.4 \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/History.md b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/History.md new file mode 100644 index 0000000..c9a0e3c --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/History.md @@ -0,0 +1,109 @@ + +0.5.6 / 2013-04-09 +================== + + * fix empty key productions in parser + +0.5.5 / 2013-03-20 +================== + + * output key= for null or undefined values. Closes #52 + +0.5.4 / 2013-03-15 +================== + + * fix ignoring of null / undefined. Closes #44 + +0.5.3 2012-12-09 +================== + + * add info to component.json + * remove regular client-side ./querystring.js, fix component.json support + +0.5.2 / 2012-11-14 +================== + + * fix uri encoding of non-plain object string values + +0.5.1 / 2012-09-18 +================== + + * fix encoded `=`. Closes #43 + +0.5.0 / 2012-05-04 +================== + + * Added component support + +0.4.2 / 2012-02-08 +================== + + * Fixed: ensure objects are created when appropriate not arrays [aheckmann] + +0.4.1 / 2012-01-26 +================== + + * Fixed stringify()ing numbers. Closes #23 + +0.4.0 / 2011-11-21 +================== + + * Allow parsing of an existing object (for `bodyParser()`) [jackyz] + * Replaced expresso with mocha + +0.3.2 / 2011-11-08 +================== + + * Fixed global variable leak + +0.3.1 / 2011-08-17 +================== + + * Added `try/catch` around malformed uri components + * Add test coverage for Array native method bleed-though + +0.3.0 / 2011-07-19 +================== + + * Allow `array[index]` and `object[property]` syntaxes [Aria Stewart] + +0.2.0 / 2011-06-29 +================== + + * Added `qs.stringify()` [Cory Forsyth] + +0.1.0 / 2011-04-13 +================== + + * Added jQuery-ish array support + +0.0.7 / 2011-03-13 +================== + + * Fixed; handle empty string and `== null` in `qs.parse()` [dmit] + allows for convenient `qs.parse(url.parse(str).query)` + +0.0.6 / 2011-02-14 +================== + + * Fixed; support for implicit arrays + +0.0.4 / 2011-02-09 +================== + + * Fixed `+` as a space + +0.0.3 / 2011-02-08 +================== + + * Fixed case when right-hand value contains "]" + +0.0.2 / 2011-02-07 +================== + + * Fixed "=" presence in key + +0.0.1 / 2011-02-07 +================== + + * Initial release diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/Makefile b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/Makefile new file mode 100644 index 0000000..84a78ec --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/Makefile @@ -0,0 +1,6 @@ + +test: + @./node_modules/.bin/mocha \ + --ui bdd + +.PHONY: test \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/Readme.md b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/Readme.md new file mode 100644 index 0000000..27e54a4 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/Readme.md @@ -0,0 +1,58 @@ +# node-querystring + + query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others. + +## Installation + + $ npm install qs + +## Examples + +```js +var qs = require('qs'); + +qs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com'); +// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } } + +qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }}) +// => user[name]=Tobi&user[email]=tobi%40learnboost.com +``` + +## Testing + +Install dev dependencies: + + $ npm install -d + +and execute: + + $ make test + +browser: + + $ open test/browser/index.html + +## License + +(The MIT License) + +Copyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca> + +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. \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/benchmark.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/benchmark.js new file mode 100644 index 0000000..97e2c93 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/benchmark.js @@ -0,0 +1,17 @@ + +var qs = require('./'); + +var times = 100000 + , start = new Date + , n = times; + +console.log('times: %d', times); + +while (n--) qs.parse('foo=bar'); +console.log('simple: %dms', new Date - start); + +var start = new Date + , n = times; + +while (n--) qs.parse('user[name][first]=tj&user[name][last]=holowaychuk'); +console.log('nested: %dms', new Date - start); \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/component.json b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/component.json new file mode 100644 index 0000000..0a46c2d --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/component.json @@ -0,0 +1,9 @@ +{ + "name": "querystring", + "repo": "visionmedia/node-querystring", + "description": "query-string parser / stringifier with nesting support", + "version": "0.5.6", + "keywords": ["querystring", "query", "parser"], + "scripts": ["index.js"], + "license": "MIT" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/examples.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/examples.js new file mode 100644 index 0000000..ebe3a97 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/examples.js @@ -0,0 +1,51 @@ + +/** + * Module dependencies. + */ + +var qs = require('./'); + +var obj = qs.parse('foo'); +console.log(obj) + +var obj = qs.parse('foo=bar=baz'); +console.log(obj) + +var obj = qs.parse('users[]'); +console.log(obj) + +var obj = qs.parse('name=tj&email=tj@vision-media.ca'); +console.log(obj) + +var obj = qs.parse('users[]=tj&users[]=tobi&users[]=jane'); +console.log(obj) + +var obj = qs.parse('user[name][first]=tj&user[name][last]=holowaychuk'); +console.log(obj) + +var obj = qs.parse('users[][name][first]=tj&users[][name][last]=holowaychuk'); +console.log(obj) + +var obj = qs.parse('a=a&a=b&a=c'); +console.log(obj) + +var obj = qs.parse('user[tj]=tj&user[tj]=TJ'); +console.log(obj) + +var obj = qs.parse('user[names]=tj&user[names]=TJ&user[names]=Tyler'); +console.log(obj) + +var obj = qs.parse('user[name][first]=tj&user[name][first]=TJ'); +console.log(obj) + +var obj = qs.parse('user[0]=tj&user[1]=TJ'); +console.log(obj) + +var obj = qs.parse('user[0]=tj&user[]=TJ'); +console.log(obj) + +var obj = qs.parse('user[0]=tj&user[foo]=TJ'); +console.log(obj) + +var str = qs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }}); +console.log(str); diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/index.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/index.js new file mode 100644 index 0000000..8b27b23 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/index.js @@ -0,0 +1,268 @@ + +/** + * Object#toString() ref for stringify(). + */ + +var toString = Object.prototype.toString; + +/** + * Cache non-integer test regexp. + */ + +var isint = /^[0-9]+$/; + +function promote(parent, key) { + if (parent[key].length == 0) return parent[key] = {}; + var t = {}; + for (var i in parent[key]) t[i] = parent[key][i]; + parent[key] = t; + return t; +} + +function parse(parts, parent, key, val) { + var part = parts.shift(); + // end + if (!part) { + if (Array.isArray(parent[key])) { + parent[key].push(val); + } else if ('object' == typeof parent[key]) { + parent[key] = val; + } else if ('undefined' == typeof parent[key]) { + parent[key] = val; + } else { + parent[key] = [parent[key], val]; + } + // array + } else { + var obj = parent[key] = parent[key] || []; + if (']' == part) { + if (Array.isArray(obj)) { + if ('' != val) obj.push(val); + } else if ('object' == typeof obj) { + obj[Object.keys(obj).length] = val; + } else { + obj = parent[key] = [parent[key], val]; + } + // prop + } else if (~part.indexOf(']')) { + part = part.substr(0, part.length - 1); + if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key); + parse(parts, obj, part, val); + // key + } else { + if (!isint.test(part) && Array.isArray(obj)) obj = promote(parent, key); + parse(parts, obj, part, val); + } + } +} + +/** + * Merge parent key/val pair. + */ + +function merge(parent, key, val){ + if (~key.indexOf(']')) { + var parts = key.split('[') + , len = parts.length + , last = len - 1; + parse(parts, parent, 'base', val); + // optimize + } else { + if (!isint.test(key) && Array.isArray(parent.base)) { + var t = {}; + for (var k in parent.base) t[k] = parent.base[k]; + parent.base = t; + } + set(parent.base, key, val); + } + + return parent; +} + +/** + * Parse the given obj. + */ + +function parseObject(obj){ + var ret = { base: {} }; + Object.keys(obj).forEach(function(name){ + merge(ret, name, obj[name]); + }); + return ret.base; +} + +/** + * Parse the given str. + */ + +function parseString(str){ + return String(str) + .split('&') + .reduce(function(ret, pair){ + var eql = pair.indexOf('=') + , brace = lastBraceInKey(pair) + , key = pair.substr(0, brace || eql) + , val = pair.substr(brace || eql, pair.length) + , val = val.substr(val.indexOf('=') + 1, val.length); + + // ?foo + if ('' == key) key = pair, val = ''; + if ('' == key) return ret; + + return merge(ret, decode(key), decode(val)); + }, { base: {} }).base; +} + +/** + * Parse the given query `str` or `obj`, returning an object. + * + * @param {String} str | {Object} obj + * @return {Object} + * @api public + */ + +exports.parse = function(str){ + if (null == str || '' == str) return {}; + return 'object' == typeof str + ? parseObject(str) + : parseString(str); +}; + +/** + * Turn the given `obj` into a query string + * + * @param {Object} obj + * @return {String} + * @api public + */ + +var stringify = exports.stringify = function(obj, prefix) { + if (Array.isArray(obj)) { + return stringifyArray(obj, prefix); + } else if ('[object Object]' == toString.call(obj)) { + return stringifyObject(obj, prefix); + } else if ('string' == typeof obj) { + return stringifyString(obj, prefix); + } else { + return prefix + '=' + encodeURIComponent(String(obj)); + } +}; + +/** + * Stringify the given `str`. + * + * @param {String} str + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyString(str, prefix) { + if (!prefix) throw new TypeError('stringify expects an object'); + return prefix + '=' + encodeURIComponent(str); +} + +/** + * Stringify the given `arr`. + * + * @param {Array} arr + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyArray(arr, prefix) { + var ret = []; + if (!prefix) throw new TypeError('stringify expects an object'); + for (var i = 0; i < arr.length; i++) { + ret.push(stringify(arr[i], prefix + '[' + i + ']')); + } + return ret.join('&'); +} + +/** + * Stringify the given `obj`. + * + * @param {Object} obj + * @param {String} prefix + * @return {String} + * @api private + */ + +function stringifyObject(obj, prefix) { + var ret = [] + , keys = Object.keys(obj) + , key; + + for (var i = 0, len = keys.length; i < len; ++i) { + key = keys[i]; + if ('' == key) continue; + if (null == obj[key]) { + ret.push(encodeURIComponent(key) + '='); + } else { + ret.push(stringify(obj[key], prefix + ? prefix + '[' + encodeURIComponent(key) + ']' + : encodeURIComponent(key))); + } + } + + return ret.join('&'); +} + +/** + * Set `obj`'s `key` to `val` respecting + * the weird and wonderful syntax of a qs, + * where "foo=bar&foo=baz" becomes an array. + * + * @param {Object} obj + * @param {String} key + * @param {String} val + * @api private + */ + +function set(obj, key, val) { + var v = obj[key]; + if (undefined === v) { + obj[key] = val; + } else if (Array.isArray(v)) { + v.push(val); + } else { + obj[key] = [v, val]; + } +} + +/** + * Locate last brace in `str` within the key. + * + * @param {String} str + * @return {Number} + * @api private + */ + +function lastBraceInKey(str) { + var len = str.length + , brace + , c; + for (var i = 0; i < len; ++i) { + c = str[i]; + if (']' == c) brace = false; + if ('[' == c) brace = true; + if ('=' == c && !brace) return i; + } +} + +/** + * Decode `str`. + * + * @param {String} str + * @return {String} + * @api private + */ + +function decode(str) { + try { + return decodeURIComponent(str.replace(/\+/g, ' ')); + } catch (err) { + return str; + } +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/package.json b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/package.json new file mode 100644 index 0000000..753f536 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/package.json @@ -0,0 +1,44 @@ +{ + "name": "qs", + "description": "querystring parser", + "version": "0.5.6", + "keywords": [ + "query string", + "parser", + "component" + ], + "repository": { + "type": "git", + "url": "git://github.com/visionmedia/node-querystring.git" + }, + "devDependencies": { + "mocha": "*", + "expect.js": "*" + }, + "component": { + "scripts": { + "querystring": "querystring.js" + } + }, + "author": { + "name": "TJ Holowaychuk", + "email": "tj@vision-media.ca", + "url": "http://tjholowaychuk.com" + }, + "main": "index", + "engines": { + "node": "*" + }, + "readme": "# node-querystring\n\n query string parser for node and the browser supporting nesting, as it was removed from `0.3.x`, so this library provides the previous and commonly desired behaviour (and twice as fast). Used by [express](http://expressjs.com), [connect](http://senchalabs.github.com/connect) and others.\n\n## Installation\n\n $ npm install qs\n\n## Examples\n\n```js\nvar qs = require('qs');\n\nqs.parse('user[name][first]=Tobi&user[email]=tobi@learnboost.com');\n// => { user: { name: { first: 'Tobi' }, email: 'tobi@learnboost.com' } }\n\nqs.stringify({ user: { name: 'Tobi', email: 'tobi@learnboost.com' }})\n// => user[name]=Tobi&user[email]=tobi%40learnboost.com\n```\n\n## Testing\n\nInstall dev dependencies:\n\n $ npm install -d\n\nand execute:\n\n $ make test\n\nbrowser:\n\n $ open test/browser/index.html\n\n## License \n\n(The MIT License)\n\nCopyright (c) 2010 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.", + "readmeFilename": "Readme.md", + "bugs": { + "url": "https://github.com/visionmedia/node-querystring/issues" + }, + "homepage": "https://github.com/visionmedia/node-querystring", + "_id": "qs@0.5.6", + "dist": { + "shasum": "70bdff68d571b47c41d68fc5f769801dc488e8ff" + }, + "_from": "qs@~0.5.2", + "_resolved": "https://registry.npmjs.org/qs/-/qs-0.5.6.tgz" +} diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/test/browser/expect.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/test/browser/expect.js new file mode 100644 index 0000000..76aa4e8 --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/test/browser/expect.js @@ -0,0 +1,1202 @@ + +(function (global, module) { + + if ('undefined' == typeof module) { + var module = { exports: {} } + , exports = module.exports + } + + /** + * Exports. + */ + + module.exports = expect; + expect.Assertion = Assertion; + + /** + * Exports version. + */ + + expect.version = '0.1.2'; + + /** + * Possible assertion flags. + */ + + var flags = { + not: ['to', 'be', 'have', 'include', 'only'] + , to: ['be', 'have', 'include', 'only', 'not'] + , only: ['have'] + , have: ['own'] + , be: ['an'] + }; + + function expect (obj) { + return new Assertion(obj); + } + + /** + * Constructor + * + * @api private + */ + + function Assertion (obj, flag, parent) { + this.obj = obj; + this.flags = {}; + + if (undefined != parent) { + this.flags[flag] = true; + + for (var i in parent.flags) { + if (parent.flags.hasOwnProperty(i)) { + this.flags[i] = true; + } + } + } + + var $flags = flag ? flags[flag] : keys(flags) + , self = this + + if ($flags) { + for (var i = 0, l = $flags.length; i < l; i++) { + // avoid recursion + if (this.flags[$flags[i]]) continue; + + var name = $flags[i] + , assertion = new Assertion(this.obj, name, this) + + if ('function' == typeof Assertion.prototype[name]) { + // clone the function, make sure we dont touch the prot reference + var old = this[name]; + this[name] = function () { + return old.apply(self, arguments); + } + + for (var fn in Assertion.prototype) { + if (Assertion.prototype.hasOwnProperty(fn) && fn != name) { + this[name][fn] = bind(assertion[fn], assertion); + } + } + } else { + this[name] = assertion; + } + } + } + }; + + /** + * Performs an assertion + * + * @api private + */ + + Assertion.prototype.assert = function (truth, msg, error) { + var msg = this.flags.not ? error : msg + , ok = this.flags.not ? !truth : truth; + + if (!ok) { + throw new Error(msg); + } + + this.and = new Assertion(this.obj); + }; + + /** + * Check if the value is truthy + * + * @api public + */ + + Assertion.prototype.ok = function () { + this.assert( + !!this.obj + , 'expected ' + i(this.obj) + ' to be truthy' + , 'expected ' + i(this.obj) + ' to be falsy'); + }; + + /** + * Assert that the function throws. + * + * @param {Function|RegExp} callback, or regexp to match error string against + * @api public + */ + + Assertion.prototype.throwError = + Assertion.prototype.throwException = function (fn) { + expect(this.obj).to.be.a('function'); + + var thrown = false + , not = this.flags.not + + try { + this.obj(); + } catch (e) { + if ('function' == typeof fn) { + fn(e); + } else if ('object' == typeof fn) { + var subject = 'string' == typeof e ? e : e.message; + if (not) { + expect(subject).to.not.match(fn); + } else { + expect(subject).to.match(fn); + } + } + thrown = true; + } + + if ('object' == typeof fn && not) { + // in the presence of a matcher, ensure the `not` only applies to + // the matching. + this.flags.not = false; + } + + var name = this.obj.name || 'fn'; + this.assert( + thrown + , 'expected ' + name + ' to throw an exception' + , 'expected ' + name + ' not to throw an exception'); + }; + + /** + * Checks if the array is empty. + * + * @api public + */ + + Assertion.prototype.empty = function () { + var expectation; + + if ('object' == typeof this.obj && null !== this.obj && !isArray(this.obj)) { + if ('number' == typeof this.obj.length) { + expectation = !this.obj.length; + } else { + expectation = !keys(this.obj).length; + } + } else { + if ('string' != typeof this.obj) { + expect(this.obj).to.be.an('object'); + } + + expect(this.obj).to.have.property('length'); + expectation = !this.obj.length; + } + + this.assert( + expectation + , 'expected ' + i(this.obj) + ' to be empty' + , 'expected ' + i(this.obj) + ' to not be empty'); + return this; + }; + + /** + * Checks if the obj exactly equals another. + * + * @api public + */ + + Assertion.prototype.be = + Assertion.prototype.equal = function (obj) { + this.assert( + obj === this.obj + , 'expected ' + i(this.obj) + ' to equal ' + i(obj) + , 'expected ' + i(this.obj) + ' to not equal ' + i(obj)); + return this; + }; + + /** + * Checks if the obj sortof equals another. + * + * @api public + */ + + Assertion.prototype.eql = function (obj) { + this.assert( + expect.eql(obj, this.obj) + , 'expected ' + i(this.obj) + ' to sort of equal ' + i(obj) + , 'expected ' + i(this.obj) + ' to sort of not equal ' + i(obj)); + return this; + }; + + /** + * Assert within start to finish (inclusive). + * + * @param {Number} start + * @param {Number} finish + * @api public + */ + + Assertion.prototype.within = function (start, finish) { + var range = start + '..' + finish; + this.assert( + this.obj >= start && this.obj <= finish + , 'expected ' + i(this.obj) + ' to be within ' + range + , 'expected ' + i(this.obj) + ' to not be within ' + range); + return this; + }; + + /** + * Assert typeof / instance of + * + * @api public + */ + + Assertion.prototype.a = + Assertion.prototype.an = function (type) { + if ('string' == typeof type) { + // proper english in error msg + var n = /^[aeiou]/.test(type) ? 'n' : ''; + + // typeof with support for 'array' + this.assert( + 'array' == type ? isArray(this.obj) : + 'object' == type + ? 'object' == typeof this.obj && null !== this.obj + : type == typeof this.obj + , 'expected ' + i(this.obj) + ' to be a' + n + ' ' + type + , 'expected ' + i(this.obj) + ' not to be a' + n + ' ' + type); + } else { + // instanceof + var name = type.name || 'supplied constructor'; + this.assert( + this.obj instanceof type + , 'expected ' + i(this.obj) + ' to be an instance of ' + name + , 'expected ' + i(this.obj) + ' not to be an instance of ' + name); + } + + return this; + }; + + /** + * Assert numeric value above _n_. + * + * @param {Number} n + * @api public + */ + + Assertion.prototype.greaterThan = + Assertion.prototype.above = function (n) { + this.assert( + this.obj > n + , 'expected ' + i(this.obj) + ' to be above ' + n + , 'expected ' + i(this.obj) + ' to be below ' + n); + return this; + }; + + /** + * Assert numeric value below _n_. + * + * @param {Number} n + * @api public + */ + + Assertion.prototype.lessThan = + Assertion.prototype.below = function (n) { + this.assert( + this.obj < n + , 'expected ' + i(this.obj) + ' to be below ' + n + , 'expected ' + i(this.obj) + ' to be above ' + n); + return this; + }; + + /** + * Assert string value matches _regexp_. + * + * @param {RegExp} regexp + * @api public + */ + + Assertion.prototype.match = function (regexp) { + this.assert( + regexp.exec(this.obj) + , 'expected ' + i(this.obj) + ' to match ' + regexp + , 'expected ' + i(this.obj) + ' not to match ' + regexp); + return this; + }; + + /** + * Assert property "length" exists and has value of _n_. + * + * @param {Number} n + * @api public + */ + + Assertion.prototype.length = function (n) { + expect(this.obj).to.have.property('length'); + var len = this.obj.length; + this.assert( + n == len + , 'expected ' + i(this.obj) + ' to have a length of ' + n + ' but got ' + len + , 'expected ' + i(this.obj) + ' to not have a length of ' + len); + return this; + }; + + /** + * Assert property _name_ exists, with optional _val_. + * + * @param {String} name + * @param {Mixed} val + * @api public + */ + + Assertion.prototype.property = function (name, val) { + if (this.flags.own) { + this.assert( + Object.prototype.hasOwnProperty.call(this.obj, name) + , 'expected ' + i(this.obj) + ' to have own property ' + i(name) + , 'expected ' + i(this.obj) + ' to not have own property ' + i(name)); + return this; + } + + if (this.flags.not && undefined !== val) { + if (undefined === this.obj[name]) { + throw new Error(i(this.obj) + ' has no property ' + i(name)); + } + } else { + var hasProp; + try { + hasProp = name in this.obj + } catch (e) { + hasProp = undefined !== this.obj[name] + } + + this.assert( + hasProp + , 'expected ' + i(this.obj) + ' to have a property ' + i(name) + , 'expected ' + i(this.obj) + ' to not have a property ' + i(name)); + } + + if (undefined !== val) { + this.assert( + val === this.obj[name] + , 'expected ' + i(this.obj) + ' to have a property ' + i(name) + + ' of ' + i(val) + ', but got ' + i(this.obj[name]) + , 'expected ' + i(this.obj) + ' to not have a property ' + i(name) + + ' of ' + i(val)); + } + + this.obj = this.obj[name]; + return this; + }; + + /** + * Assert that the array contains _obj_ or string contains _obj_. + * + * @param {Mixed} obj|string + * @api public + */ + + Assertion.prototype.string = + Assertion.prototype.contain = function (obj) { + if ('string' == typeof this.obj) { + this.assert( + ~this.obj.indexOf(obj) + , 'expected ' + i(this.obj) + ' to contain ' + i(obj) + , 'expected ' + i(this.obj) + ' to not contain ' + i(obj)); + } else { + this.assert( + ~indexOf(this.obj, obj) + , 'expected ' + i(this.obj) + ' to contain ' + i(obj) + , 'expected ' + i(this.obj) + ' to not contain ' + i(obj)); + } + return this; + }; + + /** + * Assert exact keys or inclusion of keys by using + * the `.own` modifier. + * + * @param {Array|String ...} keys + * @api public + */ + + Assertion.prototype.key = + Assertion.prototype.keys = function ($keys) { + var str + , ok = true; + + $keys = isArray($keys) + ? $keys + : Array.prototype.slice.call(arguments); + + if (!$keys.length) throw new Error('keys required'); + + var actual = keys(this.obj) + , len = $keys.length; + + // Inclusion + ok = every($keys, function (key) { + return ~indexOf(actual, key); + }); + + // Strict + if (!this.flags.not && this.flags.only) { + ok = ok && $keys.length == actual.length; + } + + // Key string + if (len > 1) { + $keys = map($keys, function (key) { + return i(key); + }); + var last = $keys.pop(); + str = $keys.join(', ') + ', and ' + last; + } else { + str = i($keys[0]); + } + + // Form + str = (len > 1 ? 'keys ' : 'key ') + str; + + // Have / include + str = (!this.flags.only ? 'include ' : 'only have ') + str; + + // Assertion + this.assert( + ok + , 'expected ' + i(this.obj) + ' to ' + str + , 'expected ' + i(this.obj) + ' to not ' + str); + + return this; + }; + + /** + * Function bind implementation. + */ + + function bind (fn, scope) { + return function () { + return fn.apply(scope, arguments); + } + } + + /** + * Array every compatibility + * + * @see bit.ly/5Fq1N2 + * @api public + */ + + function every (arr, fn, thisObj) { + var scope = thisObj || global; + for (var i = 0, j = arr.length; i < j; ++i) { + if (!fn.call(scope, arr[i], i, arr)) { + return false; + } + } + return true; + }; + + /** + * Array indexOf compatibility. + * + * @see bit.ly/a5Dxa2 + * @api public + */ + + function indexOf (arr, o, i) { + if (Array.prototype.indexOf) { + return Array.prototype.indexOf.call(arr, o, i); + } + + if (arr.length === undefined) { + return -1; + } + + for (var j = arr.length, i = i < 0 ? i + j < 0 ? 0 : i + j : i || 0 + ; i < j && arr[i] !== o; i++); + + return j <= i ? -1 : i; + }; + + /** + * Inspects an object. + * + * @see taken from node.js `util` module (copyright Joyent, MIT license) + * @api private + */ + + function i (obj, showHidden, depth) { + var seen = []; + + function stylize (str) { + return str; + }; + + function format (value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (value && typeof value.inspect === 'function' && + // Filter out the util module, it's inspect function is special + value !== exports && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + return value.inspect(recurseTimes); + } + + // Primitive types cannot have properties + switch (typeof value) { + case 'undefined': + return stylize('undefined', 'undefined'); + + case 'string': + var simple = '\'' + json.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return stylize(simple, 'string'); + + case 'number': + return stylize('' + value, 'number'); + + case 'boolean': + return stylize('' + value, 'boolean'); + } + // For some reason typeof null is "object", so special case here. + if (value === null) { + return stylize('null', 'null'); + } + + // Look up the keys of the object. + var visible_keys = keys(value); + var $keys = showHidden ? Object.getOwnPropertyNames(value) : visible_keys; + + // Functions without properties can be shortcutted. + if (typeof value === 'function' && $keys.length === 0) { + if (isRegExp(value)) { + return stylize('' + value, 'regexp'); + } else { + var name = value.name ? ': ' + value.name : ''; + return stylize('[Function' + name + ']', 'special'); + } + } + + // Dates without properties can be shortcutted + if (isDate(value) && $keys.length === 0) { + return stylize(value.toUTCString(), 'date'); + } + + var base, type, braces; + // Determine the object type + if (isArray(value)) { + type = 'Array'; + braces = ['[', ']']; + } else { + type = 'Object'; + braces = ['{', '}']; + } + + // Make functions say that they are functions + if (typeof value === 'function') { + var n = value.name ? ': ' + value.name : ''; + base = (isRegExp(value)) ? ' ' + value : ' [Function' + n + ']'; + } else { + base = ''; + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + value.toUTCString(); + } + + if ($keys.length === 0) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return stylize('' + value, 'regexp'); + } else { + return stylize('[Object]', 'special'); + } + } + + seen.push(value); + + var output = map($keys, function (key) { + var name, str; + if (value.__lookupGetter__) { + if (value.__lookupGetter__(key)) { + if (value.__lookupSetter__(key)) { + str = stylize('[Getter/Setter]', 'special'); + } else { + str = stylize('[Getter]', 'special'); + } + } else { + if (value.__lookupSetter__(key)) { + str = stylize('[Setter]', 'special'); + } + } + } + if (indexOf(visible_keys, key) < 0) { + name = '[' + key + ']'; + } + if (!str) { + if (indexOf(seen, value[key]) < 0) { + if (recurseTimes === null) { + str = format(value[key]); + } else { + str = format(value[key], recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (isArray(value)) { + str = map(str.split('\n'), function (line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + map(str.split('\n'), function (line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = stylize('[Circular]', 'special'); + } + } + if (typeof name === 'undefined') { + if (type === 'Array' && key.match(/^\d+$/)) { + return str; + } + name = json.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = stylize(name, 'string'); + } + } + + return name + ': ' + str; + }); + + seen.pop(); + + var numLinesEst = 0; + var length = reduce(output, function (prev, cur) { + numLinesEst++; + if (indexOf(cur, '\n') >= 0) numLinesEst++; + return prev + cur.length + 1; + }, 0); + + if (length > 50) { + output = braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + + } else { + output = braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; + } + + return output; + } + return format(obj, (typeof depth === 'undefined' ? 2 : depth)); + }; + + function isArray (ar) { + return Object.prototype.toString.call(ar) == '[object Array]'; + }; + + function isRegExp(re) { + var s = '' + re; + return re instanceof RegExp || // easy case + // duck-type for context-switching evalcx case + typeof(re) === 'function' && + re.constructor.name === 'RegExp' && + re.compile && + re.test && + re.exec && + s.match(/^\/.*\/[gim]{0,3}$/); + }; + + function isDate(d) { + if (d instanceof Date) return true; + return false; + }; + + function keys (obj) { + if (Object.keys) { + return Object.keys(obj); + } + + var keys = []; + + for (var i in obj) { + if (Object.prototype.hasOwnProperty.call(obj, i)) { + keys.push(i); + } + } + + return keys; + } + + function map (arr, mapper, that) { + if (Array.prototype.map) { + return Array.prototype.map.call(arr, mapper, that); + } + + var other= new Array(arr.length); + + for (var i= 0, n = arr.length; i= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + + // if array contains no values, no initial value to return + if (++i >= len) + throw new TypeError(); + } while (true); + } + + for (; i < len; i++) { + if (i in this) + rv = fun.call(null, rv, this[i], i, this); + } + + return rv; + }; + + /** + * Asserts deep equality + * + * @see taken from node.js `assert` module (copyright Joyent, MIT license) + * @api private + */ + + expect.eql = function eql (actual, expected) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + } else if ('undefined' != typeof Buffer + && Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) { + if (actual.length != expected.length) return false; + + for (var i = 0; i < actual.length; i++) { + if (actual[i] !== expected[i]) return false; + } + + return true; + + // 7.2. If the expected value is a Date object, the actual value is + // equivalent if it is also a Date object that refers to the same time. + } else if (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + // 7.3. Other pairs that do not both pass typeof value == "object", + // equivalence is determined by ==. + } else if (typeof actual != 'object' && typeof expected != 'object') { + return actual == expected; + + // 7.4. For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical "prototype" property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } + } + + function isUndefinedOrNull (value) { + return value === null || value === undefined; + } + + function isArguments (object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; + } + + function objEquiv (a, b) { + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + // an identical "prototype" property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return expect.eql(a, b); + } + try{ + var ka = keys(a), + kb = keys(b), + key, i; + } catch (e) {//happens when one is a string literal and the other isn't + return false; + } + // having the same number of owned properties (keys incorporates hasOwnProperty) + if (ka.length != kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!expect.eql(a[key], b[key])) + return false; + } + return true; + } + + var json = (function () { + "use strict"; + + if ('object' == typeof JSON && JSON.parse && JSON.stringify) { + return { + parse: nativeJSON.parse + , stringify: nativeJSON.stringify + } + } + + var JSON = {}; + + function f(n) { + // Format integers to have at least two digits. + return n < 10 ? '0' + n : n; + } + + function date(d, key) { + return isFinite(d.valueOf()) ? + d.getUTCFullYear() + '-' + + f(d.getUTCMonth() + 1) + '-' + + f(d.getUTCDate()) + 'T' + + f(d.getUTCHours()) + ':' + + f(d.getUTCMinutes()) + ':' + + f(d.getUTCSeconds()) + 'Z' : null; + }; + + 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 instanceof Date) { + value = date(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) { + if (typeof rep[i] === 'string') { + k = rep[i]; + 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.prototype.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. + + 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. + + 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.prototype.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. + + text = String(text); + 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'); + }; + + return JSON; + })(); + + if ('undefined' != typeof window) { + window.expect = module.exports; + } + +})( + this + , 'undefined' != typeof module ? module : {} + , 'undefined' != typeof exports ? exports : {} +); \ No newline at end of file diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/test/browser/index.html b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/test/browser/index.html new file mode 100644 index 0000000..c73147a --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/test/browser/index.html @@ -0,0 +1,18 @@ + + + Mocha + + + + + + + + + + + + +
        + + diff --git a/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/test/browser/jquery.js b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/test/browser/jquery.js new file mode 100644 index 0000000..f3201aa --- /dev/null +++ b/node_modules/grunt-contrib-watch/node_modules/tiny-lr/node_modules/qs/test/browser/jquery.js @@ -0,0 +1,8981 @@ +/*! + * jQuery JavaScript Library v1.6.2 + * http://jquery.com/ + * + * Copyright 2011, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Thu Jun 30 14:16:56 2011 -0400 + */ +(function( window, undefined ) { + +// Use the correct document accordingly with window argument (sandbox) +var document = window.document, + navigator = window.navigator, + location = window.location; +var jQuery = (function() { + +// Define a local copy of jQuery +var jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // A central reference to the root jQuery(document) + rootjQuery, + + // A simple way to check for HTML strings or ID strings + // (both of which we optimize for) + quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, + + // Check if a string has a non-whitespace character in it + rnotwhite = /\S/, + + // Used for trimming whitespace + trimLeft = /^\s+/, + trimRight = /\s+$/, + + // Check for digits + rdigit = /\d/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, + + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, + rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + + // Useragent RegExp + rwebkit = /(webkit)[ \/]([\w.]+)/, + ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, + rmsie = /(msie) ([\w.]+)/, + rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, + + // Matches dashed string for camelizing + rdashAlpha = /-([a-z])/ig, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + + // Keep a UserAgent string for use with jQuery.browser + userAgent = navigator.userAgent, + + // For matching the engine and version of the browser + browserMatch, + + // The deferred used on DOM ready + readyList, + + // The ready event handler + DOMContentLoaded, + + // Save a reference to some core methods + toString = Object.prototype.toString, + hasOwn = Object.prototype.hasOwnProperty, + push = Array.prototype.push, + slice = Array.prototype.slice, + trim = String.prototype.trim, + indexOf = Array.prototype.indexOf, + + // [[Class]] -> type pairs + class2type = {}; + +jQuery.fn = jQuery.prototype = { + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem, ret, doc; + + // Handle $(""), $(null), or $(undefined) + if ( !selector ) { + return this; + } + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + } + + // The body element only exists once, optimize finding it + if ( selector === "body" && !context && document.body ) { + this.context = document; + this[0] = document.body; + this.selector = selector; + this.length = 1; + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + // Are we dealing with HTML string or an ID? + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = quickExpr.exec( selector ); + } + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + doc = (context ? context.ownerDocument || context : document); + + // If a single string is passed in and it's a single tag + // just do a createElement and skip the rest + ret = rsingleTag.exec( selector ); + + if ( ret ) { + if ( jQuery.isPlainObject( context ) ) { + selector = [ document.createElement( ret[1] ) ]; + jQuery.fn.attr.call( selector, context, true ); + + } else { + selector = [ doc.createElement( ret[1] ) ]; + } + + } else { + ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); + selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes; + } + + return jQuery.merge( this, selector ); + + // HANDLE: $("#id") + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return (context || rootjQuery).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if (selector.selector !== undefined) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The current version of jQuery being used + jquery: "1.6.2", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return slice.call( this, 0 ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems, name, selector ) { + // Build a new jQuery matched element set + var ret = this.constructor(); + + if ( jQuery.isArray( elems ) ) { + push.apply( ret, elems ); + + } else { + jQuery.merge( ret, elems ); + } + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + ret.context = this.context; + + if ( name === "find" ) { + ret.selector = this.selector + (this.selector ? " " : "") + selector; + } else if ( name ) { + ret.selector = this.selector + "." + name + "(" + selector + ")"; + } + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Attach the listeners + jQuery.bindReady(); + + // Add the callback + readyList.done( fn ); + + return this; + }, + + eq: function( i ) { + return i === -1 ? + this.slice( i ) : + this.slice( i, +i + 1 ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ), + "slice", slice.call(arguments).join(",") ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + // Either a released hold or an DOMready/load event and not yet ready + if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready, 1 ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger( "ready" ).unbind( "ready" ); + } + } + }, + + bindReady: function() { + if ( readyList ) { + return; + } + + readyList = jQuery._Deferred(); + + // Catch cases where $(document).ready() is called after the + // browser event has already occurred. + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + return setTimeout( jQuery.ready, 1 ); + } + + // Mozilla, Opera and webkit nightlies currently support this event + if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", jQuery.ready, false ); + + // If IE event model is used + } else if ( document.attachEvent ) { + // ensure firing before onload, + // maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", DOMContentLoaded ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", jQuery.ready ); + + // If IE and not a frame + // continually check to see if the document is ready + var toplevel = false; + + try { + toplevel = window.frameElement == null; + } catch(e) {} + + if ( document.documentElement.doScroll && toplevel ) { + doScrollCheck(); + } + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + // A crude way of determining if an object is a window + isWindow: function( obj ) { + return obj && typeof obj === "object" && "setInterval" in obj; + }, + + isNaN: function( obj ) { + return obj == null || !rdigit.test( obj ) || isNaN( obj ); + }, + + type: function( obj ) { + return obj == null ? + String( obj ) : + class2type[ toString.call(obj) ] || "object"; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + for ( var name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw msg; + }, + + parseJSON: function( data ) { + if ( typeof data !== "string" || !data ) { + return null; + } + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return (new Function( "return " + data ))(); + + } + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + // (xml & tmp used internally) + parseXML: function( data , xml , tmp ) { + + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + + tmp = xml.documentElement; + + if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) { + jQuery.error( "Invalid XML: " + data ); + } + + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && rnotwhite.test( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + } )( data ); + } + }, + + // Converts a dashed string to camelCased string; + // Used by both the css and data modules + camelCase: function( string ) { + return string.replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); + }, + + // args is for internal usage only + each: function( object, callback, args ) { + var name, i = 0, + length = object.length, + isObj = length === undefined || jQuery.isFunction( object ); + + if ( args ) { + if ( isObj ) { + for ( name in object ) { + if ( callback.apply( object[ name ], args ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.apply( object[ i++ ], args ) === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isObj ) { + for ( name in object ) { + if ( callback.call( object[ name ], name, object[ name ] ) === false ) { + break; + } + } + } else { + for ( ; i < length; ) { + if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { + break; + } + } + } + } + + return object; + }, + + // Use native String.trim function wherever possible + trim: trim ? + function( text ) { + return text == null ? + "" : + trim.call( text ); + } : + + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); + }, + + // results is for internal usage only + makeArray: function( array, results ) { + var ret = results || []; + + if ( array != null ) { + // The window, strings (and functions) also have 'length' + // The extra typeof function check is to prevent crashes + // in Safari 2 (See: #3039) + // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 + var type = jQuery.type( array ); + + if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { + push.call( ret, array ); + } else { + jQuery.merge( ret, array ); + } + } + + return ret; + }, + + inArray: function( elem, array ) { + + if ( indexOf ) { + return indexOf.call( array, elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + }, + + merge: function( first, second ) { + var i = first.length, + j = 0; + + if ( typeof second.length === "number" ) { + for ( var l = second.length; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var ret = [], retVal; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( var i = 0, length = elems.length; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, key, ret = [], + i = 0, + length = elems.length, + // jquery objects are treated as arrays + isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( key in elems ) { + value = callback( elems[ key ], key, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return ret.concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + if ( typeof context === "string" ) { + var tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + var args = slice.call( arguments, 2 ), + proxy = function() { + return fn.apply( context, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; + + return proxy; + }, + + // Mutifunctional method to get and set values to a collection + // The value/s can optionally be executed if it's a function + access: function( elems, key, value, exec, fn, pass ) { + var length = elems.length; + + // Setting many attributes + if ( typeof key === "object" ) { + for ( var k in key ) { + jQuery.access( elems, k, key[k], exec, fn, value ); + } + return elems; + } + + // Setting one attribute + if ( value !== undefined ) { + // Optionally, function values get executed if exec is true + exec = !pass && exec && jQuery.isFunction(value); + + for ( var i = 0; i < length; i++ ) { + fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); + } + + return elems; + } + + // Getting an attribute + return length ? fn( elems[0], key ) : undefined; + }, + + now: function() { + return (new Date()).getTime(); + }, + + // Use of jQuery.browser is frowned upon. + // More details: http://docs.jquery.com/Utilities/jQuery.browser + uaMatch: function( ua ) { + ua = ua.toLowerCase(); + + var match = rwebkit.exec( ua ) || + ropera.exec( ua ) || + rmsie.exec( ua ) || + ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || + []; + + return { browser: match[1] || "", version: match[2] || "0" }; + }, + + sub: function() { + function jQuerySub( selector, context ) { + return new jQuerySub.fn.init( selector, context ); + } + jQuery.extend( true, jQuerySub, this ); + jQuerySub.superclass = this; + jQuerySub.fn = jQuerySub.prototype = this(); + jQuerySub.fn.constructor = jQuerySub; + jQuerySub.sub = this.sub; + jQuerySub.fn.init = function init( selector, context ) { + if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { + context = jQuerySub( context ); + } + + return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); + }; + jQuerySub.fn.init.prototype = jQuerySub.fn; + var rootjQuerySub = jQuerySub(document); + return jQuerySub; + }, + + browser: {} +}); + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +browserMatch = jQuery.uaMatch( userAgent ); +if ( browserMatch.browser ) { + jQuery.browser[ browserMatch.browser ] = true; + jQuery.browser.version = browserMatch.version; +} + +// Deprecated, use jQuery.browser.webkit instead +if ( jQuery.browser.webkit ) { + jQuery.browser.safari = true; +} + +// IE doesn't match non-breaking spaces with \s +if ( rnotwhite.test( "\xA0" ) ) { + trimLeft = /^[\s\xA0]+/; + trimRight = /[\s\xA0]+$/; +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); + +// Cleanup functions for the document ready method +if ( document.addEventListener ) { + DOMContentLoaded = function() { + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); + jQuery.ready(); + }; + +} else if ( document.attachEvent ) { + DOMContentLoaded = function() { + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( document.readyState === "complete" ) { + document.detachEvent( "onreadystatechange", DOMContentLoaded ); + jQuery.ready(); + } + }; +} + +// The DOM ready check for Internet Explorer +function doScrollCheck() { + if ( jQuery.isReady ) { + return; + } + + try { + // If IE is used, use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + document.documentElement.doScroll("left"); + } catch(e) { + setTimeout( doScrollCheck, 1 ); + return; + } + + // and execute any waiting functions + jQuery.ready(); +} + +return jQuery; + +})(); + + +var // Promise methods + promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ), + // Static reference to slice + sliceDeferred = [].slice; + +jQuery.extend({ + // Create a simple deferred (one callbacks list) + _Deferred: function() { + var // callbacks list + callbacks = [], + // stored [ context , args ] + fired, + // to avoid firing when already doing so + firing, + // flag to know if the deferred has been cancelled + cancelled, + // the deferred itself + deferred = { + + // done( f1, f2, ...) + done: function() { + if ( !cancelled ) { + var args = arguments, + i, + length, + elem, + type, + _fired; + if ( fired ) { + _fired = fired; + fired = 0; + } + for ( i = 0, length = args.length; i < length; i++ ) { + elem = args[ i ]; + type = jQuery.type( elem ); + if ( type === "array" ) { + deferred.done.apply( deferred, elem ); + } else if ( type === "function" ) { + callbacks.push( elem ); + } + } + if ( _fired ) { + deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] ); + } + } + return this; + }, + + // resolve with given context and args + resolveWith: function( context, args ) { + if ( !cancelled && !fired && !firing ) { + // make sure args are available (#8421) + args = args || []; + firing = 1; + try { + while( callbacks[ 0 ] ) { + callbacks.shift().apply( context, args ); + } + } + finally { + fired = [ context, args ]; + firing = 0; + } + } + return this; + }, + + // resolve with this as context and given arguments + resolve: function() { + deferred.resolveWith( this, arguments ); + return this; + }, + + // Has this deferred been resolved? + isResolved: function() { + return !!( firing || fired ); + }, + + // Cancel + cancel: function() { + cancelled = 1; + callbacks = []; + return this; + } + }; + + return deferred; + }, + + // Full fledged deferred (two callbacks list) + Deferred: function( func ) { + var deferred = jQuery._Deferred(), + failDeferred = jQuery._Deferred(), + promise; + // Add errorDeferred methods, then and promise + jQuery.extend( deferred, { + then: function( doneCallbacks, failCallbacks ) { + deferred.done( doneCallbacks ).fail( failCallbacks ); + return this; + }, + always: function() { + return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments ); + }, + fail: failDeferred.done, + rejectWith: failDeferred.resolveWith, + reject: failDeferred.resolve, + isRejected: failDeferred.isResolved, + pipe: function( fnDone, fnFail ) { + return jQuery.Deferred(function( newDefer ) { + jQuery.each( { + done: [ fnDone, "resolve" ], + fail: [ fnFail, "reject" ] + }, function( handler, data ) { + var fn = data[ 0 ], + action = data[ 1 ], + returned; + if ( jQuery.isFunction( fn ) ) { + deferred[ handler ](function() { + returned = fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise().then( newDefer.resolve, newDefer.reject ); + } else { + newDefer[ action ]( returned ); + } + }); + } else { + deferred[ handler ]( newDefer[ action ] ); + } + }); + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + if ( obj == null ) { + if ( promise ) { + return promise; + } + promise = obj = {}; + } + var i = promiseMethods.length; + while( i-- ) { + obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ]; + } + return obj; + } + }); + // Make sure only one callback list will be used + deferred.done( failDeferred.cancel ).fail( deferred.cancel ); + // Unexpose cancel + delete deferred.cancel; + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + return deferred; + }, + + // Deferred helper + when: function( firstParam ) { + var args = arguments, + i = 0, + length = args.length, + count = length, + deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? + firstParam : + jQuery.Deferred(); + function resolveFunc( i ) { + return function( value ) { + args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; + if ( !( --count ) ) { + // Strange bug in FF4: + // Values changed onto the arguments object sometimes end up as undefined values + // outside the $.when method. Cloning the object into a fresh array solves the issue + deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) ); + } + }; + } + if ( length > 1 ) { + for( ; i < length; i++ ) { + if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) { + args[ i ].promise().then( resolveFunc(i), deferred.reject ); + } else { + --count; + } + } + if ( !count ) { + deferred.resolveWith( deferred, args ); + } + } else if ( deferred !== firstParam ) { + deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); + } + return deferred.promise(); + } +}); + + + +jQuery.support = (function() { + + var div = document.createElement( "div" ), + documentElement = document.documentElement, + all, + a, + select, + opt, + input, + marginDiv, + support, + fragment, + body, + testElementParent, + testElement, + testElementStyle, + tds, + events, + eventName, + i, + isSupported; + + // Preliminary tests + div.setAttribute("className", "t"); + div.innerHTML = "
        a"; + + all = div.getElementsByTagName( "*" ); + a = div.getElementsByTagName( "a" )[ 0 ]; + + // Can't get basic test support + if ( !all || !all.length || !a ) { + return {}; + } + + // First batch of supports tests + select = document.createElement( "select" ); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName( "input" )[ 0 ]; + + support = { + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: ( div.firstChild.nodeType === 3 ), + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName( "tbody" ).length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName( "link" ).length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: ( a.getAttribute( "href" ) === "/a" ), + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.55$/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Make sure that if no value is specified for a checkbox + // that it defaults to "on". + // (WebKit defaults to "" instead) + checkOn: ( input.value === "on" ), + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // Will be defined later + submitBubbles: true, + changeBubbles: true, + focusinBubbles: false, + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Test to see if it's possible to delete an expando from an element + // Fails in Internet Explorer + try { + delete div.test; + } catch( e ) { + support.deleteExpando = false; + } + + if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { + div.attachEvent( "onclick", function() { + // Cloning a node shouldn't copy over any + // bound event handlers (IE does this) + support.noCloneEvent = false; + }); + div.cloneNode( true ).fireEvent( "onclick" ); + } + + // Check if a radio maintains it's value + // after being appended to the DOM + input = document.createElement("input"); + input.value = "t"; + input.setAttribute("type", "radio"); + support.radioValue = input.value === "t"; + + input.setAttribute("checked", "checked"); + div.appendChild( input ); + fragment = document.createDocumentFragment(); + fragment.appendChild( div.firstChild ); + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + div.innerHTML = ""; + + // Figure out if the W3C box model works as expected + div.style.width = div.style.paddingLeft = "1px"; + + body = document.getElementsByTagName( "body" )[ 0 ]; + // We use our own, invisible, body unless the body is already present + // in which case we use a div (#9239) + testElement = document.createElement( body ? "div" : "body" ); + testElementStyle = { + visibility: "hidden", + width: 0, + height: 0, + border: 0, + margin: 0 + }; + if ( body ) { + jQuery.extend( testElementStyle, { + position: "absolute", + left: -1000, + top: -1000 + }); + } + for ( i in testElementStyle ) { + testElement.style[ i ] = testElementStyle[ i ]; + } + testElement.appendChild( div ); + testElementParent = body || documentElement; + testElementParent.insertBefore( testElement, testElementParent.firstChild ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + support.boxModel = div.offsetWidth === 2; + + if ( "zoom" in div.style ) { + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + // (IE < 8 does this) + div.style.display = "inline"; + div.style.zoom = 1; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 ); + + // Check if elements with layout shrink-wrap their children + // (IE 6 does this) + div.style.display = ""; + div.innerHTML = "
        "; + support.shrinkWrapBlocks = ( div.offsetWidth !== 2 ); + } + + div.innerHTML = "
        t
        "; + tds = div.getElementsByTagName( "td" ); + + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + // (only IE 8 fails this test) + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Check if empty table cells still have offsetWidth/Height + // (IE < 8 fail this test) + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + div.innerHTML = ""; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. For more + // info see bug #3333 + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + if ( document.defaultView && document.defaultView.getComputedStyle ) { + marginDiv = document.createElement( "div" ); + marginDiv.style.width = "0"; + marginDiv.style.marginRight = "0"; + div.appendChild( marginDiv ); + support.reliableMarginRight = + ( parseInt( ( document.defaultView.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; + } + + // Remove the body element we added + testElement.innerHTML = ""; + testElementParent.removeChild( testElement ); + + // Technique from Juriy Zaytsev + // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/ + // We only care about the case where non-standard event systems + // are used, namely in IE. Short-circuiting here helps us to + // avoid an eval call (in setAttribute) which can cause CSP + // to go haywire. See: https://developer.mozilla.org/en/Security/CSP + if ( div.attachEvent ) { + for( i in { + submit: 1, + change: 1, + focusin: 1 + } ) { + eventName = "on" + i; + isSupported = ( eventName in div ); + if ( !isSupported ) { + div.setAttribute( eventName, "return;" ); + isSupported = ( typeof div[ eventName ] === "function" ); + } + support[ i + "Bubbles" ] = isSupported; + } + } + + // Null connected elements to avoid leaks in IE + testElement = fragment = select = opt = body = marginDiv = div = input = null; + + return support; +})(); + +// Keep track of boxModel +jQuery.boxModel = jQuery.support.boxModel; + + + + +var rbrace = /^(?:\{.*\}|\[.*\])$/, + rmultiDash = /([a-z])([A-Z])/g; + +jQuery.extend({ + cache: {}, + + // Please use with caution + uuid: 0, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache, + + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ jQuery.expando ] = id = ++jQuery.uuid; + } else { + id = jQuery.expando; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name); + } else { + cache[ id ] = jQuery.extend(cache[ id ], name); + } + } + + thisCache = cache[ id ]; + + // Internal jQuery data is stored in a separate object inside the object's data + // cache in order to avoid key collisions between internal data and user-defined + // data + if ( pvt ) { + if ( !thisCache[ internalKey ] ) { + thisCache[ internalKey ] = {}; + } + + thisCache = thisCache[ internalKey ]; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should + // not attempt to inspect the internal events object using jQuery.data, as this + // internal data object is undocumented and subject to change. + if ( name === "events" && !thisCache[name] ) { + return thisCache[ internalKey ] && thisCache[ internalKey ].events; + } + + return getByName ? + // Check for both converted-to-camel and non-converted data property names + thisCache[ jQuery.camelCase( name ) ] || thisCache[ name ] : + thisCache; + }, + + removeData: function( elem, name, pvt /* Internal Use Only */ ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var internalKey = jQuery.expando, isNode = elem.nodeType, + + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + + // See jQuery.data for more information + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ]; + + if ( thisCache ) { + delete thisCache[ name ]; + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !isEmptyDataObject(thisCache) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( pvt ) { + delete cache[ id ][ internalKey ]; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject(cache[ id ]) ) { + return; + } + } + + var internalCache = cache[ id ][ internalKey ]; + + // Browsers that fail expando deletion also refuse to delete expandos on + // the window, but it will allow it on all other JS objects; other browsers + // don't care + if ( jQuery.support.deleteExpando || cache != window ) { + delete cache[ id ]; + } else { + cache[ id ] = null; + } + + // We destroyed the entire user cache at once because it's faster than + // iterating through each key, but we need to continue to persist internal + // data if it existed + if ( internalCache ) { + cache[ id ] = {}; + // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery + // metadata on plain JS objects when the object is serialized using + // JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + + cache[ id ][ internalKey ] = internalCache; + + // Otherwise, we need to eliminate the expando on the node to avoid + // false lookups in the cache for entries that no longer exist + } else if ( isNode ) { + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( jQuery.support.deleteExpando ) { + delete elem[ jQuery.expando ]; + } else if ( elem.removeAttribute ) { + elem.removeAttribute( jQuery.expando ); + } else { + elem[ jQuery.expando ] = null; + } + } + }, + + // For internal use only. + _data: function( elem, name, data ) { + return jQuery.data( elem, name, data, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + if ( elem.nodeName ) { + var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; + + if ( match ) { + return !(match === true || elem.getAttribute("classid") !== match); + } + } + + return true; + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var data = null; + + if ( typeof key === "undefined" ) { + if ( this.length ) { + data = jQuery.data( this[0] ); + + if ( this[0].nodeType === 1 ) { + var attr = this[0].attributes, name; + for ( var i = 0, l = attr.length; i < l; i++ ) { + name = attr[i].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.substring(5) ); + + dataAttr( this[0], name, data[ name ] ); + } + } + } + } + + return data; + + } else if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value === undefined ) { + data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + // Try to fetch any internally stored data first + if ( data === undefined && this.length ) { + data = jQuery.data( this[0], key ); + data = dataAttr( this[0], key, data ); + } + + return data === undefined && parts[1] ? + this.data( parts[0] ) : + data; + + } else { + return this.each(function() { + var $this = jQuery( this ), + args = [ parts[0], value ]; + + $this.triggerHandler( "setData" + parts[1] + "!", args ); + jQuery.data( this, key, value ); + $this.triggerHandler( "changeData" + parts[1] + "!", args ); + }); + } + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + var name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + !jQuery.isNaN( data ) ? parseFloat( data ) : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; +} + +// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON +// property to be considered empty objects; this property always exists in +// order to make sure JSON.stringify does not expose internal metadata +function isEmptyDataObject( obj ) { + for ( var name in obj ) { + if ( name !== "toJSON" ) { + return false; + } + } + + return true; +} + + + + +function handleQueueMarkDefer( elem, type, src ) { + var deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + defer = jQuery.data( elem, deferDataKey, undefined, true ); + if ( defer && + ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) && + ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) { + // Give room for hard-coded callbacks to fire first + // and eventually mark/queue something else on the element + setTimeout( function() { + if ( !jQuery.data( elem, queueDataKey, undefined, true ) && + !jQuery.data( elem, markDataKey, undefined, true ) ) { + jQuery.removeData( elem, deferDataKey, true ); + defer.resolve(); + } + }, 0 ); + } +} + +jQuery.extend({ + + _mark: function( elem, type ) { + if ( elem ) { + type = (type || "fx") + "mark"; + jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true ); + } + }, + + _unmark: function( force, elem, type ) { + if ( force !== true ) { + type = elem; + elem = force; + force = false; + } + if ( elem ) { + type = type || "fx"; + var key = type + "mark", + count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 ); + if ( count ) { + jQuery.data( elem, key, count, true ); + } else { + jQuery.removeData( elem, key, true ); + handleQueueMarkDefer( elem, type, "mark" ); + } + } + }, + + queue: function( elem, type, data ) { + if ( elem ) { + type = (type || "fx") + "queue"; + var q = jQuery.data( elem, type, undefined, true ); + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !q || jQuery.isArray(data) ) { + q = jQuery.data( elem, type, jQuery.makeArray(data), true ); + } else { + q.push( data ); + } + } + return q || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + fn = queue.shift(), + defer; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + } + + if ( fn ) { + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift("inprogress"); + } + + fn.call(elem, function() { + jQuery.dequeue(elem, type); + }); + } + + if ( !queue.length ) { + jQuery.removeData( elem, type + "queue", true ); + handleQueueMarkDefer( elem, type, "queue" ); + } + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + } + + if ( data === undefined ) { + return jQuery.queue( this[0], type ); + } + return this.each(function() { + var queue = jQuery.queue( this, type, data ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[time] || time : time; + type = type || "fx"; + + return this.queue( type, function() { + var elem = this; + setTimeout(function() { + jQuery.dequeue( elem, type ); + }, time ); + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, object ) { + if ( typeof type !== "string" ) { + object = type; + type = undefined; + } + type = type || "fx"; + var defer = jQuery.Deferred(), + elements = this, + i = elements.length, + count = 1, + deferDataKey = type + "defer", + queueDataKey = type + "queue", + markDataKey = type + "mark", + tmp; + function resolve() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + } + while( i-- ) { + if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || + ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || + jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && + jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) { + count++; + tmp.done( resolve ); + } + } + resolve(); + return defer.promise(); + } +}); + + + + +var rclass = /[\n\t\r]/g, + rspace = /\s+/, + rreturn = /\r/g, + rtype = /^(?:button|input)$/i, + rfocusable = /^(?:button|input|object|select|textarea)$/i, + rclickable = /^a(?:rea)?$/i, + rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, + rinvalidChar = /\:|^on/, + formHook, boolHook; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.attr ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, name, value, true, jQuery.prop ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch( e ) {} + }); + }, + + addClass: function( value ) { + var classNames, i, l, elem, + setClass, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call(this, j, this.className) ); + }); + } + + if ( value && typeof value === "string" ) { + classNames = value.split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 ) { + if ( !elem.className && classNames.length === 1 ) { + elem.className = value; + + } else { + setClass = " " + elem.className + " "; + + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { + setClass += classNames[ c ] + " "; + } + } + elem.className = jQuery.trim( setClass ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classNames, i, l, elem, className, c, cl; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call(this, j, this.className) ); + }); + } + + if ( (value && typeof value === "string") || value === undefined ) { + classNames = (value || "").split( rspace ); + + for ( i = 0, l = this.length; i < l; i++ ) { + elem = this[ i ]; + + if ( elem.nodeType === 1 && elem.className ) { + if ( value ) { + className = (" " + elem.className + " ").replace( rclass, " " ); + for ( c = 0, cl = classNames.length; c < cl; c++ ) { + className = className.replace(" " + classNames[ c ] + " ", " "); + } + elem.className = jQuery.trim( className ); + + } else { + elem.className = ""; + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.split( rspace ); + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space seperated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + } else if ( type === "undefined" || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // toggle whole className + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " "; + for ( var i = 0, l = this.length; i < l; i++ ) { + if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return undefined; + } + + var isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var self = jQuery(this), val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, + index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type === "select-one"; + + // Nothing was selected + if ( index < 0 ) { + return null; + } + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + // Don't return options that are disabled or in a disabled optgroup + if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && + (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + // Fixes Bug #2551 -- select.val() broken in IE after form.reset() + if ( one && !values.length && options.length ) { + return jQuery( options[ index ] ).val(); + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attrFn: { + val: true, + css: true, + html: true, + text: true, + data: true, + width: true, + height: true, + offset: true + }, + + attrFix: { + // Always normalize to ensure hook usage + tabindex: "tabIndex" + }, + + attr: function( elem, name, value, pass ) { + var nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + if ( pass && name in jQuery.attrFn ) { + return jQuery( elem )[ name ]( value ); + } + + // Fallback to prop when attributes are not supported + if ( !("getAttribute" in elem) ) { + return jQuery.prop( elem, name, value ); + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // Normalize the name if needed + if ( notxml ) { + name = jQuery.attrFix[ name ] || name; + + hooks = jQuery.attrHooks[ name ]; + + if ( !hooks ) { + // Use boolHook for boolean attributes + if ( rboolean.test( name ) ) { + + hooks = boolHook; + + // Use formHook for forms and if the name contains certain characters + } else if ( formHook && name !== "className" && + (jQuery.nodeName( elem, "form" ) || rinvalidChar.test( name )) ) { + + hooks = formHook; + } + } + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return undefined; + + } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, "" + value ); + return value; + } + + } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + ret = elem.getAttribute( name ); + + // Non-existent attributes return null, we normalize to undefined + return ret === null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, name ) { + var propName; + if ( elem.nodeType === 1 ) { + name = jQuery.attrFix[ name ] || name; + + if ( jQuery.support.getSetAttribute ) { + // Use removeAttribute in browsers that support it + elem.removeAttribute( name ); + } else { + jQuery.attr( elem, name, "" ); + elem.removeAttributeNode( elem.getAttributeNode( name ) ); + } + + // Set corresponding property to false for boolean attributes + if ( rboolean.test( name ) && (propName = jQuery.propFix[ name ] || name) in elem ) { + elem[ propName ] = false; + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + // We can't allow the type property to be changed (since it causes problems in IE) + if ( rtype.test( elem.nodeName ) && elem.parentNode ) { + jQuery.error( "type property can't be changed" ); + } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to it's default in case type is set after value + // This is for element creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + }, + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabIndex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + }, + // Use the value property for back compat + // Use the formHook for button elements in IE6/7 (#1954) + value: { + get: function( elem, name ) { + if ( formHook && jQuery.nodeName( elem, "button" ) ) { + return formHook.get( elem, name ); + } + return name in elem ? + elem.value : + null; + }, + set: function( elem, value, name ) { + if ( formHook && jQuery.nodeName( elem, "button" ) ) { + return formHook.set( elem, value, name ); + } + // Does not return so that setAttribute is also used + elem.value = value; + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return undefined; + } + + var ret, hooks, + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return (elem[ name ] = value); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: {} +}); + +// Hook for boolean attributes +boolHook = { + get: function( elem, name ) { + // Align boolean attributes with corresponding properties + return jQuery.prop( elem, name ) ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + var propName; + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + // value is true since we know at this point it's type boolean and not false + // Set boolean attributes to the same name and set the DOM property + propName = jQuery.propFix[ name ] || name; + if ( propName in elem ) { + // Only set the IDL specifically if it already exists on the element + elem[ propName ] = true; + } + + elem.setAttribute( name, name.toLowerCase() ); + } + return name; + } +}; + +// IE6/7 do not support getting/setting some attributes with get/setAttribute +if ( !jQuery.support.getSetAttribute ) { + + // propFix is more comprehensive and contains all fixes + jQuery.attrFix = jQuery.propFix; + + // Use this for any attribute on a form in IE6/7 + formHook = jQuery.attrHooks.name = jQuery.attrHooks.title = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret; + ret = elem.getAttributeNode( name ); + // Return undefined if nodeValue is empty string + return ret && ret.nodeValue !== "" ? + ret.nodeValue : + undefined; + }, + set: function( elem, value, name ) { + // Check form objects in IE (multiple bugs related) + // Only use nodeValue if the attribute node exists on the form + var ret = elem.getAttributeNode( name ); + if ( ret ) { + ret.nodeValue = value; + return value; + } + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); +} + + +// Some attributes require a special call on IE +if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret === null ? undefined : ret; + } + }); + }); +} + +if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Normalize to lowercase since IE uppercases css property names + return elem.style.cssText.toLowerCase() || undefined; + }, + set: function( elem, value ) { + return (elem.style.cssText = "" + value); + } + }; +} + +// Safari mis-reports the default selected property of an option +// Accessing the parent's selectedIndex property fixes it +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }); +} + +// Radios and checkboxes getter/setter +if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); +} +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0); + } + } + }); +}); + + + + +var rnamespaces = /\.(.*)$/, + rformElems = /^(?:textarea|input|select)$/i, + rperiod = /\./g, + rspaces = / /g, + rescape = /[^\w\s.|`]/g, + fcleanup = function( nm ) { + return nm.replace(rescape, "\\$&"); + }; + +/* + * A number of helper functions used for managing events. + * Many of the ideas behind this code originated from + * Dean Edwards' addEvent library. + */ +jQuery.event = { + + // Bind an event to an element + // Original by Dean Edwards + add: function( elem, types, handler, data ) { + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } else if ( !handler ) { + // Fixes bug #7229. Fix recommended by jdalton + return; + } + + var handleObjIn, handleObj; + + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + } + + // Make sure that the function being executed has a unique ID + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure + var elemData = jQuery._data( elem ); + + // If no elemData is found then we must be trying to bind to one of the + // banned noData elements + if ( !elemData ) { + return; + } + + var events = elemData.events, + eventHandle = elemData.handle; + + if ( !events ) { + elemData.events = events = {}; + } + + if ( !eventHandle ) { + elemData.handle = eventHandle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.handle.apply( eventHandle.elem, arguments ) : + undefined; + }; + } + + // Add elem as a property of the handle function + // This is to prevent a memory leak with non-native events in IE. + eventHandle.elem = elem; + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = types.split(" "); + + var type, i = 0, namespaces; + + while ( (type = types[ i++ ]) ) { + handleObj = handleObjIn ? + jQuery.extend({}, handleObjIn) : + { handler: handler, data: data }; + + // Namespaced event handlers + if ( type.indexOf(".") > -1 ) { + namespaces = type.split("."); + type = namespaces.shift(); + handleObj.namespace = namespaces.slice(0).sort().join("."); + + } else { + namespaces = []; + handleObj.namespace = ""; + } + + handleObj.type = type; + if ( !handleObj.guid ) { + handleObj.guid = handler.guid; + } + + // Get the current list of functions bound to this event + var handlers = events[ type ], + special = jQuery.event.special[ type ] || {}; + + // Init the event handler queue + if ( !handlers ) { + handlers = events[ type ] = []; + + // Check for a special event handler + // Only use addEventListener/attachEvent if the special + // events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add the function to the element's handler list + handlers.push( handleObj ); + + // Keep track of which events have been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + global: {}, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, pos ) { + // don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + if ( handler === false ) { + handler = returnFalse; + } + + var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ), + events = elemData && elemData.events; + + if ( !elemData || !events ) { + return; + } + + // types is actually an event object here + if ( types && types.type ) { + handler = types.handler; + types = types.type; + } + + // Unbind all events for the element + if ( !types || typeof types === "string" && types.charAt(0) === "." ) { + types = types || ""; + + for ( type in events ) { + jQuery.event.remove( elem, type + types ); + } + + return; + } + + // Handle multiple events separated by a space + // jQuery(...).unbind("mouseover mouseout", fn); + types = types.split(" "); + + while ( (type = types[ i++ ]) ) { + origType = type; + handleObj = null; + all = type.indexOf(".") < 0; + namespaces = []; + + if ( !all ) { + // Namespaced event handlers + namespaces = type.split("."); + type = namespaces.shift(); + + namespace = new RegExp("(^|\\.)" + + jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + eventType = events[ type ]; + + if ( !eventType ) { + continue; + } + + if ( !handler ) { + for ( j = 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( all || namespace.test( handleObj.namespace ) ) { + jQuery.event.remove( elem, origType, handleObj.handler, j ); + eventType.splice( j--, 1 ); + } + } + + continue; + } + + special = jQuery.event.special[ type ] || {}; + + for ( j = pos || 0; j < eventType.length; j++ ) { + handleObj = eventType[ j ]; + + if ( handler.guid === handleObj.guid ) { + // remove the given handler for the given type + if ( all || namespace.test( handleObj.namespace ) ) { + if ( pos == null ) { + eventType.splice( j--, 1 ); + } + + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + + if ( pos != null ) { + break; + } + } + } + + // remove generic event handler if no more handlers exist + if ( eventType.length === 0 || pos != null && eventType.length === 1 ) { + if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + ret = null; + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + var handle = elemData.handle; + if ( handle ) { + handle.elem = null; + } + + delete elemData.events; + delete elemData.handle; + + if ( jQuery.isEmptyObject( elemData ) ) { + jQuery.removeData( elem, undefined, true ); + } + } + }, + + // Events that are safe to short-circuit if no handlers are attached. + // Native DOM events should not be added, they may have inline handlers. + customEvent: { + "getData": true, + "setData": true, + "changeData": true + }, + + trigger: function( event, data, elem, onlyHandlers ) { + // Event object or event type + var type = event.type || event, + namespaces = [], + exclusive; + + if ( type.indexOf("!") >= 0 ) { + // Exclusive events trigger only for the exact event (no namespaces) + type = type.slice(0, -1); + exclusive = true; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + + if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + // No jQuery handlers for this event type, and it can't have inline handlers + return; + } + + // Caller can pass in an Event, Object, or just an event type string + event = typeof event === "object" ? + // jQuery.Event object + event[ jQuery.expando ] ? event : + // Object literal + new jQuery.Event( type, event ) : + // Just the event type (string) + new jQuery.Event( type ); + + event.type = type; + event.exclusive = exclusive; + event.namespace = namespaces.join("."); + event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)"); + + // triggerHandler() and global events don't bubble or run the default action + if ( onlyHandlers || !elem ) { + event.preventDefault(); + event.stopPropagation(); + } + + // Handle a global trigger + if ( !elem ) { + // TODO: Stop taunting the data cache; remove global events and always attach to document + jQuery.each( jQuery.cache, function() { + // internalKey variable is just used to make it easier to find + // and potentially change this stuff later; currently it just + // points to jQuery.expando + var internalKey = jQuery.expando, + internalCache = this[ internalKey ]; + if ( internalCache && internalCache.events && internalCache.events[ type ] ) { + jQuery.event.trigger( event, data, internalCache.handle.elem ); + } + }); + return; + } + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // Clean up the event in case it is being reused + event.result = undefined; + event.target = elem; + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data != null ? jQuery.makeArray( data ) : []; + data.unshift( event ); + + var cur = elem, + // IE doesn't like method names with a colon (#3533, #8272) + ontype = type.indexOf(":") < 0 ? "on" + type : ""; + + // Fire event on the current element, then bubble up the DOM tree + do { + var handle = jQuery._data( cur, "handle" ); + + event.currentTarget = cur; + if ( handle ) { + handle.apply( cur, data ); + } + + // Trigger an inline bound script + if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { + event.result = false; + event.preventDefault(); + } + + // Bubble up to document, then to window + cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window; + } while ( cur && !event.isPropagationStopped() ); + + // If nobody prevented the default action, do it now + if ( !event.isDefaultPrevented() ) { + var old, + special = jQuery.event.special[ type ] || {}; + + if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction)() check here because IE6/7 fails that test. + // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch. + try { + if ( ontype && elem[ type ] ) { + // Don't re-trigger an onFOO event when we call its FOO() method + old = elem[ ontype ]; + + if ( old ) { + elem[ ontype ] = null; + } + + jQuery.event.triggered = type; + elem[ type ](); + } + } catch ( ieError ) {} + + if ( old ) { + elem[ ontype ] = old; + } + + jQuery.event.triggered = undefined; + } + } + + return event.result; + }, + + handle: function( event ) { + event = jQuery.event.fix( event || window.event ); + // Snapshot the handlers list since a called handler may add/remove events. + var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0), + run_all = !event.exclusive && !event.namespace, + args = Array.prototype.slice.call( arguments, 0 ); + + // Use the fix-ed Event rather than the (read-only) native event + args[0] = event; + event.currentTarget = this; + + for ( var j = 0, l = handlers.length; j < l; j++ ) { + var handleObj = handlers[ j ]; + + // Triggered event must 1) be non-exclusive and have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event. + if ( run_all || event.namespace_re.test( handleObj.namespace ) ) { + // Pass in a reference to the handler function itself + // So that we can later remove it + event.handler = handleObj.handler; + event.data = handleObj.data; + event.handleObj = handleObj; + + var ret = handleObj.handler.apply( this, args ); + + if ( ret !== undefined ) { + event.result = ret; + if ( ret === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + return event.result; + }, + + props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "), + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // store a copy of the original event object + // and "clone" to set read-only properties + var originalEvent = event; + event = jQuery.Event( originalEvent ); + + for ( var i = this.props.length, prop; i; ) { + prop = this.props[ --i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Fix target property, if necessary + if ( !event.target ) { + // Fixes #1925 where srcElement might not be defined either + event.target = event.srcElement || document; + } + + // check if target is a textnode (safari) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && event.fromElement ) { + event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement; + } + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && event.clientX != null ) { + var eventDocument = event.target.ownerDocument || document, + doc = eventDocument.documentElement, + body = eventDocument.body; + + event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0); + event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0); + } + + // Add which for key events + if ( event.which == null && (event.charCode != null || event.keyCode != null) ) { + event.which = event.charCode != null ? event.charCode : event.keyCode; + } + + // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs) + if ( !event.metaKey && event.ctrlKey ) { + event.metaKey = event.ctrlKey; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && event.button !== undefined ) { + event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) )); + } + + return event; + }, + + // Deprecated, use jQuery.guid instead + guid: 1E8, + + // Deprecated, use jQuery.proxy instead + proxy: jQuery.proxy, + + special: { + ready: { + // Make sure the ready event is setup + setup: jQuery.bindReady, + teardown: jQuery.noop + }, + + live: { + add: function( handleObj ) { + jQuery.event.add( this, + liveConvert( handleObj.origType, handleObj.selector ), + jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) ); + }, + + remove: function( handleObj ) { + jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj ); + } + }, + + beforeunload: { + setup: function( data, namespaces, eventHandle ) { + // We only want to do this special case on windows + if ( jQuery.isWindow( this ) ) { + this.onbeforeunload = eventHandle; + } + }, + + teardown: function( namespaces, eventHandle ) { + if ( this.onbeforeunload === eventHandle ) { + this.onbeforeunload = null; + } + } + } + } +}; + +jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + if ( elem.detachEvent ) { + elem.detachEvent( "on" + type, handle ); + } + }; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !this.preventDefault ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // timeStamp is buggy for some events on Firefox(#3843) + // So we won't rely on the native value + this.timeStamp = jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +function returnFalse() { + return false; +} +function returnTrue() { + return true; +} + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + preventDefault: function() { + this.isDefaultPrevented = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + + // if preventDefault exists run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // otherwise set the returnValue property of the original event to false (IE) + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + this.isPropagationStopped = returnTrue; + + var e = this.originalEvent; + if ( !e ) { + return; + } + // if stopPropagation exists run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + // otherwise set the cancelBubble property of the original event to true (IE) + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + }, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse +}; + +// Checks if an event happened on an element within another element +// Used in jQuery.event.special.mouseenter and mouseleave handlers +var withinElement = function( event ) { + + // Check if mouse(over|out) are still within the same parent element + var related = event.relatedTarget, + inside = false, + eventType = event.type; + + event.type = event.data; + + if ( related !== this ) { + + if ( related ) { + inside = jQuery.contains( this, related ); + } + + if ( !inside ) { + + jQuery.event.handle.apply( this, arguments ); + + event.type = eventType; + } + } +}, + +// In case of event delegation, we only need to rename the event.type, +// liveHandler will take care of the rest. +delegate = function( event ) { + event.type = event.data; + jQuery.event.handle.apply( this, arguments ); +}; + +// Create mouseenter and mouseleave events +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + setup: function( data ) { + jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig ); + }, + teardown: function( data ) { + jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement ); + } + }; +}); + +// submit delegation +if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function( data, namespaces ) { + if ( !jQuery.nodeName( this, "form" ) ) { + jQuery.event.add(this, "click.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) { + trigger( "submit", this, arguments ); + } + }); + + jQuery.event.add(this, "keypress.specialSubmit", function( e ) { + var elem = e.target, + type = elem.type; + + if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) { + trigger( "submit", this, arguments ); + } + }); + + } else { + return false; + } + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialSubmit" ); + } + }; + +} + +// change delegation, happens here so we have bind. +if ( !jQuery.support.changeBubbles ) { + + var changeFilters, + + getVal = function( elem ) { + var type = elem.type, val = elem.value; + + if ( type === "radio" || type === "checkbox" ) { + val = elem.checked; + + } else if ( type === "select-multiple" ) { + val = elem.selectedIndex > -1 ? + jQuery.map( elem.options, function( elem ) { + return elem.selected; + }).join("-") : + ""; + + } else if ( jQuery.nodeName( elem, "select" ) ) { + val = elem.selectedIndex; + } + + return val; + }, + + testChange = function testChange( e ) { + var elem = e.target, data, val; + + if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) { + return; + } + + data = jQuery._data( elem, "_change_data" ); + val = getVal(elem); + + // the current data will be also retrieved by beforeactivate + if ( e.type !== "focusout" || elem.type !== "radio" ) { + jQuery._data( elem, "_change_data", val ); + } + + if ( data === undefined || val === data ) { + return; + } + + if ( data != null || val ) { + e.type = "change"; + e.liveFired = undefined; + jQuery.event.trigger( e, arguments[1], elem ); + } + }; + + jQuery.event.special.change = { + filters: { + focusout: testChange, + + beforedeactivate: testChange, + + click: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) { + testChange.call( this, e ); + } + }, + + // Change has to be called before submit + // Keydown will be called before keypress, which is used in submit-event delegation + keydown: function( e ) { + var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : ""; + + if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) || + (e.keyCode === 32 && (type === "checkbox" || type === "radio")) || + type === "select-multiple" ) { + testChange.call( this, e ); + } + }, + + // Beforeactivate happens also before the previous element is blurred + // with this event you can't trigger a change event, but you can store + // information + beforeactivate: function( e ) { + var elem = e.target; + jQuery._data( elem, "_change_data", getVal(elem) ); + } + }, + + setup: function( data, namespaces ) { + if ( this.type === "file" ) { + return false; + } + + for ( var type in changeFilters ) { + jQuery.event.add( this, type + ".specialChange", changeFilters[type] ); + } + + return rformElems.test( this.nodeName ); + }, + + teardown: function( namespaces ) { + jQuery.event.remove( this, ".specialChange" ); + + return rformElems.test( this.nodeName ); + } + }; + + changeFilters = jQuery.event.special.change.filters; + + // Handle when the input is .focus()'d + changeFilters.focus = changeFilters.beforeactivate; +} + +function trigger( type, elem, args ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + // Don't pass args or remember liveFired; they apply to the donor event. + var event = jQuery.extend( {}, args[ 0 ] ); + event.type = type; + event.originalEvent = {}; + event.liveFired = undefined; + jQuery.event.handle.call( elem, event ); + if ( event.isDefaultPrevented() ) { + args[ 0 ].preventDefault(); + } +} + +// Create "bubbling" focus and blur events +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + + function handler( donor ) { + // Donor event is always a native one; fix it and switch its type. + // Let focusin/out handler cancel the donor focus/blur event. + var e = jQuery.event.fix( donor ); + e.type = fix; + e.originalEvent = {}; + jQuery.event.trigger( e, null, e.target ); + if ( e.isDefaultPrevented() ) { + donor.preventDefault(); + } + } + }); +} + +jQuery.each(["bind", "one"], function( i, name ) { + jQuery.fn[ name ] = function( type, data, fn ) { + var handler; + + // Handle object literals + if ( typeof type === "object" ) { + for ( var key in type ) { + this[ name ](key, data, type[key], fn); + } + return this; + } + + if ( arguments.length === 2 || data === false ) { + fn = data; + data = undefined; + } + + if ( name === "one" ) { + handler = function( event ) { + jQuery( this ).unbind( event, handler ); + return fn.apply( this, arguments ); + }; + handler.guid = fn.guid || jQuery.guid++; + } else { + handler = fn; + } + + if ( type === "unload" && name !== "one" ) { + this.one( type, data, fn ); + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.add( this[i], type, handler, data ); + } + } + + return this; + }; +}); + +jQuery.fn.extend({ + unbind: function( type, fn ) { + // Handle object literals + if ( typeof type === "object" && !type.preventDefault ) { + for ( var key in type ) { + this.unbind(key, type[key]); + } + + } else { + for ( var i = 0, l = this.length; i < l; i++ ) { + jQuery.event.remove( this[i], type, fn ); + } + } + + return this; + }, + + delegate: function( selector, types, data, fn ) { + return this.live( types, data, fn, selector ); + }, + + undelegate: function( selector, types, fn ) { + if ( arguments.length === 0 ) { + return this.unbind( "live" ); + + } else { + return this.die( types, null, fn, selector ); + } + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + + triggerHandler: function( type, data ) { + if ( this[0] ) { + return jQuery.event.trigger( type, data, this[0], true ); + } + }, + + toggle: function( fn ) { + // Save reference to arguments for access in closure + var args = arguments, + guid = fn.guid || jQuery.guid++, + i = 0, + toggler = function( event ) { + // Figure out which function to execute + var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i; + jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 ); + + // Make sure that clicks stop + event.preventDefault(); + + // and execute the function + return args[ lastToggle ].apply( this, arguments ) || false; + }; + + // link all the functions, so any of them can unbind this click handler + toggler.guid = guid; + while ( i < args.length ) { + args[ i++ ].guid = guid; + } + + return this.click( toggler ); + }, + + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + } +}); + +var liveMap = { + focus: "focusin", + blur: "focusout", + mouseenter: "mouseover", + mouseleave: "mouseout" +}; + +jQuery.each(["live", "die"], function( i, name ) { + jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) { + var type, i = 0, match, namespaces, preType, + selector = origSelector || this.selector, + context = origSelector ? this : jQuery( this.context ); + + if ( typeof types === "object" && !types.preventDefault ) { + for ( var key in types ) { + context[ name ]( key, data, types[key], selector ); + } + + return this; + } + + if ( name === "die" && !types && + origSelector && origSelector.charAt(0) === "." ) { + + context.unbind( origSelector ); + + return this; + } + + if ( data === false || jQuery.isFunction( data ) ) { + fn = data || returnFalse; + data = undefined; + } + + types = (types || "").split(" "); + + while ( (type = types[ i++ ]) != null ) { + match = rnamespaces.exec( type ); + namespaces = ""; + + if ( match ) { + namespaces = match[0]; + type = type.replace( rnamespaces, "" ); + } + + if ( type === "hover" ) { + types.push( "mouseenter" + namespaces, "mouseleave" + namespaces ); + continue; + } + + preType = type; + + if ( liveMap[ type ] ) { + types.push( liveMap[ type ] + namespaces ); + type = type + namespaces; + + } else { + type = (liveMap[ type ] || type) + namespaces; + } + + if ( name === "live" ) { + // bind live handler + for ( var j = 0, l = context.length; j < l; j++ ) { + jQuery.event.add( context[j], "live." + liveConvert( type, selector ), + { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } ); + } + + } else { + // unbind live handler + context.unbind( "live." + liveConvert( type, selector ), fn ); + } + } + + return this; + }; +}); + +function liveHandler( event ) { + var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret, + elems = [], + selectors = [], + events = jQuery._data( this, "events" ); + + // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911) + if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) { + return; + } + + if ( event.namespace ) { + namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)"); + } + + event.liveFired = this; + + var live = events.live.slice(0); + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) { + selectors.push( handleObj.selector ); + + } else { + live.splice( j--, 1 ); + } + } + + match = jQuery( event.target ).closest( selectors, event.currentTarget ); + + for ( i = 0, l = match.length; i < l; i++ ) { + close = match[i]; + + for ( j = 0; j < live.length; j++ ) { + handleObj = live[j]; + + if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) { + elem = close.elem; + related = null; + + // Those two events require additional checking + if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) { + event.type = handleObj.preType; + related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0]; + + // Make sure not to accidentally match a child element with the same selector + if ( related && jQuery.contains( elem, related ) ) { + related = elem; + } + } + + if ( !related || related !== elem ) { + elems.push({ elem: elem, handleObj: handleObj, level: close.level }); + } + } + } + } + + for ( i = 0, l = elems.length; i < l; i++ ) { + match = elems[i]; + + if ( maxLevel && match.level > maxLevel ) { + break; + } + + event.currentTarget = match.elem; + event.data = match.handleObj.data; + event.handleObj = match.handleObj; + + ret = match.handleObj.origHandler.apply( match.elem, arguments ); + + if ( ret === false || event.isPropagationStopped() ) { + maxLevel = match.level; + + if ( ret === false ) { + stop = false; + } + if ( event.isImmediatePropagationStopped() ) { + break; + } + } + } + + return stop; +} + +function liveConvert( type, selector ) { + return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&"); +} + +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + if ( fn == null ) { + fn = data; + data = null; + } + + return arguments.length > 0 ? + this.bind( name, data, fn ) : + this.trigger( name ); + }; + + if ( jQuery.attrFn ) { + jQuery.attrFn[ name ] = true; + } +}); + + + +/*! + * Sizzle CSS Selector Engine + * Copyright 2011, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * More information: http://sizzlejs.com/ + */ +(function(){ + +var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, + done = 0, + toString = Object.prototype.toString, + hasDuplicate = false, + baseHasDuplicate = true, + rBackslash = /\\/g, + rNonWord = /\W/; + +// Here we check if the JavaScript engine is using some sort of +// optimization where it does not always call our comparision +// function. If that is the case, discard the hasDuplicate value. +// Thus far that includes Google Chrome. +[0, 0].sort(function() { + baseHasDuplicate = false; + return 0; +}); + +var Sizzle = function( selector, context, results, seed ) { + results = results || []; + context = context || document; + + var origContext = context; + + if ( context.nodeType !== 1 && context.nodeType !== 9 ) { + return []; + } + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + var m, set, checkSet, extra, ret, cur, pop, i, + prune = true, + contextXML = Sizzle.isXML( context ), + parts = [], + soFar = selector; + + // Reset the position of the chunker regexp (start from head) + do { + chunker.exec( "" ); + m = chunker.exec( soFar ); + + if ( m ) { + soFar = m[3]; + + parts.push( m[1] ); + + if ( m[2] ) { + extra = m[3]; + break; + } + } + } while ( m ); + + if ( parts.length > 1 && origPOS.exec( selector ) ) { + + if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { + set = posProcess( parts[0] + parts[1], context ); + + } else { + set = Expr.relative[ parts[0] ] ? + [ context ] : + Sizzle( parts.shift(), context ); + + while ( parts.length ) { + selector = parts.shift(); + + if ( Expr.relative[ selector ] ) { + selector += parts.shift(); + } + + set = posProcess( selector, set ); + } + } + + } else { + // Take a shortcut and set the context if the root selector is an ID + // (but not if it'll be faster if the inner selector is an ID) + if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && + Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { + + ret = Sizzle.find( parts.shift(), context, contextXML ); + context = ret.expr ? + Sizzle.filter( ret.expr, ret.set )[0] : + ret.set[0]; + } + + if ( context ) { + ret = seed ? + { expr: parts.pop(), set: makeArray(seed) } : + Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); + + set = ret.expr ? + Sizzle.filter( ret.expr, ret.set ) : + ret.set; + + if ( parts.length > 0 ) { + checkSet = makeArray( set ); + + } else { + prune = false; + } + + while ( parts.length ) { + cur = parts.pop(); + pop = cur; + + if ( !Expr.relative[ cur ] ) { + cur = ""; + } else { + pop = parts.pop(); + } + + if ( pop == null ) { + pop = context; + } + + Expr.relative[ cur ]( checkSet, pop, contextXML ); + } + + } else { + checkSet = parts = []; + } + } + + if ( !checkSet ) { + checkSet = set; + } + + if ( !checkSet ) { + Sizzle.error( cur || selector ); + } + + if ( toString.call(checkSet) === "[object Array]" ) { + if ( !prune ) { + results.push.apply( results, checkSet ); + + } else if ( context && context.nodeType === 1 ) { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { + results.push( set[i] ); + } + } + + } else { + for ( i = 0; checkSet[i] != null; i++ ) { + if ( checkSet[i] && checkSet[i].nodeType === 1 ) { + results.push( set[i] ); + } + } + } + + } else { + makeArray( checkSet, results ); + } + + if ( extra ) { + Sizzle( extra, origContext, results, seed ); + Sizzle.uniqueSort( results ); + } + + return results; +}; + +Sizzle.uniqueSort = function( results ) { + if ( sortOrder ) { + hasDuplicate = baseHasDuplicate; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( var i = 1; i < results.length; i++ ) { + if ( results[i] === results[ i - 1 ] ) { + results.splice( i--, 1 ); + } + } + } + } + + return results; +}; + +Sizzle.matches = function( expr, set ) { + return Sizzle( expr, null, null, set ); +}; + +Sizzle.matchesSelector = function( node, expr ) { + return Sizzle( expr, null, null, [node] ).length > 0; +}; + +Sizzle.find = function( expr, context, isXML ) { + var set; + + if ( !expr ) { + return []; + } + + for ( var i = 0, l = Expr.order.length; i < l; i++ ) { + var match, + type = Expr.order[i]; + + if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { + var left = match[1]; + match.splice( 1, 1 ); + + if ( left.substr( left.length - 1 ) !== "\\" ) { + match[1] = (match[1] || "").replace( rBackslash, "" ); + set = Expr.find[ type ]( match, context, isXML ); + + if ( set != null ) { + expr = expr.replace( Expr.match[ type ], "" ); + break; + } + } + } + } + + if ( !set ) { + set = typeof context.getElementsByTagName !== "undefined" ? + context.getElementsByTagName( "*" ) : + []; + } + + return { set: set, expr: expr }; +}; + +Sizzle.filter = function( expr, set, inplace, not ) { + var match, anyFound, + old = expr, + result = [], + curLoop = set, + isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); + + while ( expr && set.length ) { + for ( var type in Expr.filter ) { + if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { + var found, item, + filter = Expr.filter[ type ], + left = match[1]; + + anyFound = false; + + match.splice(1,1); + + if ( left.substr( left.length - 1 ) === "\\" ) { + continue; + } + + if ( curLoop === result ) { + result = []; + } + + if ( Expr.preFilter[ type ] ) { + match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); + + if ( !match ) { + anyFound = found = true; + + } else if ( match === true ) { + continue; + } + } + + if ( match ) { + for ( var i = 0; (item = curLoop[i]) != null; i++ ) { + if ( item ) { + found = filter( item, match, i, curLoop ); + var pass = not ^ !!found; + + if ( inplace && found != null ) { + if ( pass ) { + anyFound = true; + + } else { + curLoop[i] = false; + } + + } else if ( pass ) { + result.push( item ); + anyFound = true; + } + } + } + } + + if ( found !== undefined ) { + if ( !inplace ) { + curLoop = result; + } + + expr = expr.replace( Expr.match[ type ], "" ); + + if ( !anyFound ) { + return []; + } + + break; + } + } + } + + // Improper expression + if ( expr === old ) { + if ( anyFound == null ) { + Sizzle.error( expr ); + + } else { + break; + } + } + + old = expr; + } + + return curLoop; +}; + +Sizzle.error = function( msg ) { + throw "Syntax error, unrecognized expression: " + msg; +}; + +var Expr = Sizzle.selectors = { + order: [ "ID", "NAME", "TAG" ], + + match: { + ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, + NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, + ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, + TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, + CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, + POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, + PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ + }, + + leftMatch: {}, + + attrMap: { + "class": "className", + "for": "htmlFor" + }, + + attrHandle: { + href: function( elem ) { + return elem.getAttribute( "href" ); + }, + type: function( elem ) { + return elem.getAttribute( "type" ); + } + }, + + relative: { + "+": function(checkSet, part){ + var isPartStr = typeof part === "string", + isTag = isPartStr && !rNonWord.test( part ), + isPartStrNotTag = isPartStr && !isTag; + + if ( isTag ) { + part = part.toLowerCase(); + } + + for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { + if ( (elem = checkSet[i]) ) { + while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} + + checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? + elem || false : + elem === part; + } + } + + if ( isPartStrNotTag ) { + Sizzle.filter( part, checkSet, true ); + } + }, + + ">": function( checkSet, part ) { + var elem, + isPartStr = typeof part === "string", + i = 0, + l = checkSet.length; + + if ( isPartStr && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + var parent = elem.parentNode; + checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; + } + } + + } else { + for ( ; i < l; i++ ) { + elem = checkSet[i]; + + if ( elem ) { + checkSet[i] = isPartStr ? + elem.parentNode : + elem.parentNode === part; + } + } + + if ( isPartStr ) { + Sizzle.filter( part, checkSet, true ); + } + } + }, + + "": function(checkSet, part, isXML){ + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); + }, + + "~": function( checkSet, part, isXML ) { + var nodeCheck, + doneName = done++, + checkFn = dirCheck; + + if ( typeof part === "string" && !rNonWord.test( part ) ) { + part = part.toLowerCase(); + nodeCheck = part; + checkFn = dirNodeCheck; + } + + checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); + } + }, + + find: { + ID: function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }, + + NAME: function( match, context ) { + if ( typeof context.getElementsByName !== "undefined" ) { + var ret = [], + results = context.getElementsByName( match[1] ); + + for ( var i = 0, l = results.length; i < l; i++ ) { + if ( results[i].getAttribute("name") === match[1] ) { + ret.push( results[i] ); + } + } + + return ret.length === 0 ? null : ret; + } + }, + + TAG: function( match, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( match[1] ); + } + } + }, + preFilter: { + CLASS: function( match, curLoop, inplace, result, not, isXML ) { + match = " " + match[1].replace( rBackslash, "" ) + " "; + + if ( isXML ) { + return match; + } + + for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { + if ( elem ) { + if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { + if ( !inplace ) { + result.push( elem ); + } + + } else if ( inplace ) { + curLoop[i] = false; + } + } + } + + return false; + }, + + ID: function( match ) { + return match[1].replace( rBackslash, "" ); + }, + + TAG: function( match, curLoop ) { + return match[1].replace( rBackslash, "" ).toLowerCase(); + }, + + CHILD: function( match ) { + if ( match[1] === "nth" ) { + if ( !match[2] ) { + Sizzle.error( match[0] ); + } + + match[2] = match[2].replace(/^\+|\s*/g, ''); + + // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' + var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( + match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || + !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); + + // calculate the numbers (first)n+(last) including if they are negative + match[2] = (test[1] + (test[2] || 1)) - 0; + match[3] = test[3] - 0; + } + else if ( match[2] ) { + Sizzle.error( match[0] ); + } + + // TODO: Move to normal caching system + match[0] = done++; + + return match; + }, + + ATTR: function( match, curLoop, inplace, result, not, isXML ) { + var name = match[1] = match[1].replace( rBackslash, "" ); + + if ( !isXML && Expr.attrMap[name] ) { + match[1] = Expr.attrMap[name]; + } + + // Handle if an un-quoted value was used + match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); + + if ( match[2] === "~=" ) { + match[4] = " " + match[4] + " "; + } + + return match; + }, + + PSEUDO: function( match, curLoop, inplace, result, not ) { + if ( match[1] === "not" ) { + // If we're dealing with a complex expression, or a simple one + if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { + match[3] = Sizzle(match[3], null, null, curLoop); + + } else { + var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); + + if ( !inplace ) { + result.push.apply( result, ret ); + } + + return false; + } + + } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { + return true; + } + + return match; + }, + + POS: function( match ) { + match.unshift( true ); + + return match; + } + }, + + filters: { + enabled: function( elem ) { + return elem.disabled === false && elem.type !== "hidden"; + }, + + disabled: function( elem ) { + return elem.disabled === true; + }, + + checked: function( elem ) { + return elem.checked === true; + }, + + selected: function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + parent: function( elem ) { + return !!elem.firstChild; + }, + + empty: function( elem ) { + return !elem.firstChild; + }, + + has: function( elem, i, match ) { + return !!Sizzle( match[3], elem ).length; + }, + + header: function( elem ) { + return (/h\d/i).test( elem.nodeName ); + }, + + text: function( elem ) { + var attr = elem.getAttribute( "type" ), type = elem.type; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); + }, + + radio: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; + }, + + checkbox: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; + }, + + file: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; + }, + + password: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; + }, + + submit: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "submit" === elem.type; + }, + + image: function( elem ) { + return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; + }, + + reset: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && "reset" === elem.type; + }, + + button: function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && "button" === elem.type || name === "button"; + }, + + input: function( elem ) { + return (/input|select|textarea|button/i).test( elem.nodeName ); + }, + + focus: function( elem ) { + return elem === elem.ownerDocument.activeElement; + } + }, + setFilters: { + first: function( elem, i ) { + return i === 0; + }, + + last: function( elem, i, match, array ) { + return i === array.length - 1; + }, + + even: function( elem, i ) { + return i % 2 === 0; + }, + + odd: function( elem, i ) { + return i % 2 === 1; + }, + + lt: function( elem, i, match ) { + return i < match[3] - 0; + }, + + gt: function( elem, i, match ) { + return i > match[3] - 0; + }, + + nth: function( elem, i, match ) { + return match[3] - 0 === i; + }, + + eq: function( elem, i, match ) { + return match[3] - 0 === i; + } + }, + filter: { + PSEUDO: function( elem, match, i, array ) { + var name = match[1], + filter = Expr.filters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + + } else if ( name === "contains" ) { + return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0; + + } else if ( name === "not" ) { + var not = match[3]; + + for ( var j = 0, l = not.length; j < l; j++ ) { + if ( not[j] === elem ) { + return false; + } + } + + return true; + + } else { + Sizzle.error( name ); + } + }, + + CHILD: function( elem, match ) { + var type = match[1], + node = elem; + + switch ( type ) { + case "only": + case "first": + while ( (node = node.previousSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + if ( type === "first" ) { + return true; + } + + node = elem; + + case "last": + while ( (node = node.nextSibling) ) { + if ( node.nodeType === 1 ) { + return false; + } + } + + return true; + + case "nth": + var first = match[2], + last = match[3]; + + if ( first === 1 && last === 0 ) { + return true; + } + + var doneName = match[0], + parent = elem.parentNode; + + if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) { + var count = 0; + + for ( node = parent.firstChild; node; node = node.nextSibling ) { + if ( node.nodeType === 1 ) { + node.nodeIndex = ++count; + } + } + + parent.sizcache = doneName; + } + + var diff = elem.nodeIndex - last; + + if ( first === 0 ) { + return diff === 0; + + } else { + return ( diff % first === 0 && diff / first >= 0 ); + } + } + }, + + ID: function( elem, match ) { + return elem.nodeType === 1 && elem.getAttribute("id") === match; + }, + + TAG: function( elem, match ) { + return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match; + }, + + CLASS: function( elem, match ) { + return (" " + (elem.className || elem.getAttribute("class")) + " ") + .indexOf( match ) > -1; + }, + + ATTR: function( elem, match ) { + var name = match[1], + result = Expr.attrHandle[ name ] ? + Expr.attrHandle[ name ]( elem ) : + elem[ name ] != null ? + elem[ name ] : + elem.getAttribute( name ), + value = result + "", + type = match[2], + check = match[4]; + + return result == null ? + type === "!=" : + type === "=" ? + value === check : + type === "*=" ? + value.indexOf(check) >= 0 : + type === "~=" ? + (" " + value + " ").indexOf(check) >= 0 : + !check ? + value && result !== false : + type === "!=" ? + value !== check : + type === "^=" ? + value.indexOf(check) === 0 : + type === "$=" ? + value.substr(value.length - check.length) === check : + type === "|=" ? + value === check || value.substr(0, check.length + 1) === check + "-" : + false; + }, + + POS: function( elem, match, i, array ) { + var name = match[2], + filter = Expr.setFilters[ name ]; + + if ( filter ) { + return filter( elem, i, match, array ); + } + } + } +}; + +var origPOS = Expr.match.POS, + fescape = function(all, num){ + return "\\" + (num - 0 + 1); + }; + +for ( var type in Expr.match ) { + Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); + Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); +} + +var makeArray = function( array, results ) { + array = Array.prototype.slice.call( array, 0 ); + + if ( results ) { + results.push.apply( results, array ); + return results; + } + + return array; +}; + +// Perform a simple check to determine if the browser is capable of +// converting a NodeList to an array using builtin methods. +// Also verifies that the returned array holds DOM nodes +// (which is not the case in the Blackberry browser) +try { + Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; + +// Provide a fallback method if it does not work +} catch( e ) { + makeArray = function( array, results ) { + var i = 0, + ret = results || []; + + if ( toString.call(array) === "[object Array]" ) { + Array.prototype.push.apply( ret, array ); + + } else { + if ( typeof array.length === "number" ) { + for ( var l = array.length; i < l; i++ ) { + ret.push( array[i] ); + } + + } else { + for ( ; array[i]; i++ ) { + ret.push( array[i] ); + } + } + } + + return ret; + }; +} + +var sortOrder, siblingCheck; + +if ( document.documentElement.compareDocumentPosition ) { + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { + return a.compareDocumentPosition ? -1 : 1; + } + + return a.compareDocumentPosition(b) & 4 ? -1 : 1; + }; + +} else { + sortOrder = function( a, b ) { + // The nodes are identical, we can exit early + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Fallback to using sourceIndex (in IE) if it's available on both nodes + } else if ( a.sourceIndex && b.sourceIndex ) { + return a.sourceIndex - b.sourceIndex; + } + + var al, bl, + ap = [], + bp = [], + aup = a.parentNode, + bup = b.parentNode, + cur = aup; + + // If the nodes are siblings (or identical) we can do a quick check + if ( aup === bup ) { + return siblingCheck( a, b ); + + // If no parents were found then the nodes are disconnected + } else if ( !aup ) { + return -1; + + } else if ( !bup ) { + return 1; + } + + // Otherwise they're somewhere else in the tree so we need + // to build up a full list of the parentNodes for comparison + while ( cur ) { + ap.unshift( cur ); + cur = cur.parentNode; + } + + cur = bup; + + while ( cur ) { + bp.unshift( cur ); + cur = cur.parentNode; + } + + al = ap.length; + bl = bp.length; + + // Start walking down the tree looking for a discrepancy + for ( var i = 0; i < al && i < bl; i++ ) { + if ( ap[i] !== bp[i] ) { + return siblingCheck( ap[i], bp[i] ); + } + } + + // We ended someplace up the tree so do a sibling check + return i === al ? + siblingCheck( a, bp[i], -1 ) : + siblingCheck( ap[i], b, 1 ); + }; + + siblingCheck = function( a, b, ret ) { + if ( a === b ) { + return ret; + } + + var cur = a.nextSibling; + + while ( cur ) { + if ( cur === b ) { + return -1; + } + + cur = cur.nextSibling; + } + + return 1; + }; +} + +// Utility function for retreiving the text value of an array of DOM nodes +Sizzle.getText = function( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += Sizzle.getText( elem.childNodes ); + } + } + + return ret; +}; + +// Check to see if the browser returns elements by name when +// querying by getElementById (and provide a workaround) +(function(){ + // We're going to inject a fake input element with a specified name + var form = document.createElement("div"), + id = "script" + (new Date()).getTime(), + root = document.documentElement; + + form.innerHTML = ""; + + // Inject it into the root element, check its status, and remove it quickly + root.insertBefore( form, root.firstChild ); + + // The workaround has to do additional checks after a getElementById + // Which slows things down for other browsers (hence the branching) + if ( document.getElementById( id ) ) { + Expr.find.ID = function( match, context, isXML ) { + if ( typeof context.getElementById !== "undefined" && !isXML ) { + var m = context.getElementById(match[1]); + + return m ? + m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? + [m] : + undefined : + []; + } + }; + + Expr.filter.ID = function( elem, match ) { + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); + + return elem.nodeType === 1 && node && node.nodeValue === match; + }; + } + + root.removeChild( form ); + + // release memory in IE + root = form = null; +})(); + +(function(){ + // Check to see if the browser returns only elements + // when doing getElementsByTagName("*") + + // Create a fake element + var div = document.createElement("div"); + div.appendChild( document.createComment("") ); + + // Make sure no comments are found + if ( div.getElementsByTagName("*").length > 0 ) { + Expr.find.TAG = function( match, context ) { + var results = context.getElementsByTagName( match[1] ); + + // Filter out possible comments + if ( match[1] === "*" ) { + var tmp = []; + + for ( var i = 0; results[i]; i++ ) { + if ( results[i].nodeType === 1 ) { + tmp.push( results[i] ); + } + } + + results = tmp; + } + + return results; + }; + } + + // Check to see if an attribute returns normalized href attributes + div.innerHTML = ""; + + if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && + div.firstChild.getAttribute("href") !== "#" ) { + + Expr.attrHandle.href = function( elem ) { + return elem.getAttribute( "href", 2 ); + }; + } + + // release memory in IE + div = null; +})(); + +if ( document.querySelectorAll ) { + (function(){ + var oldSizzle = Sizzle, + div = document.createElement("div"), + id = "__sizzle__"; + + div.innerHTML = "

        "; + + // Safari can't handle uppercase or unicode characters when + // in quirks mode. + if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { + return; + } + + Sizzle = function( query, context, extra, seed ) { + context = context || document; + + // Only use querySelectorAll on non-XML documents + // (ID selectors don't work in non-HTML documents) + if ( !seed && !Sizzle.isXML(context) ) { + // See if we find a selector to speed up + var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); + + if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { + // Speed-up: Sizzle("TAG") + if ( match[1] ) { + return makeArray( context.getElementsByTagName( query ), extra ); + + // Speed-up: Sizzle(".CLASS") + } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { + return makeArray( context.getElementsByClassName( match[2] ), extra ); + } + } + + if ( context.nodeType === 9 ) { + // Speed-up: Sizzle("body") + // The body element only exists once, optimize finding it + if ( query === "body" && context.body ) { + return makeArray( [ context.body ], extra ); + + // Speed-up: Sizzle("#ID") + } else if ( match && match[3] ) { + var elem = context.getElementById( match[3] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id === match[3] ) { + return makeArray( [ elem ], extra ); + } + + } else { + return makeArray( [], extra ); + } + } + + try { + return makeArray( context.querySelectorAll(query), extra ); + } catch(qsaError) {} + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + var oldContext = context, + old = context.getAttribute( "id" ), + nid = old || id, + hasParent = context.parentNode, + relativeHierarchySelector = /^\s*[+~]/.test( query ); + + if ( !old ) { + context.setAttribute( "id", nid ); + } else { + nid = nid.replace( /'/g, "\\$&" ); + } + if ( relativeHierarchySelector && hasParent ) { + context = context.parentNode; + } + + try { + if ( !relativeHierarchySelector || hasParent ) { + return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); + } + + } catch(pseudoError) { + } finally { + if ( !old ) { + oldContext.removeAttribute( "id" ); + } + } + } + } + + return oldSizzle(query, context, extra, seed); + }; + + for ( var prop in oldSizzle ) { + Sizzle[ prop ] = oldSizzle[ prop ]; + } + + // release memory in IE + div = null; + })(); +} + +(function(){ + var html = document.documentElement, + matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; + + if ( matches ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9 fails this) + var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), + pseudoWorks = false; + + try { + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( document.documentElement, "[test!='']:sizzle" ); + + } catch( pseudoError ) { + pseudoWorks = true; + } + + Sizzle.matchesSelector = function( node, expr ) { + // Make sure that attribute selectors are quoted + expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); + + if ( !Sizzle.isXML( node ) ) { + try { + if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { + var ret = matches.call( node, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || !disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9, so check for that + node.document && node.document.nodeType !== 11 ) { + return ret; + } + } + } catch(e) {} + } + + return Sizzle(expr, null, null, [node]).length > 0; + }; + } +})(); + +(function(){ + var div = document.createElement("div"); + + div.innerHTML = "
        "; + + // Opera can't find a second classname (in 9.6) + // Also, make sure that getElementsByClassName actually exists + if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { + return; + } + + // Safari caches class attributes, doesn't catch changes (in 3.2) + div.lastChild.className = "e"; + + if ( div.getElementsByClassName("e").length === 1 ) { + return; + } + + Expr.order.splice(1, 0, "CLASS"); + Expr.find.CLASS = function( match, context, isXML ) { + if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { + return context.getElementsByClassName(match[1]); + } + }; + + // release memory in IE + div = null; +})(); + +function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 && !isXML ){ + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( elem.nodeName.toLowerCase() === cur ) { + match = elem; + break; + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { + for ( var i = 0, l = checkSet.length; i < l; i++ ) { + var elem = checkSet[i]; + + if ( elem ) { + var match = false; + + elem = elem[dir]; + + while ( elem ) { + if ( elem.sizcache === doneName ) { + match = checkSet[elem.sizset]; + break; + } + + if ( elem.nodeType === 1 ) { + if ( !isXML ) { + elem.sizcache = doneName; + elem.sizset = i; + } + + if ( typeof cur !== "string" ) { + if ( elem === cur ) { + match = true; + break; + } + + } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { + match = elem; + break; + } + } + + elem = elem[dir]; + } + + checkSet[i] = match; + } + } +} + +if ( document.documentElement.contains ) { + Sizzle.contains = function( a, b ) { + return a !== b && (a.contains ? a.contains(b) : true); + }; + +} else if ( document.documentElement.compareDocumentPosition ) { + Sizzle.contains = function( a, b ) { + return !!(a.compareDocumentPosition(b) & 16); + }; + +} else { + Sizzle.contains = function() { + return false; + }; +} + +Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; + + return documentElement ? documentElement.nodeName !== "HTML" : false; +}; + +var posProcess = function( selector, context ) { + var match, + tmpSet = [], + later = "", + root = context.nodeType ? [context] : context; + + // Position selectors must be done after the filter + // And so must :not(positional) so we move all PSEUDOs to the end + while ( (match = Expr.match.PSEUDO.exec( selector )) ) { + later += match[0]; + selector = selector.replace( Expr.match.PSEUDO, "" ); + } + + selector = Expr.relative[selector] ? selector + "*" : selector; + + for ( var i = 0, l = root.length; i < l; i++ ) { + Sizzle( selector, root[i], tmpSet ); + } + + return Sizzle.filter( later, tmpSet ); +}; + +// EXPOSE +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.filters; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; + + +})(); + + +var runtil = /Until$/, + rparentsprev = /^(?:parents|prevUntil|prevAll)/, + // Note: This RegExp should be improved, or likely pulled from Sizzle + rmultiselector = /,/, + isSimple = /^.[^:#\[\.,]*$/, + slice = Array.prototype.slice, + POS = jQuery.expr.match.POS, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var self = this, + i, l; + + if ( typeof selector !== "string" ) { + return jQuery( selector ).filter(function() { + for ( i = 0, l = self.length; i < l; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }); + } + + var ret = this.pushStack( "", "find", selector ), + length, n, r; + + for ( i = 0, l = this.length; i < l; i++ ) { + length = ret.length; + jQuery.find( selector, this[i], ret ); + + if ( i > 0 ) { + // Make sure that the results are unique + for ( n = length; n < ret.length; n++ ) { + for ( r = 0; r < length; r++ ) { + if ( ret[r] === ret[n] ) { + ret.splice(n--, 1); + break; + } + } + } + } + } + + return ret; + }, + + has: function( target ) { + var targets = jQuery( target ); + return this.filter(function() { + for ( var i = 0, l = targets.length; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false), "not", selector); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true), "filter", selector ); + }, + + is: function( selector ) { + return !!selector && ( typeof selector === "string" ? + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var ret = [], i, l, cur = this[0]; + + // Array + if ( jQuery.isArray( selectors ) ) { + var match, selector, + matches = {}, + level = 1; + + if ( cur && selectors.length ) { + for ( i = 0, l = selectors.length; i < l; i++ ) { + selector = selectors[i]; + + if ( !matches[ selector ] ) { + matches[ selector ] = POS.test( selector ) ? + jQuery( selector, context || this.context ) : + selector; + } + } + + while ( cur && cur.ownerDocument && cur !== context ) { + for ( selector in matches ) { + match = matches[ selector ]; + + if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) { + ret.push({ selector: selector, elem: cur, level: level }); + } + } + + cur = cur.parentNode; + level++; + } + } + + return ret; + } + + // String + var pos = POS.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( i = 0, l = this.length; i < l; i++ ) { + cur = this[i]; + + while ( cur ) { + if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + + } else { + cur = cur.parentNode; + if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { + break; + } + } + } + } + + ret = ret.length > 1 ? jQuery.unique( ret ) : ret; + + return this.pushStack( ret, "closest", selectors ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + if ( !elem || typeof elem === "string" ) { + return jQuery.inArray( this[0], + // If it receives a string, the selector is used + // If it receives nothing, the siblings are used + elem ? jQuery( elem ) : this.parent().children() ); + } + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? + all : + jQuery.unique( all ) ); + }, + + andSelf: function() { + return this.add( this.prevObject ); + } +}); + +// A painfully simple check to see if an element is disconnected +// from a document (should be improved, where feasible). +function isDisconnected( node ) { + return !node || !node.parentNode || node.parentNode.nodeType === 11; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return jQuery.nth( elem, 2, "nextSibling" ); + }, + prev: function( elem ) { + return jQuery.nth( elem, 2, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( elem.parentNode.firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.makeArray( elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ), + // The variable 'args' was introduced in + // https://github.com/jquery/jquery/commit/52a0238 + // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed. + // http://code.google.com/p/v8/issues/detail?id=1050 + args = slice.call(arguments); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret, name, args.join(",") ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + nth: function( cur, result, dir, elem ) { + result = result || 1; + var num = 0; + + for ( ; cur; cur = cur[dir] ) { + if ( cur.nodeType === 1 && ++num === result ) { + break; + } + } + + return cur; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem, i ) { + return (elem === qualifier) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem, i ) { + return (jQuery.inArray( elem, qualifier ) >= 0) === keep; + }); +} + + + + +var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, + rtagName = /<([\w:]+)/, + rtbody = /", "" ], + legend: [ 1, "
        ", "
        " ], + thead: [ 1, "", "
        " ], + tr: [ 2, "", "
        " ], + td: [ 3, "", "
        " ], + col: [ 2, "", "
        " ], + area: [ 1, "", "" ], + _default: [ 0, "", "" ] + }; + +wrapMap.optgroup = wrapMap.option; +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// IE can't serialize and \n```\n\nFeel free to add this script to your template situation and toggle with some sort of `dev` flag.\n\n##### Using Live Reload with the Browser Extension\nInstead of adding a script tag to your page, you can live reload your page by installing a browser extension. Please visit [how do I install and use the browser extensions](http://feedback.livereload.com/knowledgebase/articles/86242-how-do-i-install-and-use-the-browser-extensions-) for help installing an extension for your browser.\n\nOnce installed please use the default live reload port `35729` and the browser extension will automatically reload your page without needing the `