조인천

ver3

Showing 121 changed files with 9299 additions and 3 deletions
1 var request = require('request'); 1 var request = require('request');
2 2
3 var optionParams = { 3 var optionParams = {
4 - q:"kakao", 4 + q:"저라뎃",
5 part:"snippet", 5 part:"snippet",
6 key:"AIzaSyCgGa6aM7taXs4bajtYukbc_EQAKTLVTNc", 6 key:"AIzaSyCgGa6aM7taXs4bajtYukbc_EQAKTLVTNc",
7 - maxResult2:5 7 + type:"video",
8 + maxResult2:5,
9 + regionCode:"KR",
10 + videoDuration:"short"
8 }; 11 };
12 +optionParams.q = encodeURI(optionParams.q);
13 +
9 var url = "https://www.googleapis.com/youtube/v3/search?"; 14 var url = "https://www.googleapis.com/youtube/v3/search?";
10 for (var option in optionParams) 15 for (var option in optionParams)
11 { 16 {
...@@ -14,6 +19,33 @@ for (var option in optionParams) ...@@ -14,6 +19,33 @@ for (var option in optionParams)
14 19
15 url = url.substr(0,url.length-1); 20 url = url.substr(0,url.length-1);
16 21
22 +var VideoIds = new Array();
23 +var idx = 0;
17 request(url, function(err,res,body){ 24 request(url, function(err,res,body){
18 - console.log(body) 25 + //console.log(body)
26 + var data = JSON.parse(body).items;
27 +
28 + for(var content in data)
29 + {
30 + VideoIds[idx]=(data[content].id.videoId);
31 + idx++;
32 + }
33 + console.log(VideoIds.length);
34 + console.log(VideoIds[0]);
35 + console.log(typeof(VideoIds[1]));
36 +
37 + //다운로드 부분
38 + var fs = require('fs');
39 + var youtubedl = require('youtube-dl');
40 + var video = youtubedl('http://www.youtube.com/watch?v='.concat(VideoIds[1]));
41 +
42 + video.on('info',function(info)
43 + {
44 + console.log('Download started');
45 + console.log('filename : '+ info.filename);
46 + console.log('size : '+info.size);
47 + });
48 +
49 + video.pipe(fs.createWriteStream('justlikethat.mp4'));
19 }); 50 });
51 +
......
This file is too large to display.
This file is too large to display.
This file is too large to display.
This file is too large to display.
1 +#!/bin/sh
2 +basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3 +
4 +case `uname` in
5 + *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
6 +esac
7 +
8 +if [ -x "$basedir/node" ]; then
9 + "$basedir/node" "$basedir/../mkdirp/bin/cmd.js" "$@"
10 + ret=$?
11 +else
12 + node "$basedir/../mkdirp/bin/cmd.js" "$@"
13 + ret=$?
14 +fi
15 +exit $ret
1 +@IF EXIST "%~dp0\node.exe" (
2 + "%~dp0\node.exe" "%~dp0\..\mkdirp\bin\cmd.js" %*
3 +) ELSE (
4 + @SETLOCAL
5 + @SET PATHEXT=%PATHEXT:;.JS;=;%
6 + node "%~dp0\..\mkdirp\bin\cmd.js" %*
7 +)
...\ No newline at end of file ...\ No newline at end of file
1 +<a name="2.0.0"></a>
2 +# 2.0.0 (2019-05-22)
3 +
4 +* build: be possible setup downloader for windows ([8111957](https://github.com/przemyslawpluta/node-youtube-dl/commit/8111957))
5 +* build: improve workflow ([5ce37dd](https://github.com/przemyslawpluta/node-youtube-dl/commit/5ce37dd))
6 +* build: improve workflow ([9ff909e](https://github.com/przemyslawpluta/node-youtube-dl/commit/9ff909e))
7 +* build: setup node version ([41f0a80](https://github.com/przemyslawpluta/node-youtube-dl/commit/41f0a80))
8 +* build: setup properly release message ([8f7a11b](https://github.com/przemyslawpluta/node-youtube-dl/commit/8f7a11b))
9 +* build: take end on consideration ([66e1324](https://github.com/przemyslawpluta/node-youtube-dl/commit/66e1324))
10 +* refactor: remove dead code ([1a74f06](https://github.com/przemyslawpluta/node-youtube-dl/commit/1a74f06))
11 +
12 +
13 +
14 +<a name="1.13.5"></a>
15 +## 1.13.5 (2019-05-22)
16 +
17 +* Fix non-json outputs ([cfff104](https://github.com/przemyslawpluta/node-youtube-dl/commit/cfff104))
18 +* Fix typo in comments ([e968072](https://github.com/przemyslawpluta/node-youtube-dl/commit/e968072))
19 +* New has() method that replaces arr.indexOf where applicable ([5ec1f87](https://github.com/przemyslawpluta/node-youtube-dl/commit/5ec1f87))
20 +* Removed package-lock.json ([56cbc63](https://github.com/przemyslawpluta/node-youtube-dl/commit/56cbc63))
21 +* Replace typeof === "string" with util.isString globally ([e3f4a9d](https://github.com/przemyslawpluta/node-youtube-dl/commit/e3f4a9d))
22 +* Fix: Checking if we have args before testing them ([113ed2a](https://github.com/przemyslawpluta/node-youtube-dl/commit/113ed2a))
23 +
24 +
25 +
26 +<a name="1.13.4"></a>
27 +## 1.13.4 (2019-05-18)
28 +
29 +* ci: update builds ([3977c65](https://github.com/przemyslawpluta/node-youtube-dl/commit/3977c65))
30 +* Update youtube-dl.js ([bfc0a1d](https://github.com/przemyslawpluta/node-youtube-dl/commit/bfc0a1d))
31 +
32 +
33 +
34 +<a name="1.13.3"></a>
35 +## 1.13.3 (2019-05-16)
36 +
37 +* test: update ([fd31af8](https://github.com/przemyslawpluta/node-youtube-dl/commit/fd31af8))
38 +* fix: fix a regression caused by previous refactorings ([dfed31a](https://github.com/przemyslawpluta/node-youtube-dl/commit/dfed31a)), closes [#230](https://github.com/przemyslawpluta/node-youtube-dl/issues/230)
39 +* Enable option to select subtitle formats ([4bc1caa](https://github.com/przemyslawpluta/node-youtube-dl/commit/4bc1caa))
40 +
41 +
42 +
43 +<a name="1.13.2"></a>
44 +## 1.13.2 (2019-03-29)
45 +
46 +* Send header because gets 403 if cookie is needed ([91f3f69](https://github.com/przemyslawpluta/node-youtube-dl/commit/91f3f69))
47 +
48 +
49 +
50 +<a name="1.13.1"></a>
51 +## 1.13.1 (2019-02-04)
52 +
53 +* Fixed typo & removed redundant line ([156bbd5](https://github.com/przemyslawpluta/node-youtube-dl/commit/156bbd5))
54 +
55 +
56 +
57 +<a name="1.13.0"></a>
58 +# 1.13.0 (2019-01-25)
59 +
60 +* build: add release process ([8cc1b05](https://github.com/przemyslawpluta/node-youtube-dl/commit/8cc1b05))
61 +* test: update snapshots ([65fb75e](https://github.com/przemyslawpluta/node-youtube-dl/commit/65fb75e))
62 +* add editorconfig ([8a92f0b](https://github.com/przemyslawpluta/node-youtube-dl/commit/8a92f0b))
63 +* add hms to duration, twitch test ([9ea3ff1](https://github.com/przemyslawpluta/node-youtube-dl/commit/9ea3ff1))
64 +* add sensible `execFile` good defaults ([2524d75](https://github.com/przemyslawpluta/node-youtube-dl/commit/2524d75)), closes [#173](https://github.com/przemyslawpluta/node-youtube-dl/issues/173)
65 +* Adding dashes before the video ID ([da8f4dd](https://github.com/przemyslawpluta/node-youtube-dl/commit/da8f4dd))
66 +* changed to _filename in line 33 readme ([87d3891](https://github.com/przemyslawpluta/node-youtube-dl/commit/87d3891))
67 +* Consider copyright videos as not available in order to continue on error ([e19d8d1](https://github.com/przemyslawpluta/node-youtube-dl/commit/e19d8d1))
68 +* Consider not made available videos as not available in order to continue on error ([ae7ea3b](https://github.com/przemyslawpluta/node-youtube-dl/commit/ae7ea3b))
69 +* Correct extension in playlist.js ([5d77436](https://github.com/przemyslawpluta/node-youtube-dl/commit/5d77436))
70 +* Correct test with correct video info ([0ee2609](https://github.com/przemyslawpluta/node-youtube-dl/commit/0ee2609))
71 +* Disable non-functional test ([ca1aa42](https://github.com/przemyslawpluta/node-youtube-dl/commit/ca1aa42))
72 +* download best and combine is ffmpeg available ([2193220](https://github.com/przemyslawpluta/node-youtube-dl/commit/2193220))
73 +* Download correct binary for windows systems ([3874a88](https://github.com/przemyslawpluta/node-youtube-dl/commit/3874a88))
74 +* drop tests for 4,5 and version bump ([3634c67](https://github.com/przemyslawpluta/node-youtube-dl/commit/3634c67))
75 +* Fix encoding issue on windows ([d65114d](https://github.com/przemyslawpluta/node-youtube-dl/commit/d65114d))
76 +* Get and set path from youtube-dl ([161ed2a](https://github.com/przemyslawpluta/node-youtube-dl/commit/161ed2a))
77 +* handle thumbnails download ([a0832dc](https://github.com/przemyslawpluta/node-youtube-dl/commit/a0832dc))
78 +* hms and raw duration ([eb0e9de](https://github.com/przemyslawpluta/node-youtube-dl/commit/eb0e9de))
79 +* meta tweaks ([f685ad7](https://github.com/przemyslawpluta/node-youtube-dl/commit/f685ad7))
80 +* minor typo ([429b1f7](https://github.com/przemyslawpluta/node-youtube-dl/commit/429b1f7))
81 +* missing ; ([05f8f62](https://github.com/przemyslawpluta/node-youtube-dl/commit/05f8f62))
82 +* remove dead code ([4b1ba39](https://github.com/przemyslawpluta/node-youtube-dl/commit/4b1ba39))
83 +* remove deprecated badge ([19a7b33](https://github.com/przemyslawpluta/node-youtube-dl/commit/19a7b33))
84 +* remove lock ([0131daf](https://github.com/przemyslawpluta/node-youtube-dl/commit/0131daf))
85 +* Remove size from download test, not relevant ([e22ee14](https://github.com/przemyslawpluta/node-youtube-dl/commit/e22ee14))
86 +* remove vimeo tests ([1f717cc](https://github.com/przemyslawpluta/node-youtube-dl/commit/1f717cc))
87 +* update dependencies ([bf28967](https://github.com/przemyslawpluta/node-youtube-dl/commit/bf28967))
88 +* update snapshot ([70ec50a](https://github.com/przemyslawpluta/node-youtube-dl/commit/70ec50a))
89 +* Update test about twitch (twitch id are not anymore the video title) ([b9f0317](https://github.com/przemyslawpluta/node-youtube-dl/commit/b9f0317))
90 +* update travis builds ([efe313c](https://github.com/przemyslawpluta/node-youtube-dl/commit/efe313c))
91 +* Updated test case since video title changed on twitch's end ([7c22361](https://github.com/przemyslawpluta/node-youtube-dl/commit/7c22361))
92 +* use const over var ([6ed5a1c](https://github.com/przemyslawpluta/node-youtube-dl/commit/6ed5a1c))
93 +
94 +
95 +
96 +<a name="1.12.1"></a>
97 +## 1.12.1 (2017-09-28)
98 +
99 +* cleanup ([68ea1df](https://github.com/przemyslawpluta/node-youtube-dl/commit/68ea1df))
100 +* cleanup ([5efbce3](https://github.com/przemyslawpluta/node-youtube-dl/commit/5efbce3))
101 +* concat args ([25ed267](https://github.com/przemyslawpluta/node-youtube-dl/commit/25ed267))
102 +* correct repo url ([88ec7c8](https://github.com/przemyslawpluta/node-youtube-dl/commit/88ec7c8))
103 +* Document how to increase buffer size ([3bb3e4d](https://github.com/przemyslawpluta/node-youtube-dl/commit/3bb3e4d))
104 +* drop getFormats, update vimeo test ([da47d4d](https://github.com/przemyslawpluta/node-youtube-dl/commit/da47d4d))
105 +* drop io.js tests ([b1fa4fb](https://github.com/przemyslawpluta/node-youtube-dl/commit/b1fa4fb))
106 +* drop soundcloud due to ssl error on travis ([0c7168d](https://github.com/przemyslawpluta/node-youtube-dl/commit/0c7168d))
107 +* drop tests for 0.10 ([473cdf6](https://github.com/przemyslawpluta/node-youtube-dl/commit/473cdf6))
108 +* fix ([a6d6d36](https://github.com/przemyslawpluta/node-youtube-dl/commit/a6d6d36))
109 +* Fix issue with duration not formatting correctly ([d9dd0ec](https://github.com/przemyslawpluta/node-youtube-dl/commit/d9dd0ec))
110 +* fix package name ([5642547](https://github.com/przemyslawpluta/node-youtube-dl/commit/5642547))
111 +* fix tests, update formatting ([796f922](https://github.com/przemyslawpluta/node-youtube-dl/commit/796f922))
112 +* fixed downloader if user passed in a custom bin dir ([2954eed](https://github.com/przemyslawpluta/node-youtube-dl/commit/2954eed))
113 +* Fixed tests assertion, video sizes changed probably due to change in streaming technology and title ([d2f7894](https://github.com/przemyslawpluta/node-youtube-dl/commit/d2f7894))
114 +* hotfix for the electron issue ([ae7608c](https://github.com/przemyslawpluta/node-youtube-dl/commit/ae7608c))
115 +* Make properties configurable ([dab402b](https://github.com/przemyslawpluta/node-youtube-dl/commit/dab402b))
116 +* manage missing video array plus tests ([6f2840e](https://github.com/przemyslawpluta/node-youtube-dl/commit/6f2840e))
117 +* py + node test ([cf2d5e1](https://github.com/przemyslawpluta/node-youtube-dl/commit/cf2d5e1))
118 +* python test ([e6b597a](https://github.com/przemyslawpluta/node-youtube-dl/commit/e6b597a))
119 +* Quickfix for Copy Error in Usage Example ([db27e8a](https://github.com/przemyslawpluta/node-youtube-dl/commit/db27e8a))
120 +* skip error is video has been removed by the user ([5e94b13](https://github.com/przemyslawpluta/node-youtube-dl/commit/5e94b13))
121 +* skip error is video has been removed by the user ([956056b](https://github.com/przemyslawpluta/node-youtube-dl/commit/956056b))
122 +* ssl err test ([0738a25](https://github.com/przemyslawpluta/node-youtube-dl/commit/0738a25))
123 +* test ([80d924a](https://github.com/przemyslawpluta/node-youtube-dl/commit/80d924a))
124 +* travis ssl force ([6b0f0f8](https://github.com/przemyslawpluta/node-youtube-dl/commit/6b0f0f8))
125 +* update audio.js ([17c3fb1](https://github.com/przemyslawpluta/node-youtube-dl/commit/17c3fb1))
126 +* update build status ([1aa9d82](https://github.com/przemyslawpluta/node-youtube-dl/commit/1aa9d82))
127 +* update details ([653f411](https://github.com/przemyslawpluta/node-youtube-dl/commit/653f411))
128 +* update icons ([0399db6](https://github.com/przemyslawpluta/node-youtube-dl/commit/0399db6))
129 +* update mode ([e83b336](https://github.com/przemyslawpluta/node-youtube-dl/commit/e83b336))
130 +* update package ([2867fc5](https://github.com/przemyslawpluta/node-youtube-dl/commit/2867fc5))
131 +* Update README.md ([76cb708](https://github.com/przemyslawpluta/node-youtube-dl/commit/76cb708))
132 +* update tests ([d745285](https://github.com/przemyslawpluta/node-youtube-dl/commit/d745285))
133 +* update travis env ([08fd355](https://github.com/przemyslawpluta/node-youtube-dl/commit/08fd355))
134 +* update travis-ci ([339460b](https://github.com/przemyslawpluta/node-youtube-dl/commit/339460b))
135 +* update youtube-dl permissions ([621b478](https://github.com/przemyslawpluta/node-youtube-dl/commit/621b478))
136 +* updates & fixes ([8bc4839](https://github.com/przemyslawpluta/node-youtube-dl/commit/8bc4839))
137 +* version bump ([a839a5f](https://github.com/przemyslawpluta/node-youtube-dl/commit/a839a5f))
138 +
139 +
140 +
141 +<a name="1.11.1"></a>
142 +## 1.11.1 (2016-04-06)
143 +
144 +* add heroku support ([541e710](https://github.com/przemyslawpluta/node-youtube-dl/commit/541e710))
145 +* version bump ([22abe25](https://github.com/przemyslawpluta/node-youtube-dl/commit/22abe25))
146 +
147 +
148 +
149 +<a name="1.11.0"></a>
150 +# 1.11.0 (2016-03-25)
151 +
152 +* add getFormats example ([d9b2925](https://github.com/przemyslawpluta/node-youtube-dl/commit/d9b2925))
153 +* add node 4 & 5 for testing ([8683ac1](https://github.com/przemyslawpluta/node-youtube-dl/commit/8683ac1))
154 +* adding ability to continue partially downloaded files. ([e9e540a](https://github.com/przemyslawpluta/node-youtube-dl/commit/e9e540a))
155 +* allow for external bin but keep details internally ([f35daab](https://github.com/przemyslawpluta/node-youtube-dl/commit/f35daab))
156 +* As requested, I was trying to make the code as readable as possible ([38884d1](https://github.com/przemyslawpluta/node-youtube-dl/commit/38884d1))
157 +* callback err ([f49128c](https://github.com/przemyslawpluta/node-youtube-dl/commit/f49128c))
158 +* change bin permissions ([957172b](https://github.com/przemyslawpluta/node-youtube-dl/commit/957172b))
159 +* check for datadir existence ([1817160](https://github.com/przemyslawpluta/node-youtube-dl/commit/1817160))
160 +* choose bin location ([1123d33](https://github.com/przemyslawpluta/node-youtube-dl/commit/1123d33))
161 +* cleanup ([12eb585](https://github.com/przemyslawpluta/node-youtube-dl/commit/12eb585))
162 +* cleanup ([1a8b2f0](https://github.com/przemyslawpluta/node-youtube-dl/commit/1a8b2f0))
163 +* cleanup .gitignore ([bf5b974](https://github.com/przemyslawpluta/node-youtube-dl/commit/bf5b974))
164 +* dependencies bump ([f131dca](https://github.com/przemyslawpluta/node-youtube-dl/commit/f131dca))
165 +* document `ytdl.exec()` with audio example ([2b8333f](https://github.com/przemyslawpluta/node-youtube-dl/commit/2b8333f))
166 +* extract downloader ([f27c45a](https://github.com/przemyslawpluta/node-youtube-dl/commit/f27c45a))
167 +* fix bin path ([6f9ef39](https://github.com/przemyslawpluta/node-youtube-dl/commit/6f9ef39))
168 +* fix license meta in pacakge.json ([3d2f168](https://github.com/przemyslawpluta/node-youtube-dl/commit/3d2f168))
169 +* fix resolution or audio ([d2a3269](https://github.com/przemyslawpluta/node-youtube-dl/commit/d2a3269))
170 +* handle playlists ([acb1571](https://github.com/przemyslawpluta/node-youtube-dl/commit/acb1571))
171 +* install module before download ([f3e0ac7](https://github.com/przemyslawpluta/node-youtube-dl/commit/f3e0ac7))
172 +* missing dependency ([f56cb24](https://github.com/przemyslawpluta/node-youtube-dl/commit/f56cb24))
173 +* move bin path to datadir ([7ef58ef](https://github.com/przemyslawpluta/node-youtube-dl/commit/7ef58ef))
174 +* no longer maintaining ([1aa9076](https://github.com/przemyslawpluta/node-youtube-dl/commit/1aa9076))
175 +* package postinstall ([c1f052f](https://github.com/przemyslawpluta/node-youtube-dl/commit/c1f052f))
176 +* permission change on bin ([c061caa](https://github.com/przemyslawpluta/node-youtube-dl/commit/c061caa))
177 +* permission change on bin cleanup test ([6912150](https://github.com/przemyslawpluta/node-youtube-dl/commit/6912150))
178 +* preventing options being created if it doesn't exist ([894e215](https://github.com/przemyslawpluta/node-youtube-dl/commit/894e215))
179 +* remove unused module ([6fc3f02](https://github.com/przemyslawpluta/node-youtube-dl/commit/6fc3f02))
180 +* resolve to .exe on win ([2c5467e](https://github.com/przemyslawpluta/node-youtube-dl/commit/2c5467e))
181 +* skip over not available videos during playlist download ([45ee26b](https://github.com/przemyslawpluta/node-youtube-dl/commit/45ee26b))
182 +* store example videos in dir to keep things cleaner ([e7cc0d5](https://github.com/przemyslawpluta/node-youtube-dl/commit/e7cc0d5))
183 +* update ([4da180b](https://github.com/przemyslawpluta/node-youtube-dl/commit/4da180b))
184 +* update ([60a0cf4](https://github.com/przemyslawpluta/node-youtube-dl/commit/60a0cf4))
185 +* update path ([b9992cf](https://github.com/przemyslawpluta/node-youtube-dl/commit/b9992cf))
186 +* update readme ([c159427](https://github.com/przemyslawpluta/node-youtube-dl/commit/c159427))
187 +* update readme ([a41b965](https://github.com/przemyslawpluta/node-youtube-dl/commit/a41b965))
188 +* update README ([1565229](https://github.com/przemyslawpluta/node-youtube-dl/commit/1565229))
189 +* update tests ([7be149d](https://github.com/przemyslawpluta/node-youtube-dl/commit/7be149d))
190 +* Updating comment block for inline quotes, replacing double quotes with single quotes ([1646cec](https://github.com/przemyslawpluta/node-youtube-dl/commit/1646cec))
191 +
192 +
193 +
194 +<a name="1.10.5"></a>
195 +## 1.10.5 (2015-05-07)
196 +
197 +* 1.10.5 ([d2d4eba](https://github.com/przemyslawpluta/node-youtube-dl/commit/d2d4eba))
198 +* better check for `--format` ([dbaebb3](https://github.com/przemyslawpluta/node-youtube-dl/commit/dbaebb3))
199 +
200 +
201 +
202 +<a name="1.10.4"></a>
203 +## 1.10.4 (2015-05-07)
204 +
205 +* 1.10.4 ([06ec68e](https://github.com/przemyslawpluta/node-youtube-dl/commit/06ec68e))
206 +* check for `--format` too ([08ca167](https://github.com/przemyslawpluta/node-youtube-dl/commit/08ca167))
207 +* Specify download format 'best' if none supplied ([edee4d3](https://github.com/przemyslawpluta/node-youtube-dl/commit/edee4d3))
208 +* update examples ([023a502](https://github.com/przemyslawpluta/node-youtube-dl/commit/023a502))
209 +* update tests ([a85779d](https://github.com/przemyslawpluta/node-youtube-dl/commit/a85779d))
210 +
211 +
212 +
213 +<a name="1.10.3"></a>
214 +## 1.10.3 (2015-04-19)
215 +
216 +* 1.10.3 ([a70895e](https://github.com/przemyslawpluta/node-youtube-dl/commit/a70895e))
217 +* Fix the broken Host HTTP Header for Dailymotion && Fix Test ([9657b8c](https://github.com/przemyslawpluta/node-youtube-dl/commit/9657b8c))
218 +
219 +
220 +
221 +<a name="1.10.2"></a>
222 +## 1.10.2 (2015-03-24)
223 +
224 +* 1.10.2 ([484d1c3](https://github.com/przemyslawpluta/node-youtube-dl/commit/484d1c3))
225 +* a bit of docs ([c3c1b4b](https://github.com/przemyslawpluta/node-youtube-dl/commit/c3c1b4b))
226 +* print warning when getting warnings from stderr ([26bd213](https://github.com/przemyslawpluta/node-youtube-dl/commit/26bd213))
227 +
228 +
229 +
230 +<a name="1.10.1"></a>
231 +## 1.10.1 (2015-02-26)
232 +
233 +* 1.10.1 ([498e288](https://github.com/przemyslawpluta/node-youtube-dl/commit/498e288))
234 +* add io.js and 0.12 to test matrix ([17ce70b](https://github.com/przemyslawpluta/node-youtube-dl/commit/17ce70b))
235 +* call binary with python instead of directly, fixes #66 ([833d281](https://github.com/przemyslawpluta/node-youtube-dl/commit/833d281)), closes [#66](https://github.com/przemyslawpluta/node-youtube-dl/issues/66)
236 +* dont test on node v0.8 ([5c1c182](https://github.com/przemyslawpluta/node-youtube-dl/commit/5c1c182))
237 +* quote iojs ([47d1485](https://github.com/przemyslawpluta/node-youtube-dl/commit/47d1485))
238 +* update packages ([413cf53](https://github.com/przemyslawpluta/node-youtube-dl/commit/413cf53))
239 +* use container based environment ([4947618](https://github.com/przemyslawpluta/node-youtube-dl/commit/4947618))
240 +
241 +
242 +
243 +<a name="1.10.0"></a>
244 +# 1.10.0 (2015-02-19)
245 +
246 +* 1.10.0 ([d3018e5](https://github.com/przemyslawpluta/node-youtube-dl/commit/d3018e5))
247 +* Multiple URL support (array param) for getInfo() ([1afab0b](https://github.com/przemyslawpluta/node-youtube-dl/commit/1afab0b))
248 +
249 +
250 +
251 +<a name="1.9.0"></a>
252 +# 1.9.0 (2015-02-13)
253 +
254 +* 1.9.0 ([e3be488](https://github.com/przemyslawpluta/node-youtube-dl/commit/e3be488))
255 +* add warnings for using deprecated fields ([d2c53ae](https://github.com/przemyslawpluta/node-youtube-dl/commit/d2c53ae))
256 +* Call getInfo from getFormats ([4ecda89](https://github.com/przemyslawpluta/node-youtube-dl/commit/4ecda89))
257 +* document how to keep youtube-dl binary up to date. fixes #61 ([a8eface](https://github.com/przemyslawpluta/node-youtube-dl/commit/a8eface)), closes [#61](https://github.com/przemyslawpluta/node-youtube-dl/issues/61)
258 +* dont check each individual format object ([50c113f](https://github.com/przemyslawpluta/node-youtube-dl/commit/50c113f))
259 +* fix getting playlist info ([cdb37fe](https://github.com/przemyslawpluta/node-youtube-dl/commit/cdb37fe))
260 +* Move formatDuration to util.js ([c309c24](https://github.com/przemyslawpluta/node-youtube-dl/commit/c309c24))
261 +* remove unused old functions ([e4689a6](https://github.com/przemyslawpluta/node-youtube-dl/commit/e4689a6))
262 +* Return the full info provided by youtube-dl ([ace1b11](https://github.com/przemyslawpluta/node-youtube-dl/commit/ace1b11))
263 +* Use the '--dump-json' option for extracting the video information ([b3a9fcd](https://github.com/przemyslawpluta/node-youtube-dl/commit/b3a9fcd))
264 +* Use the '--dump-json' option for getFormats ([e93a8b9](https://github.com/przemyslawpluta/node-youtube-dl/commit/e93a8b9))
265 +
266 +
267 +
268 +<a name="1.8.0"></a>
269 +# 1.8.0 (2015-01-15)
270 +
271 +* 1.8.0 ([ab8b3df](https://github.com/przemyslawpluta/node-youtube-dl/commit/ab8b3df))
272 +* Added extractor API incl. tests and example code ([d2b3983](https://github.com/przemyslawpluta/node-youtube-dl/commit/d2b3983))
273 +* dont download video when downloading subtitles ([3cfa382](https://github.com/przemyslawpluta/node-youtube-dl/commit/3cfa382))
274 +* put try/catch around unlinking subtitle file ([a3f5202](https://github.com/przemyslawpluta/node-youtube-dl/commit/a3f5202))
275 +
276 +
277 +
278 +<a name="1.7.0"></a>
279 +# 1.7.0 (2015-01-08)
280 +
281 +* 1.7.0 ([777619e](https://github.com/przemyslawpluta/node-youtube-dl/commit/777619e))
282 +* added more cli args to ignore ([8edbd1e](https://github.com/przemyslawpluta/node-youtube-dl/commit/8edbd1e))
283 +* get duration. fixes #53 ([fd7d7c9](https://github.com/przemyslawpluta/node-youtube-dl/commit/fd7d7c9)), closes [#53](https://github.com/przemyslawpluta/node-youtube-dl/issues/53)
284 +* make `args` passed to youtube-dl actually optional ([413d0ab](https://github.com/przemyslawpluta/node-youtube-dl/commit/413d0ab))
285 +
286 +
287 +
288 +<a name="1.6.0"></a>
289 +# 1.6.0 (2014-11-23)
290 +
291 +* 1.6.0 ([8d548eb](https://github.com/przemyslawpluta/node-youtube-dl/commit/8d548eb))
292 +* add `getSubs()` function. fixes #48 ([6cb55af](https://github.com/przemyslawpluta/node-youtube-dl/commit/6cb55af)), closes [#48](https://github.com/przemyslawpluta/node-youtube-dl/issues/48)
293 +* better resolution detection ([cff5763](https://github.com/przemyslawpluta/node-youtube-dl/commit/cff5763))
294 +* check size is defined ([0e67ef1](https://github.com/przemyslawpluta/node-youtube-dl/commit/0e67ef1))
295 +* linting ([916e8da](https://github.com/przemyslawpluta/node-youtube-dl/commit/916e8da))
296 +* linting ([1f5e319](https://github.com/przemyslawpluta/node-youtube-dl/commit/1f5e319))
297 +* update formats returned ([d545f10](https://github.com/przemyslawpluta/node-youtube-dl/commit/d545f10))
298 +* updated getFormats regex to handle unknown & ?x formats ([7e33ace](https://github.com/przemyslawpluta/node-youtube-dl/commit/7e33ace))
299 +
300 +
301 +
302 +<a name="1.5.16"></a>
303 +## 1.5.16 (2014-10-24)
304 +
305 +* 1.5.16 ([4acfca7](https://github.com/przemyslawpluta/node-youtube-dl/commit/4acfca7))
306 +* filter out from correct args if no subs ([97346fe](https://github.com/przemyslawpluta/node-youtube-dl/commit/97346fe))
307 +* handle new warning style ([3ae2964](https://github.com/przemyslawpluta/node-youtube-dl/commit/3ae2964))
308 +* update test formats ([24f00e5](https://github.com/przemyslawpluta/node-youtube-dl/commit/24f00e5))
309 +
310 +
311 +
312 +<a name="1.5.15"></a>
313 +## 1.5.15 (2014-09-25)
314 +
315 +* 1.5.15 ([f315043](https://github.com/przemyslawpluta/node-youtube-dl/commit/f315043))
316 +* fix ([5d07020](https://github.com/przemyslawpluta/node-youtube-dl/commit/5d07020))
317 +
318 +
319 +
320 +<a name="1.5.14"></a>
321 +## 1.5.14 (2014-09-24)
322 +
323 +* 1.5.14 ([c7d7c08](https://github.com/przemyslawpluta/node-youtube-dl/commit/c7d7c08))
324 +* expose call function with empty default args as exec ([e12b538](https://github.com/przemyslawpluta/node-youtube-dl/commit/e12b538))
325 +* ignore any errors after successful download. fixes #43 ([58558d8](https://github.com/przemyslawpluta/node-youtube-dl/commit/58558d8)), closes [#43](https://github.com/przemyslawpluta/node-youtube-dl/issues/43)
326 +
327 +
328 +
329 +<a name="1.5.13"></a>
330 +## 1.5.13 (2014-09-07)
331 +
332 +* 1.5.13 ([e72b27d](https://github.com/przemyslawpluta/node-youtube-dl/commit/e72b27d))
333 +* fix for missing env variable in win ([4115b5e](https://github.com/przemyslawpluta/node-youtube-dl/commit/4115b5e))
334 +
335 +
336 +
337 +<a name="1.5.12"></a>
338 +## 1.5.12 (2014-09-04)
339 +
340 +* 1.5.12 ([8a8c681](https://github.com/przemyslawpluta/node-youtube-dl/commit/8a8c681))
341 +* fix youtube id filtering ([3cb82a9](https://github.com/przemyslawpluta/node-youtube-dl/commit/3cb82a9))
342 +
343 +
344 +
345 +<a name="1.5.11"></a>
346 +## 1.5.11 (2014-08-24)
347 +
348 +* 1.5.11 ([09d2951](https://github.com/przemyslawpluta/node-youtube-dl/commit/09d2951))
349 +* support non-youtube (speificially vimeo) videos. fixes #39 ([cd6938b](https://github.com/przemyslawpluta/node-youtube-dl/commit/cd6938b)), closes [#39](https://github.com/przemyslawpluta/node-youtube-dl/issues/39)
350 +
351 +
352 +
353 +<a name="1.5.10"></a>
354 +## 1.5.10 (2014-08-05)
355 +
356 +* 1.5.10 ([f9c0c8f](https://github.com/przemyslawpluta/node-youtube-dl/commit/f9c0c8f))
357 +* fix not passing options ([02fa0df](https://github.com/przemyslawpluta/node-youtube-dl/commit/02fa0df))
358 +
359 +
360 +
361 +<a name="1.5.9"></a>
362 +## 1.5.9 (2014-08-02)
363 +
364 +* 1.5.9 ([303fb12](https://github.com/przemyslawpluta/node-youtube-dl/commit/303fb12))
365 +* Add more entries to badArgs ([a6821b5](https://github.com/przemyslawpluta/node-youtube-dl/commit/a6821b5))
366 +* fix for failed download with no subtitles ([36fd75a](https://github.com/przemyslawpluta/node-youtube-dl/commit/36fd75a))
367 +* fix for failed download with no subtitles when requested ([69166bf](https://github.com/przemyslawpluta/node-youtube-dl/commit/69166bf))
368 +* fix for failed download with no subtitles when requested ([aeab2dd](https://github.com/przemyslawpluta/node-youtube-dl/commit/aeab2dd))
369 +* fix for failed download with no subtitles when requested ([038b1fd](https://github.com/przemyslawpluta/node-youtube-dl/commit/038b1fd))
370 +* fix for failed download with no subtitles when requested ([19c13af](https://github.com/przemyslawpluta/node-youtube-dl/commit/19c13af))
371 +* fix for failed download with no subtitles when requested ([82a48a4](https://github.com/przemyslawpluta/node-youtube-dl/commit/82a48a4))
372 +* only notify on build changes ([3cf3363](https://github.com/przemyslawpluta/node-youtube-dl/commit/3cf3363))
373 +* update request to v2.37.0 ([11757f3](https://github.com/przemyslawpluta/node-youtube-dl/commit/11757f3))
374 +
375 +
376 +
377 +<a name="1.5.8"></a>
378 +## 1.5.8 (2014-07-04)
379 +
380 +* Fix ReferenceError: onerror is not defined ([acb3512](https://github.com/przemyslawpluta/node-youtube-dl/commit/acb3512))
381 +* Fix var name: from er to err ([21bdbee](https://github.com/przemyslawpluta/node-youtube-dl/commit/21bdbee))
382 +* update request ([f97f90b](https://github.com/przemyslawpluta/node-youtube-dl/commit/f97f90b))
383 +* v1.5.7 ([f19215a](https://github.com/przemyslawpluta/node-youtube-dl/commit/f19215a))
384 +* v1.5.8 ([96083ba](https://github.com/przemyslawpluta/node-youtube-dl/commit/96083ba))
385 +
386 +
387 +
388 +<a name="1.5.6"></a>
389 +## 1.5.6 (2014-06-14)
390 +
391 +* comment consistency ([7acea1e](https://github.com/przemyslawpluta/node-youtube-dl/commit/7acea1e))
392 +* fix parsing resolutions ([ac48c37](https://github.com/przemyslawpluta/node-youtube-dl/commit/ac48c37))
393 +* fix when not giving `args` to `getInfo()` ([794617d](https://github.com/przemyslawpluta/node-youtube-dl/commit/794617d))
394 +* v1.5.6 ([80999a5](https://github.com/przemyslawpluta/node-youtube-dl/commit/80999a5))
395 +
396 +
397 +
398 +<a name="1.5.5"></a>
399 +## 1.5.5 (2014-05-02)
400 +
401 +* can pass execFile options to download ([2986447](https://github.com/przemyslawpluta/node-youtube-dl/commit/2986447))
402 +* dont parse options twice on download ([67eb88d](https://github.com/przemyslawpluta/node-youtube-dl/commit/67eb88d))
403 +* v1.5.5 ([20c3cd2](https://github.com/przemyslawpluta/node-youtube-dl/commit/20c3cd2))
404 +
405 +
406 +
407 +<a name="1.5.4"></a>
408 +## 1.5.4 (2014-05-01)
409 +
410 +* chmod bin directory too ([3d1e88f](https://github.com/przemyslawpluta/node-youtube-dl/commit/3d1e88f))
411 +* run download script on preinstall ([c377b4e](https://github.com/przemyslawpluta/node-youtube-dl/commit/c377b4e))
412 +* update vows ([a3be7a9](https://github.com/przemyslawpluta/node-youtube-dl/commit/a3be7a9))
413 +* v1.5.4 ([a0709a4](https://github.com/przemyslawpluta/node-youtube-dl/commit/a0709a4))
414 +* package: add binary ([2050667](https://github.com/przemyslawpluta/node-youtube-dl/commit/2050667))
415 +
416 +
417 +
418 +<a name="1.5.3"></a>
419 +## 1.5.3 (2014-04-26)
420 +
421 +* dont global link youtube-dl binary. too much confusion. ([b74ed8f](https://github.com/przemyslawpluta/node-youtube-dl/commit/b74ed8f))
422 +* Remove /v/ from the id to accept url like http://www.youtube.com/v/6tC1yOUvvMo provided by the youtu ([b4a3350](https://github.com/przemyslawpluta/node-youtube-dl/commit/b4a3350))
423 +* Remove useless g flag from Regex ([1239606](https://github.com/przemyslawpluta/node-youtube-dl/commit/1239606))
424 +* some code organization ([085b9f7](https://github.com/przemyslawpluta/node-youtube-dl/commit/085b9f7))
425 +* update ignore rules ([0acf105](https://github.com/przemyslawpluta/node-youtube-dl/commit/0acf105))
426 +* v1.5.3 ([3175bd0](https://github.com/przemyslawpluta/node-youtube-dl/commit/3175bd0))
427 +
428 +
429 +
430 +<a name="1.5.2"></a>
431 +## 1.5.2 (2014-04-25)
432 +
433 +* Add a second var ([76d3468](https://github.com/przemyslawpluta/node-youtube-dl/commit/76d3468))
434 +* Fix "Cannot call method 'split' of undefined" bug with last version of youtube-dl (2014.04.21.6) ([864a526](https://github.com/przemyslawpluta/node-youtube-dl/commit/864a526))
435 +* Remove commented old code ([9804155](https://github.com/przemyslawpluta/node-youtube-dl/commit/9804155))
436 +* Remove the extra space ([11aabf9](https://github.com/przemyslawpluta/node-youtube-dl/commit/11aabf9))
437 +* Save the regexp in the outer scope so it's not compiled every time this function runs ([585c526](https://github.com/przemyslawpluta/node-youtube-dl/commit/585c526))
438 +* v1.5.2 ([88be6d7](https://github.com/przemyslawpluta/node-youtube-dl/commit/88be6d7))
439 +
440 +
441 +
442 +<a name="1.5.1"></a>
443 +## 1.5.1 (2014-04-08)
444 +
445 +* add Przemyslaw to contributors ([afc4cc9](https://github.com/przemyslawpluta/node-youtube-dl/commit/afc4cc9))
446 +* fix for win py2.x / py3.x ([472a8db](https://github.com/przemyslawpluta/node-youtube-dl/commit/472a8db))
447 +* v1.5.1 ([7a2620d](https://github.com/przemyslawpluta/node-youtube-dl/commit/7a2620d))
448 +
449 +
450 +
451 +<a name="1.5.0"></a>
452 +# 1.5.0 (2014-04-08)
453 +
454 +* download first if array of clips ([28ed6bb](https://github.com/przemyslawpluta/node-youtube-dl/commit/28ed6bb))
455 +* handle videos download from youtube playlist ([b7434da](https://github.com/przemyslawpluta/node-youtube-dl/commit/b7434da))
456 +* refactor ([6c5187e](https://github.com/przemyslawpluta/node-youtube-dl/commit/6c5187e))
457 +* test update ([8704b8e](https://github.com/przemyslawpluta/node-youtube-dl/commit/8704b8e))
458 +* typo ([540ee03](https://github.com/przemyslawpluta/node-youtube-dl/commit/540ee03))
459 +* typo ([2647ed5](https://github.com/przemyslawpluta/node-youtube-dl/commit/2647ed5))
460 +* v1.5.0 ([b27d373](https://github.com/przemyslawpluta/node-youtube-dl/commit/b27d373))
461 +
462 +
463 +
464 +<a name="1.4.0"></a>
465 +# 1.4.0 (2014-03-14)
466 +
467 +* not needed ([7dcd88f](https://github.com/przemyslawpluta/node-youtube-dl/commit/7dcd88f))
468 +* reflect api changes ([82aeb41](https://github.com/przemyslawpluta/node-youtube-dl/commit/82aeb41))
469 +* update example videos ([3bd98d7](https://github.com/przemyslawpluta/node-youtube-dl/commit/3bd98d7))
470 +* update tests ([c4ab33d](https://github.com/przemyslawpluta/node-youtube-dl/commit/c4ab33d))
471 +* use youtube-dl to get download url, return stream ([3479e52](https://github.com/przemyslawpluta/node-youtube-dl/commit/3479e52))
472 +* v1.4.0 ([e23e5f3](https://github.com/przemyslawpluta/node-youtube-dl/commit/e23e5f3))
473 +
474 +
475 +
476 +<a name="1.3.6"></a>
477 +## 1.3.6 (2014-02-15)
478 +
479 +* fix - youtube-dl incorrect download ([8c439b1](https://github.com/przemyslawpluta/node-youtube-dl/commit/8c439b1))
480 +* v1.3.6 ([be7c22f](https://github.com/przemyslawpluta/node-youtube-dl/commit/be7c22f))
481 +
482 +
483 +
484 +<a name="1.3.5"></a>
485 +## 1.3.5 (2014-02-15)
486 +
487 +* Fix - win handling getInfo & getFormats ([19ccc54](https://github.com/przemyslawpluta/node-youtube-dl/commit/19ccc54))
488 +* Fix - win handling getInfo & getFormats ([7655ea1](https://github.com/przemyslawpluta/node-youtube-dl/commit/7655ea1))
489 +* v1.3.5 ([6f4eb9c](https://github.com/przemyslawpluta/node-youtube-dl/commit/6f4eb9c))
490 +
491 +
492 +
493 +<a name="1.3.4"></a>
494 +## 1.3.4 (2014-02-14)
495 +
496 +* Fix - Incorrect youtube video URL ([954df15](https://github.com/przemyslawpluta/node-youtube-dl/commit/954df15))
497 +* Fix - Incorrect youtube video URL ([17c4214](https://github.com/przemyslawpluta/node-youtube-dl/commit/17c4214))
498 +* Fix - Incorrect youtube video URL ([12dea04](https://github.com/przemyslawpluta/node-youtube-dl/commit/12dea04))
499 +* Fix - Incorrect youtube video URL ([1b10dff](https://github.com/przemyslawpluta/node-youtube-dl/commit/1b10dff))
500 +* Fix - Incorrect youtube video URL ([408e2b1](https://github.com/przemyslawpluta/node-youtube-dl/commit/408e2b1))
501 +* Fix - Incorrect youtube video URL ([c161fa6](https://github.com/przemyslawpluta/node-youtube-dl/commit/c161fa6))
502 +* Fix - Incorrect youtube video URL ([753ae6b](https://github.com/przemyslawpluta/node-youtube-dl/commit/753ae6b))
503 +* Fix - Incorrect youtube video URL ([04f4aaa](https://github.com/przemyslawpluta/node-youtube-dl/commit/04f4aaa))
504 +* Fix - Incorrect youtube video URL ([a5eeb09](https://github.com/przemyslawpluta/node-youtube-dl/commit/a5eeb09))
505 +* Fix - Incorrect youtube video URL ([28dd461](https://github.com/przemyslawpluta/node-youtube-dl/commit/28dd461))
506 +* only write version to file if downloaded successfully ([091f425](https://github.com/przemyslawpluta/node-youtube-dl/commit/091f425))
507 +* v1.3.4 ([6825c7b](https://github.com/przemyslawpluta/node-youtube-dl/commit/6825c7b))
508 +
509 +
510 +
511 +<a name="1.3.3"></a>
512 +## 1.3.3 (2014-02-12)
513 +
514 +* spawn ENOENT in win ([48a309d](https://github.com/przemyslawpluta/node-youtube-dl/commit/48a309d))
515 +* spawn ENOENT in win ([b6191c8](https://github.com/przemyslawpluta/node-youtube-dl/commit/b6191c8))
516 +* spawn ENOENT in win ([a816720](https://github.com/przemyslawpluta/node-youtube-dl/commit/a816720))
517 +* spawn ENOENT in win ([b6178e6](https://github.com/przemyslawpluta/node-youtube-dl/commit/b6178e6))
518 +* tiny cleanup ([19a0059](https://github.com/przemyslawpluta/node-youtube-dl/commit/19a0059))
519 +* update get formats regexp ([9df37f0](https://github.com/przemyslawpluta/node-youtube-dl/commit/9df37f0))
520 +* update ugh tests ([db2388c](https://github.com/przemyslawpluta/node-youtube-dl/commit/db2388c))
521 +* v1.3.3 ([f4498fa](https://github.com/przemyslawpluta/node-youtube-dl/commit/f4498fa))
522 +
523 +
524 +
525 +<a name="1.3.2"></a>
526 +## 1.3.2 (2013-10-22)
527 +
528 +* improve regexp to download latest version ([9040f81](https://github.com/przemyslawpluta/node-youtube-dl/commit/9040f81))
529 +* removed check for query.v that breaks soundcloud functionality ([11da4f7](https://github.com/przemyslawpluta/node-youtube-dl/commit/11da4f7))
530 +* version bump ([60cce67](https://github.com/przemyslawpluta/node-youtube-dl/commit/60cce67))
531 +
532 +
533 +
534 +<a name="1.3.1"></a>
535 +## 1.3.1 (2013-10-15)
536 +
537 +* always download latest version of youtube-dl ([c7de217](https://github.com/przemyslawpluta/node-youtube-dl/commit/c7de217))
538 +* fix reading download state ([174743a](https://github.com/przemyslawpluta/node-youtube-dl/commit/174743a))
539 +* formats change :/ ([e6f172d](https://github.com/przemyslawpluta/node-youtube-dl/commit/e6f172d))
540 +* make sure to delete downloaded file ([be74d80](https://github.com/przemyslawpluta/node-youtube-dl/commit/be74d80))
541 +* only download if new version ([1c8211c](https://github.com/przemyslawpluta/node-youtube-dl/commit/1c8211c))
542 +* specify format to download ([429687c](https://github.com/przemyslawpluta/node-youtube-dl/commit/429687c))
543 +* v1.3.1 ([23128d7](https://github.com/przemyslawpluta/node-youtube-dl/commit/23128d7))
544 +
545 +
546 +
547 +<a name="1.3.0"></a>
548 +# 1.3.0 (2013-09-13)
549 +
550 +* add getFormats() ([604fa7b](https://github.com/przemyslawpluta/node-youtube-dl/commit/604fa7b))
551 +* some style changes ([08a2ba5](https://github.com/przemyslawpluta/node-youtube-dl/commit/08a2ba5))
552 +* version bump ([1735865](https://github.com/przemyslawpluta/node-youtube-dl/commit/1735865))
553 +
554 +
555 +
556 +<a name="1.2.12"></a>
557 +## 1.2.12 (2013-08-27)
558 +
559 +* add id to download info ([eb92288](https://github.com/przemyslawpluta/node-youtube-dl/commit/eb92288))
560 +* better info test ([e4a1b2f](https://github.com/przemyslawpluta/node-youtube-dl/commit/e4a1b2f))
561 +* take into account multi line descriptions ([63ad7c2](https://github.com/przemyslawpluta/node-youtube-dl/commit/63ad7c2))
562 +* version bump ([8625ff4](https://github.com/przemyslawpluta/node-youtube-dl/commit/8625ff4))
563 +
564 +
565 +
566 +<a name="1.2.11"></a>
567 +## 1.2.11 (2013-08-23)
568 +
569 +* add id, itag, and resolution to `info()` ([11c7f68](https://github.com/przemyslawpluta/node-youtube-dl/commit/11c7f68))
570 +* version bump ([c5fc896](https://github.com/przemyslawpluta/node-youtube-dl/commit/c5fc896))
571 +
572 +
573 +
574 +<a name="1.2.10"></a>
575 +## 1.2.10 (2013-08-04)
576 +
577 +* cleaner example output ([7fcdf8f](https://github.com/przemyslawpluta/node-youtube-dl/commit/7fcdf8f))
578 +* correctly split lines ([13368d1](https://github.com/przemyslawpluta/node-youtube-dl/commit/13368d1))
579 +* update event-stream ([87983c1](https://github.com/przemyslawpluta/node-youtube-dl/commit/87983c1))
580 +* version bump ([b605c93](https://github.com/przemyslawpluta/node-youtube-dl/commit/b605c93))
581 +
582 +
583 +
584 +<a name="1.2.9"></a>
585 +## 1.2.9 (2013-08-04)
586 +
587 +* error checking ([524416b](https://github.com/przemyslawpluta/node-youtube-dl/commit/524416b))
588 +* update youtube-dl version ([f4d21ec](https://github.com/przemyslawpluta/node-youtube-dl/commit/f4d21ec))
589 +* version bump ([4fc9e1c](https://github.com/przemyslawpluta/node-youtube-dl/commit/4fc9e1c))
590 +
591 +
592 +
593 +<a name="1.2.8"></a>
594 +## 1.2.8 (2013-05-17)
595 +
596 +* [ci skip] ([8af4a1f](https://github.com/przemyslawpluta/node-youtube-dl/commit/8af4a1f))
597 +* check if progress is printed at least once ([189834d](https://github.com/przemyslawpluta/node-youtube-dl/commit/189834d))
598 +* fix tests ([e0895a4](https://github.com/przemyslawpluta/node-youtube-dl/commit/e0895a4))
599 +* minor cosmetics ([af3a82c](https://github.com/przemyslawpluta/node-youtube-dl/commit/af3a82c))
600 +* more thorough tests ([1d96ad2](https://github.com/przemyslawpluta/node-youtube-dl/commit/1d96ad2))
601 +* Release v1.2.8 ([85ca0da](https://github.com/przemyslawpluta/node-youtube-dl/commit/85ca0da))
602 +* update exists method ([1fbfb00](https://github.com/przemyslawpluta/node-youtube-dl/commit/1fbfb00))
603 +* update node versions ([73e93d1](https://github.com/przemyslawpluta/node-youtube-dl/commit/73e93d1))
604 +* update regexp for download progress ([f64ff44](https://github.com/przemyslawpluta/node-youtube-dl/commit/f64ff44))
605 +* update where youtube-dl is downloaded from ([dfe6234](https://github.com/przemyslawpluta/node-youtube-dl/commit/dfe6234))
606 +
607 +
608 +
609 +<a name="1.2.7"></a>
610 +## 1.2.7 (2012-08-19)
611 +
612 +* cleanup ([36e8741](https://github.com/przemyslawpluta/node-youtube-dl/commit/36e8741))
613 +* link to ytdl ([fc09348](https://github.com/przemyslawpluta/node-youtube-dl/commit/fc09348))
614 +* Release v1.2.7 ([dafa422](https://github.com/przemyslawpluta/node-youtube-dl/commit/dafa422))
615 +* version bump ([236a4a7](https://github.com/przemyslawpluta/node-youtube-dl/commit/236a4a7))
616 +
617 +
618 +
619 +<a name="1.2.6"></a>
620 +## 1.2.6 (2012-08-01)
621 +
622 +* buffer info call ([c46a993](https://github.com/przemyslawpluta/node-youtube-dl/commit/c46a993))
623 +* make sure to delete downloaded file ([5247bdb](https://github.com/przemyslawpluta/node-youtube-dl/commit/5247bdb))
624 +* separate youtubedl stdout by line ([a1b7294](https://github.com/przemyslawpluta/node-youtube-dl/commit/a1b7294))
625 +* version bump ([4f30db8](https://github.com/przemyslawpluta/node-youtube-dl/commit/4f30db8))
626 +
627 +
628 +
629 +<a name="1.2.5"></a>
630 +## 1.2.5 (2012-07-07)
631 +
632 +* [fix] path.existsSync was moved to fs.existsSync ([aadc85a](https://github.com/przemyslawpluta/node-youtube-dl/commit/aadc85a))
633 +* added node v0.8 ([a0dc4d8](https://github.com/przemyslawpluta/node-youtube-dl/commit/a0dc4d8))
634 +* existsSync ([876d969](https://github.com/przemyslawpluta/node-youtube-dl/commit/876d969))
635 +* fix existsSync ([24b7db7](https://github.com/przemyslawpluta/node-youtube-dl/commit/24b7db7))
636 +* removed engines ([1e3c85e](https://github.com/przemyslawpluta/node-youtube-dl/commit/1e3c85e))
637 +* use `fs.exists` ([658c651](https://github.com/przemyslawpluta/node-youtube-dl/commit/658c651))
638 +* version bump ([6d678d8](https://github.com/przemyslawpluta/node-youtube-dl/commit/6d678d8))
639 +
640 +
641 +
642 +<a name="1.2.4"></a>
643 +## 1.2.4 (2012-03-10)
644 +
645 +* more efficient youtube-dl download ([574cd7f](https://github.com/przemyslawpluta/node-youtube-dl/commit/574cd7f))
646 +* ver bump ([fe10efb](https://github.com/przemyslawpluta/node-youtube-dl/commit/fe10efb))
647 +* ver bump ([3fb0f0e](https://github.com/przemyslawpluta/node-youtube-dl/commit/3fb0f0e))
648 +
649 +
650 +
651 +<a name="1.2.3"></a>
652 +## 1.2.3 (2012-03-04)
653 +
654 +* used `__dirname` instead of `./` to save download ([b5fb4bf](https://github.com/przemyslawpluta/node-youtube-dl/commit/b5fb4bf))
655 +* used `path.join` to make it more cross-platform ([05c2ba3](https://github.com/przemyslawpluta/node-youtube-dl/commit/05c2ba3))
656 +
657 +
658 +
659 +<a name="1.2.2"></a>
660 +## 1.2.2 (2012-02-06)
661 +
662 +* Better error reporting ([e853b64](https://github.com/przemyslawpluta/node-youtube-dl/commit/e853b64))
663 +
664 +
665 +
666 +<a name="1.2.1"></a>
667 +## 1.2.1 (2012-01-04)
668 +
669 +* added test dir ([1695d60](https://github.com/przemyslawpluta/node-youtube-dl/commit/1695d60))
670 +* added test script ([39ecfd6](https://github.com/przemyslawpluta/node-youtube-dl/commit/39ecfd6))
671 +* better formatting ([16ad412](https://github.com/przemyslawpluta/node-youtube-dl/commit/16ad412))
672 +* better versioning ([40d175e](https://github.com/przemyslawpluta/node-youtube-dl/commit/40d175e))
673 +* cleared file ([c30ae25](https://github.com/przemyslawpluta/node-youtube-dl/commit/c30ae25))
674 +* javascript syntax ([42c9fd9](https://github.com/przemyslawpluta/node-youtube-dl/commit/42c9fd9))
675 +* organized readme ([c6069fd](https://github.com/przemyslawpluta/node-youtube-dl/commit/c6069fd))
676 +* removed v0.5 ([ef5e15c](https://github.com/przemyslawpluta/node-youtube-dl/commit/ef5e15c))
677 +* restored ([2ab9779](https://github.com/przemyslawpluta/node-youtube-dl/commit/2ab9779))
678 +* travis ci ([548d808](https://github.com/przemyslawpluta/node-youtube-dl/commit/548d808))
679 +* Written back to Javascript ([0063944](https://github.com/przemyslawpluta/node-youtube-dl/commit/0063944))
680 +
681 +
682 +
683 +<a name="1.2.0"></a>
684 +# 1.2.0 (2011-09-16)
685 +
686 +* added filename to data returned ([49909ca](https://github.com/przemyslawpluta/node-youtube-dl/commit/49909ca))
687 +* added tests ([1377915](https://github.com/przemyslawpluta/node-youtube-dl/commit/1377915))
688 +* fixed installation issue ([d05b14c](https://github.com/przemyslawpluta/node-youtube-dl/commit/d05b14c))
689 +* fixed symlink installation issue ([68199c0](https://github.com/przemyslawpluta/node-youtube-dl/commit/68199c0))
690 +
691 +
692 +
693 +<a name="1.1.0"></a>
694 +# 1.1.0 (2011-08-27)
695 +
696 +* now uses emitter ([7063855](https://github.com/przemyslawpluta/node-youtube-dl/commit/7063855))
697 +* update ([5c6ff08](https://github.com/przemyslawpluta/node-youtube-dl/commit/5c6ff08))
698 +
699 +
700 +
701 +<a name="1.0.4"></a>
702 +## 1.0.4 (2011-08-07)
703 +
704 +* added *.mp4 ([6b7a1dc](https://github.com/przemyslawpluta/node-youtube-dl/commit/6b7a1dc))
705 +* added scripts folder to tasks ([bfa584b](https://github.com/przemyslawpluta/node-youtube-dl/commit/bfa584b))
706 +* added scripts to watch task ([0afc347](https://github.com/przemyslawpluta/node-youtube-dl/commit/0afc347))
707 +* better organized ([dfd57c6](https://github.com/przemyslawpluta/node-youtube-dl/commit/dfd57c6))
708 +* commit ([059d81b](https://github.com/przemyslawpluta/node-youtube-dl/commit/059d81b))
709 +* convenience ([2cb471e](https://github.com/przemyslawpluta/node-youtube-dl/commit/2cb471e))
710 +* fixed error in info function ([ea6ceda](https://github.com/przemyslawpluta/node-youtube-dl/commit/ea6ceda))
711 +* fixed main ([572509b](https://github.com/przemyslawpluta/node-youtube-dl/commit/572509b))
712 +* minimalist ([bb5c5fb](https://github.com/przemyslawpluta/node-youtube-dl/commit/bb5c5fb))
713 +* now requires coffee-script to run ([8be7f53](https://github.com/przemyslawpluta/node-youtube-dl/commit/8be7f53))
714 +* organized ([aeaf9c8](https://github.com/przemyslawpluta/node-youtube-dl/commit/aeaf9c8))
715 +* organized ([2544054](https://github.com/przemyslawpluta/node-youtube-dl/commit/2544054))
716 +* organized ([cbea725](https://github.com/przemyslawpluta/node-youtube-dl/commit/cbea725))
717 +* removed coffeescript from installation ([b5bc9d8](https://github.com/przemyslawpluta/node-youtube-dl/commit/b5bc9d8))
718 +* updated version number ([df8861a](https://github.com/przemyslawpluta/node-youtube-dl/commit/df8861a))
719 +* when finished downloading, statistics data will be passed ([77a99e5](https://github.com/przemyslawpluta/node-youtube-dl/commit/77a99e5))
720 +
721 +
722 +
1 +Copyright (C) 2011 by Roly Fentanes
2 +
3 +Permission is hereby granted, free of charge, to any person obtaining a copy
4 +of this software and associated documentation files (the "Software"), to deal
5 +in the Software without restriction, including without limitation the rights
6 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 +copies of the Software, and to permit persons to whom the Software is
8 +furnished to do so, subject to the following conditions:
9 +
10 +The above copyright notice and this permission notice shall be included in
11 +all copies or substantial portions of the Software.
12 +
13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 +THE SOFTWARE.
1 +# youtube-dl
2 +
3 +[![Build Status](https://travis-ci.org/przemyslawpluta/node-youtube-dl.svg?branch=master)](https://travis-ci.org/przemyslawpluta/node-youtube-dl) [![npm version](https://badge.fury.io/js/youtube-dl.svg)](https://badge.fury.io/js/youtube-dl)
4 +
5 +Download videos from youtube in node.js using [youtube-dl](http://rg3.github.com/youtube-dl/).
6 +
7 +If you're only interested in downloading only from youtube, you should consider using [pure Javascript youtube downloading module](https://github.com/fent/node-ytdl).
8 +
9 +## Installation
10 +
11 +With [npm](https://www.npmjs.com/) do:
12 +
13 +``` sh
14 +npm install @microlink/youtube-dl
15 +```
16 +
17 +## Usage
18 +
19 +### Downloading videos
20 +
21 +``` js
22 +var fs = require('fs');
23 +var youtubedl = require('youtube-dl');
24 +var video = youtubedl('http://www.youtube.com/watch?v=90AiXO1pAiA',
25 + // Optional arguments passed to youtube-dl.
26 + ['--format=18'],
27 + // Additional options can be given for calling `child_process.execFile()`.
28 + { cwd: __dirname });
29 +
30 +// Will be called when the download starts.
31 +video.on('info', function(info) {
32 + console.log('Download started');
33 + console.log('filename: ' + info._filename);
34 + console.log('size: ' + info.size);
35 +});
36 +
37 +video.pipe(fs.createWriteStream('myvideo.mp4'));
38 +```
39 +
40 +It will produce an output that looks like the following when ran.
41 +
42 +```bash
43 +Got video info
44 +saving to T-ara - Number Nine - MV - 티아라-Seku9G1kT0c.mp4
45 +100.00%
46 +```
47 +
48 +### Resuming partially downloaded videos
49 +
50 +``` js
51 +var youtubedl = require('./');
52 +var fs = require('fs');
53 +var output = 'myvideo.mp4';
54 +
55 +var downloaded = 0;
56 +if (fs.existsSync(output)) {
57 + downloaded = fs.statSync(output).size;
58 +}
59 +
60 +var video = youtubedl('https://www.youtube.com/watch?v=179MiZSibco',
61 +
62 + // Optional arguments passed to youtube-dl.
63 + ['--format=18'],
64 +
65 + // start will be sent as a range header
66 + { start: downloaded, cwd: __dirname });
67 +
68 +// Will be called when the download starts.
69 +video.on('info', function(info) {
70 + console.log('Download started');
71 + console.log('filename: ' + info._filename);
72 +
73 + // info.size will be the amount to download, add
74 + var total = info.size + downloaded;
75 + console.log('size: ' + total);
76 +
77 + if (downloaded > 0) {
78 + // size will be the amount already downloaded
79 + console.log('resuming from: ' + downloaded);
80 +
81 + // display the remaining bytes to download
82 + console.log('remaining bytes: ' + info.size);
83 + }
84 +});
85 +
86 +video.pipe(fs.createWriteStream('myvideo.mp4', { flags: 'a' }));
87 +
88 +// Will be called if download was already completed and there is nothing more to download.
89 +video.on('complete', function complete(info) {
90 + 'use strict';
91 + console.log('filename: ' + info._filename + ' already downloaded.');
92 +});
93 +
94 +video.on('end', function() {
95 + console.log('finished downloading!');
96 +});
97 +```
98 +
99 +It will produce an output that looks like the following when ran.
100 +
101 +**Output:**
102 +
103 +``` sh
104 +[~/nodejs/node-youtube-dl/example]$ node resume.js
105 +Download started
106 +filename: 1 1 1-179MiZSibco.mp4
107 +size: 5109213
108 +^C
109 +```
110 +
111 +``` sh
112 +[~/nodejs/node-youtube-dl/example]$ node resume.js
113 +Download started
114 +filename: 1 1 1-179MiZSibco.mp4
115 +size: 5109213
116 +resuming from: 917504
117 +remaining bytes: 4191709
118 +finished downloading
119 +```
120 +
121 +### Getting video information
122 +
123 +``` js
124 +var youtubedl = require('youtube-dl');
125 +var url = 'http://www.youtube.com/watch?v=WKsjaOqDXgg';
126 +// Optional arguments passed to youtube-dl.
127 +var options = ['--username=user', '--password=hunter2'];
128 +youtubedl.getInfo(url, options, function(err, info) {
129 + if (err) throw err;
130 +
131 + console.log('id:', info.id);
132 + console.log('title:', info.title);
133 + console.log('url:', info.url);
134 + console.log('thumbnail:', info.thumbnail);
135 + console.log('description:', info.description);
136 + console.log('filename:', info._filename);
137 + console.log('format id:', info.format_id);
138 +});
139 +```
140 +
141 +Running that will produce something like
142 +
143 +``` sh
144 +id: WKsjaOqDXgg
145 +title: Ace Rimmer to the Rescue
146 +url: http://r5---sn-p5qlsn7e.c.youtube.com/videoplayback?ms=au&ip=160.79.125.18&cp=U0hWTFVQVl9FTENONl9NSlpDOjgtU1VsODlkVmRH&id=58ab2368ea835e08&source=youtube&expire=1377558202&factor=1.25&key=yt1&ipbits=8&mt=1377534150&itag=34&sver=3&upn=-rGWz2vYpN4&fexp=912306%2C927900%2C919395%2C926518%2C936203%2C913819%2C929117%2C929121%2C929906%2C929907%2C929922%2C929127%2C929129%2C929131%2C929930%2C925726%2C925720%2C925722%2C925718%2C929917%2C906945%2C929919%2C929933%2C912521%2C932306%2C913428%2C904830%2C919373%2C930803%2C908536%2C904122%2C938701%2C936308%2C909549%2C900816%2C912711%2C904494%2C904497%2C900375%2C906001&sparams=algorithm%2Cburst%2Ccp%2Cfactor%2Cid%2Cip%2Cipbits%2Citag%2Csource%2Cupn%2Cexpire&mv=m&burst=40&algorithm=throttle-factor&signature=ABD3A847684AD9B39331E567568D3FA0DCFA4776.7895521E130A042FB3625A17242CE3C02A4460B7&ratebypass=yes
147 +thumbnail: https://i1.ytimg.com/vi/WKsjaOqDXgg/hqdefault.jpg
148 +description: An old Red Dwarf eposide where Ace Rimmer saves the Princess Bonjella.
149 +filename: Ace Rimmer to the Rescue-WKsjaOqDXgg.flv
150 +format id: 34
151 +```
152 +
153 +You can use an array of urls to produce an array of response objects with matching array index (e.g. the 1st response object will match the first url etc...)
154 +
155 +``` js
156 +var youtubedl = require('youtube-dl');
157 +var url1 = 'http://www.youtube.com/watch?v=WKsjaOqDXgg';
158 +var url2 = 'https://vimeo.com/6586873';
159 +youtubedl.getInfo([url1, url2], function(err, info) {
160 + if (err) throw err;
161 +
162 + console.log('title for the url1:', info[0].title);
163 + console.log('title for the url2:', info[1].title);
164 +});
165 +```
166 +
167 +### Downloading subtitles
168 +
169 +``` js
170 +var youtubedl = require('youtube-dl');
171 +var url = 'https://youtu.be/PizwcirYuGY';
172 +
173 +var options = {
174 + // Write automatic subtitle file (youtube only)
175 + auto: false,
176 + // Downloads all the available subtitles.
177 + all: false,
178 + // Subtitle format. YouTube generated subtitles
179 + // are available ttml or vtt.
180 + format: 'ttml',
181 + // Languages of subtitles to download, separated by commas.
182 + lang: 'en',
183 + // The directory to save the downloaded files in.
184 + cwd: __dirname,
185 +};
186 +youtubedl.getSubs(url, options, function(err, files) {
187 + if (err) throw err;
188 +
189 + console.log('subtitle files downloaded:', files);
190 +});
191 +```
192 +
193 +### Downloading thumbnails
194 +
195 +``` js
196 +var youtubedl = require('youtube-dl');
197 +var url = 'https://youtu.be/PizwcirYuGY';
198 +
199 +var options = {
200 + // Downloads available thumbnail.
201 + all: false,
202 + // The directory to save the downloaded files in.
203 + cwd: __dirname,
204 +};
205 +youtubedl.getThumbs(url, options, function(err, files) {
206 + if (err) throw err;
207 + console.log('thumbnail file downloaded:', files);
208 +});
209 +```
210 +
211 +For more usage info on youtube-dl and the arguments you can pass to it, do `youtube-dl -h` or go to the [youtube-dl documentation][].
212 +
213 +### Downloading playlists
214 +
215 +``` js
216 +
217 +var path = require('path');
218 +var fs = require('fs');
219 +var ytdl = require('youtube-dl');
220 +
221 +function playlist(url) {
222 +
223 + 'use strict';
224 + var video = ytdl(url);
225 +
226 + video.on('error', function error(err) {
227 + console.log('error 2:', err);
228 + });
229 +
230 + var size = 0;
231 + video.on('info', function(info) {
232 + size = info.size;
233 + var output = path.join(__dirname + '/', size + '.mp4');
234 + video.pipe(fs.createWriteStream(output));
235 + });
236 +
237 + var pos = 0;
238 + video.on('data', function data(chunk) {
239 + pos += chunk.length;
240 + // `size` should not be 0 here.
241 + if (size) {
242 + var percent = (pos / size * 100).toFixed(2);
243 + process.stdout.cursorTo(0);
244 + process.stdout.clearLine(1);
245 + process.stdout.write(percent + '%');
246 + }
247 + });
248 +
249 + video.on('next', playlist);
250 +
251 +}
252 +
253 +playlist('https://www.youtube.com/playlist?list=PLEFA9E9D96CB7F807');
254 +
255 +```
256 +
257 +### Getting the list of extractors
258 +
259 +``` js
260 +var youtubedl = require('youtube-dl');
261 +youtubedl.getExtractors(true, function(err, list) {
262 + console.log('Found ' + list.length + ' extractors');
263 + for (var i = 0; i < list.length; i++) {
264 + console.log(list[i]);
265 + }
266 +});
267 +```
268 +
269 +Will print something like
270 +
271 +``` sh
272 +Found 521 extractors
273 +1up.com
274 +220.ro
275 +24video
276 +3sat
277 +```
278 +
279 +### Call the `youtube-dl` binary directly
280 +
281 +This module doesn't have `youtube-dl` download the video. Instead, it uses the `url` key from the `--dump-json` CLI option to create a node stream. That way, it can be used like any other node stream.
282 +
283 +If that, or none of the above support your use case, you can use `ytdl.exec()` to call `youtube-dl` however you like.
284 +
285 +``` js
286 +ytdl.exec(url, ['-x', '--audio-format', 'mp3'], {}, function(err, output) {
287 + if (err) throw err;
288 + console.log(output.join('\n'));
289 +});
290 +```
291 +
292 +### Update
293 +
294 +Since the youtube-dl binary is updated regularly, you can run `npm run update` to check for and download any updates for it. You can also require `../lib/downloader` in your app if you'd like to place `youtube-dl` binary in a specific directory and control when it gets updates.
295 +
296 +``` js
297 +var downloader = require('../lib/downloader');
298 +
299 +downloader('path/to-binary', function error(err, done) {
300 + 'use strict';
301 + if (err) { return console.log(err.stack); }
302 + console.log(done);
303 +});
304 +```
305 +
306 +### Tests
307 +
308 +Tests are written with [vows](http://vowsjs.org/)
309 +
310 +``` sh
311 +npm test
312 +```
313 +
314 +## License
315 +
316 +MIT
317 +
318 +[youtube-dl]: http://rg3.github.com/youtube-dl/
319 +[youtube-dl documentation]: http://rg3.github.com/youtube-dl/documentation.html
1 +{"version":"2019.05.20","path":null,"exec":"youtube-dl.exe"}
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict'
2 +
3 +const request = require('request')
4 +const mkdirp = require('mkdirp')
5 +const path = require('path')
6 +const fs = require('fs')
7 +
8 +const [, , ...flags] = process.argv
9 +
10 +const isWin = flags.includes('--platform=windows') || require('./util').isWin
11 +
12 +// First, look for the download link.
13 +let dir, filePath
14 +const defaultBin = path.join(__dirname, '..', 'bin')
15 +const defaultPath = path.join(defaultBin, 'details')
16 +const url = 'https://yt-dl.org/downloads/latest/youtube-dl'
17 +
18 +function download (url, callback) {
19 + let status
20 +
21 + // download the correct version of the binary based on the platform
22 + url = exec(url)
23 +
24 + request.get(url, { followRedirect: false }, function (err, res) {
25 + if (err) return callback(err)
26 +
27 + if (res.statusCode !== 302) {
28 + return callback(
29 + new Error(
30 + 'Did not get redirect for the latest version link. Status: ' +
31 + res.statusCode
32 + )
33 + )
34 + }
35 +
36 + const url = res.headers.location
37 + const downloadFile = request.get(url)
38 + const newVersion = /yt-dl\.org\/downloads\/(\d{4}\.\d\d\.\d\d(\.\d)?)\/youtube-dl/.exec(
39 + url
40 + )[1]
41 +
42 + downloadFile.on('response', function response (res) {
43 + if (res.statusCode !== 200) {
44 + status = new Error('Response Error: ' + res.statusCode)
45 + return
46 + }
47 + downloadFile.pipe(fs.createWriteStream(filePath, { mode: 493 }))
48 + })
49 +
50 + downloadFile.on('error', function error (err) {
51 + callback(err)
52 + })
53 +
54 + downloadFile.on('end', function end () {
55 + callback(status, newVersion)
56 + })
57 + })
58 +}
59 +
60 +const exec = path => (isWin ? path + '.exe' : path)
61 +
62 +function createBase (binDir) {
63 + dir = binDir || defaultBin
64 + mkdirp.sync(dir)
65 + if (binDir) mkdirp.sync(defaultBin)
66 + filePath = path.join(dir, exec('youtube-dl'))
67 +}
68 +
69 +function downloader (binDir, callback) {
70 + if (typeof binDir === 'function') {
71 + callback = binDir
72 + binDir = null
73 + }
74 +
75 + createBase(binDir)
76 +
77 + download(url, function error (err, newVersion) {
78 + if (err) return callback(err)
79 + fs.writeFileSync(
80 + defaultPath,
81 + JSON.stringify({
82 + version: newVersion,
83 + path: binDir ? filePath : binDir,
84 + exec: exec('youtube-dl')
85 + }),
86 + 'utf8'
87 + )
88 + return callback(null, 'Downloaded youtube-dl ' + newVersion)
89 + })
90 +}
91 +
92 +module.exports = downloader
1 +// Arguments we dont want users to use with youtube-dl
2 +// because they will break the module.
3 +const badArgs = [
4 + '-h',
5 + '--help',
6 + '-v',
7 + '--version',
8 + '-U',
9 + '--update',
10 + '-q',
11 + '--quiet',
12 + '-s',
13 + '--simulate',
14 + '-g',
15 + '--get-url',
16 + '-e',
17 + '--get-title',
18 + '--get-id',
19 + '--get-thumbnail',
20 + '--get-description',
21 + '--get-duration',
22 + '--get-filename',
23 + '--get-format',
24 + '-j',
25 + '--dump-json',
26 + '--newline',
27 + '--no-progress',
28 + '--console-title',
29 + '-v',
30 + '--verbose',
31 + '--dump-intermediate-pages',
32 + '--write-pages',
33 + '--print-traffic'
34 +]
35 +
36 +/**
37 + * Helps parse options used in youtube-dl command.
38 + *
39 + * @param {Array.<String>}
40 + * @return {Array.<String>}
41 + */
42 +exports.parseOpts = function (args) {
43 + var pos
44 + for (var i = 0, len = badArgs.length; i < len; i++) {
45 + if ((pos = args.indexOf(badArgs[i])) !== -1) {
46 + args.splice(pos, 1)
47 + }
48 + }
49 + return args
50 +}
51 +
52 +/**
53 + * Converts seconds to format hh:mm:ss
54 + *
55 + * @param {Number} seconds
56 + * @return {String}
57 + */
58 +exports.formatDuration = function (seconds) {
59 + var parts = []
60 + parts.push(seconds % 60)
61 + var minutes = Math.floor(seconds / 60)
62 + if (minutes > 0) {
63 + parts.push(minutes % 60)
64 + var hours = Math.floor(minutes / 60)
65 + if (hours > 0) {
66 + parts.push(hours)
67 + }
68 + }
69 + return parts.reverse().join(':')
70 +}
71 +
72 +/**
73 + * Checks wether str is a string or not
74 + *
75 + * @param {String} str
76 + * @return {Boolean}
77 + */
78 +exports.isString = str => typeof str === 'string'
79 +
80 +/**
81 + * Checks arr contains value
82 + *
83 + * @param {Array} arr
84 + * @param {string|number} arr
85 + * @return {Boolean}
86 + */
87 +exports.has = (arr, value) => arr && arr.indexOf(value) > -1
88 +
89 +exports.isYouTubeRegex = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\//
90 +
91 +exports.isWin =
92 + process.platform === 'win32' || process.env.NODE_PLATFORM === 'windows'
1 +'use strict'
2 +
3 +const execFile = require('child_process').execFile
4 +const streamify = require('streamify')
5 +const request = require('request')
6 +const hms = require('hh-mm-ss')
7 +const path = require('path')
8 +const http = require('http')
9 +const url = require('url')
10 +const fs = require('fs')
11 +
12 +const {
13 + isYouTubeRegex,
14 + isWin,
15 + formatDuration,
16 + has,
17 + isString
18 +} = require('./util')
19 +
20 +const detailsPath = path.join(__dirname, '..', 'bin/details')
21 +
22 +const TEN_MEGABYTES = 1000 * 1000 * 10
23 +
24 +const execFileOpts = { maxBuffer: TEN_MEGABYTES }
25 +
26 +let ytdlBinary = (() => {
27 + if (fs.existsSync(detailsPath)) {
28 + const details = JSON.parse(fs.readFileSync(detailsPath))
29 + return details.path
30 + ? details.path
31 + : path.resolve(__dirname, '..', 'bin', details.exec)
32 + }
33 +
34 + if (!fs.existsSync(ytdlBinary)) {
35 + console.error(
36 + 'ERROR: unable to locate youtube-dl details in ' +
37 + path.dirname(ytdlBinary)
38 + )
39 + process.exit(1)
40 + }
41 +})()
42 +
43 +function youtubeDl (args, options, cb) {
44 + execFile(ytdlBinary, args, { ...execFileOpts, ...options }, function done (
45 + err,
46 + stdout,
47 + stderr
48 + ) {
49 + if (err) return cb(err)
50 + return cb(null, stdout.trim().split(/\r?\n/))
51 + })
52 +}
53 +
54 +/**
55 + * Processes data
56 + *
57 + * @param {Object} data
58 + * @param {Object} options
59 + * @param {Object} stream
60 + */
61 +
62 +function processData (data, options, stream) {
63 + const item = !data.length ? data : data.shift()
64 +
65 + // fix for pause/resume downloads
66 + const headers = Object.assign(
67 + { Host: url.parse(item.url).hostname },
68 + data.http_headers
69 + )
70 +
71 + if (options && options.start > 0 && options.end > 0) {
72 + headers.Range = 'bytes=' + options.start + '-' + options.end
73 + }
74 +
75 + const req = request({ url: item.url, headers: headers, ecdhCurve: 'auto' })
76 +
77 + req.on('response', function response (res) {
78 + const size = parseInt(res.headers['content-length'], 10)
79 + if (size) item.size = size
80 +
81 + if (options && options.start > 0 && res.statusCode === 416) {
82 + // the file that is being resumed is complete.
83 + return stream.emit('complete', item)
84 + }
85 +
86 + if (res.statusCode !== 200 && res.statusCode !== 206) {
87 + return stream.emit('error', new Error('status code ' + res.statusCode))
88 + }
89 +
90 + stream.emit('info', item)
91 +
92 + stream.on('end', function end () {
93 + if (data.length) stream.emit('next', data)
94 + })
95 + })
96 +
97 + return stream.resolve(req)
98 +}
99 +
100 +/**
101 + * Downloads a video.
102 + *
103 + * @param {String} videoUrl
104 + * @param {!Array.<String>} args
105 + * @param {!Object} options
106 + */
107 +const ytdl = (module.exports = function (videoUrl, args, options) {
108 + const stream = streamify({
109 + superCtor: http.ClientResponse,
110 + readable: true,
111 + writable: false
112 + })
113 +
114 + if (!isString(videoUrl)) {
115 + processData(videoUrl, options, stream)
116 + return stream
117 + }
118 +
119 + ytdl.getInfo(videoUrl, args, options, function getInfo (err, data) {
120 + return err ? stream.emit('error', err) : processData(data, options, stream)
121 + })
122 +
123 + return stream
124 +})
125 +
126 +/**
127 + * Calls youtube-dl with some arguments and the `cb`
128 + * gets called with the output.
129 + *
130 + * @param {String|Array.<String>}
131 + * @param {Array.<String>} args
132 + * @param {Array.<String>} args2
133 + * @param {Object} options
134 + * @param {Function(!Error, String)} cb
135 + */
136 +function call (urls, args1, args2, options = {}, cb) {
137 + let args = args1
138 + if (args2) args = args.concat(args2)
139 +
140 + // check if encoding is already set
141 + if (isWin && !args.includes('--encoding')) {
142 + args.push('--encoding')
143 + args.push('utf8')
144 + }
145 +
146 + if (urls !== null) {
147 + if (isString(urls)) urls = [urls]
148 +
149 + for (let i = 0; i < urls.length; i++) {
150 + const video = urls[i]
151 + if (isYouTubeRegex.test(video)) {
152 + // Get possible IDs.
153 + const details = url.parse(video, true)
154 + let id = details.query.v || ''
155 + if (id) {
156 + args.push('http://www.youtube.com/watch?v=' + id)
157 + } else {
158 + // Get possible IDs for youtu.be from urladdr.
159 + id = details.pathname.slice(1).replace(/^v\//, '')
160 + if (id) {
161 + args.push(video)
162 + args.unshift('-i')
163 + }
164 + }
165 + } else {
166 + if (i === 0) args.push('--')
167 + args.push(video)
168 + }
169 + }
170 + }
171 +
172 + return youtubeDl(args, options, cb)
173 +}
174 +
175 +/**
176 + * Calls youtube-dl with some arguments and the `cb`
177 + * gets called with the output.
178 + *
179 + * @param {String} url
180 + * @param {Array.<String>} args
181 + * @param {Object} options
182 + * @param {Function(!Error, String)} cb
183 + */
184 +ytdl.exec = function exec (url, args, options, cb) {
185 + return call(url, [], args, options, cb)
186 +}
187 +
188 +/**
189 + * @param {Object} data
190 + * @returns {Object}
191 + */
192 +function parseInfo (data) {
193 + // youtube-dl might return just an url as a string when using the "-g" or "--get-url" flag
194 + if (isString(data) && data.startsWith('http')) {
195 + data = JSON.stringify({ url: data })
196 + }
197 +
198 + const info = JSON.parse(data)
199 +
200 + info._duration_raw = info.duration
201 + info._duration_hms = info.duration
202 + ? hms.fromS(info.duration, 'hh:mm:ss')
203 + : info.duration
204 + info.duration = info.duration ? formatDuration(info.duration) : info.duration
205 +
206 + return info
207 +}
208 +
209 +/**
210 + * Set path from youtube-dl.
211 + *
212 + * @param {String} path
213 + */
214 +ytdl.setYtdlBinary = function setYtdlBinary (path) {
215 + ytdlBinary = path
216 +}
217 +
218 +/**
219 + * Get path from youtube-dl.
220 + *
221 + * @param {String} path
222 + */
223 +ytdl.getYtdlBinary = function getYtdlBinary () {
224 + return ytdlBinary
225 +}
226 +
227 +/**
228 + * Gets info from a video.
229 + *
230 + * @param {String} url
231 + * @param {Array.<String>} args
232 + * @param {Object} options
233 + * @param {Function(!Error, Object)} cb
234 + */
235 +ytdl.getInfo = function getInfo (url, args, options, cb) {
236 + if (typeof options === 'function') {
237 + cb = options
238 + options = {}
239 + } else if (typeof args === 'function') {
240 + cb = args
241 + options = {}
242 + args = []
243 + }
244 + const defaultArgs = ['--dump-json']
245 + if (
246 + !args ||
247 + (!has(args, '-f') &&
248 + !has(args, '--format') &&
249 + args.every(function (a) {
250 + return a.indexOf('--format=') !== 0
251 + }))
252 + ) {
253 + defaultArgs.push('-f')
254 + defaultArgs.push('best')
255 + }
256 +
257 + call(url, defaultArgs, args, options, function done (err, data) {
258 + if (err) return cb(err)
259 + let info
260 +
261 + // If using the "-g" or "--get-url" flag youtube-dl will return just a string (the URL to the video) which messes up the parsing
262 + // This fixes this behaviour
263 + if (has(args, '-g') || has(args, '--get-url')) {
264 + if (Array.isArray(data) && data.length >= 2) data.splice(0, 1)
265 + }
266 +
267 + try {
268 + info = data.map(parseInfo)
269 + } catch (err) {
270 + return cb(err)
271 + }
272 +
273 + return cb(null, info.length === 1 ? info[0] : info)
274 + })
275 +}
276 +
277 +/**
278 + * @param {String} url
279 + * @param {Object} options
280 + * {Boolean} auto
281 + * {Boolean} all
282 + * {String} lang
283 + * {String} format
284 + * {String} cwd
285 + * @param {Function(!Error, Object)} cb
286 + */
287 +ytdl.getSubs = function getSubs (url, options, cb) {
288 + if (typeof options === 'function') {
289 + cb = options
290 + options = {}
291 + }
292 +
293 + const args = ['--skip-download']
294 + args.push('--write' + (options.auto ? '-auto' : '') + '-sub')
295 + if (options.all) args.push('--all-subs')
296 + if (options.lang) args.push('--sub-lang=' + options.lang)
297 + if (options.format) args.push('--sub-format=' + options.format)
298 + if (!options.warrning) args.push('--no-warnings')
299 +
300 + call(url, args, [], { cwd: options.cwd }, function (err, data) {
301 + if (err) return cb(err)
302 +
303 + const files = []
304 +
305 + for (let i = 0, len = data.length; i < len; i++) {
306 + const line = data[i]
307 + if (line.indexOf('[info] Writing video subtitles to: ') === 0) {
308 + files.push(line.slice(35))
309 + }
310 + }
311 +
312 + return cb(null, files)
313 + })
314 +}
315 +
316 +/**
317 + * @param {String} url
318 + * @param {Object} options
319 + * {Boolean} all
320 + * {String} cwd
321 + * @param {Function(!Error, Object)} cb
322 + */
323 +ytdl.getThumbs = function getThumbs (url, options, cb) {
324 + if (typeof options === 'function') {
325 + cb = options
326 + options = {}
327 + }
328 +
329 + const args = ['--skip-download']
330 +
331 + if (options.all) args.push('--write-all-thumbnails')
332 + else args.push('--write-thumbnail')
333 +
334 + if (!options.warrning) args.push('--no-warnings')
335 +
336 + call(url, args, [], { cwd: options.cwd }, function (err, data) {
337 + if (err) return cb(err)
338 +
339 + const files = []
340 +
341 + for (let i = 0, len = data.length; i < len; i++) {
342 + const line = data[i]
343 + const info = 'Writing thumbnail to: '
344 + if (has(line, info)) {
345 + files.push(line.slice(line.indexOf(info) + info.length))
346 + }
347 + }
348 +
349 + return cb(null, files)
350 + })
351 +}
352 +
353 +/**
354 + * @param {!Boolean} descriptions
355 + * @param {!Object} options
356 + * @param {Function(!Error, Object)} cb
357 + */
358 +ytdl.getExtractors = function getExtractors (descriptions, options, cb) {
359 + if (typeof options === 'function') {
360 + cb = options
361 + options = {}
362 + } else if (typeof descriptions === 'function') {
363 + cb = descriptions
364 + options = {}
365 + descriptions = false
366 + }
367 +
368 + const args = descriptions
369 + ? ['--extractor-descriptions']
370 + : ['--list-extractors']
371 +
372 + return call(null, args, null, options, cb)
373 +}
1 +{
2 + "_from": "@microlink/youtube-dl",
3 + "_id": "@microlink/youtube-dl@2.0.0",
4 + "_inBundle": false,
5 + "_integrity": "sha512-B2DqRrDHFMu1MsBTq6ZAKR4BtKgvOK91Ci9EQiMVbSGC1/3UIPxpIYP4Py4kzcS94B++zVSMirhnCgX//5Qs4w==",
6 + "_location": "/@microlink/youtube-dl",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "tag",
10 + "registry": true,
11 + "raw": "@microlink/youtube-dl",
12 + "name": "@microlink/youtube-dl",
13 + "escapedName": "@microlink%2fyoutube-dl",
14 + "scope": "@microlink",
15 + "rawSpec": "",
16 + "saveSpec": null,
17 + "fetchSpec": "latest"
18 + },
19 + "_requiredBy": [
20 + "#USER",
21 + "/"
22 + ],
23 + "_resolved": "https://registry.npmjs.org/@microlink/youtube-dl/-/youtube-dl-2.0.0.tgz",
24 + "_shasum": "0120c67949185228afe4d771cfd80719b278cd73",
25 + "_spec": "@microlink/youtube-dl",
26 + "_where": "C:\\Users\\user\\Desktop\\오소git\\오소플젝\\Youtube_MPL",
27 + "author": {
28 + "name": "Roly Fentanes",
29 + "url": "https://github.com/fent"
30 + },
31 + "bugs": {
32 + "url": "https://github.com/przemyslawpluta/node-youtube-dl/issues"
33 + },
34 + "bundleDependencies": false,
35 + "commitlint": {
36 + "extends": [
37 + "@commitlint/config-conventional"
38 + ]
39 + },
40 + "contributors": [
41 + {
42 + "name": "Roly Fentanes",
43 + "email": "roly426@gmail.com"
44 + },
45 + {
46 + "name": "przemyslawpluta",
47 + "email": "przemekpluta@hotmail.com"
48 + },
49 + {
50 + "name": "Kiko Beats",
51 + "email": "josefrancisco.verdu@gmail.com"
52 + },
53 + {
54 + "name": "Jay Salvat",
55 + "email": "jay@jaysalvat.com"
56 + },
57 + {
58 + "name": "Benjamin C",
59 + "email": "benjamin@coriou.net"
60 + },
61 + {
62 + "name": "Gregoire Guémas",
63 + "email": "gregoire.guemas@navispeed.eu"
64 + },
65 + {
66 + "name": "Jaime Marquínez Ferrándiz",
67 + "email": "jaime.marquinez.ferrandiz@gmail.com"
68 + },
69 + {
70 + "name": "Jay Baker",
71 + "email": "logikal@gmail.com"
72 + },
73 + {
74 + "name": "Jack Li",
75 + "email": "jack.lee2980@gmail.com"
76 + },
77 + {
78 + "name": "optikfluffel",
79 + "email": "optik@fluffel.io"
80 + },
81 + {
82 + "name": "Calvin",
83 + "email": "calvin@sealtelecom.com.br"
84 + },
85 + {
86 + "name": "Jeremy Louie",
87 + "email": "jeremy@jeremylouie.com"
88 + },
89 + {
90 + "name": "Sergey M․",
91 + "email": "dstftw@gmail.com"
92 + },
93 + {
94 + "name": "t3rr0r",
95 + "email": "mail@t3rr0r.com"
96 + },
97 + {
98 + "name": "EragonJ",
99 + "email": "eragonj@eragonj.me"
100 + },
101 + {
102 + "name": "tifroz",
103 + "email": "hhardel@gmail.com"
104 + },
105 + {
106 + "name": "walheresq",
107 + "email": "walheresq@hotmail.com"
108 + },
109 + {
110 + "name": "Alireza Mirian",
111 + "email": "alireza.mirian@gmail.com"
112 + },
113 + {
114 + "name": "▟ ▖▟ ▖",
115 + "email": "dodo.the.last@gmail.com"
116 + },
117 + {
118 + "name": "Davide Pastore",
119 + "email": "pasdavide@gmail.com"
120 + },
121 + {
122 + "name": "Farrin Reid",
123 + "email": "blakmatrix@gmail.com"
124 + },
125 + {
126 + "name": "Jason Penny",
127 + "email": "jason@jooraccess.com"
128 + },
129 + {
130 + "name": "Juan C. Olivares",
131 + "email": "cristobal@cxsoftware.com"
132 + },
133 + {
134 + "name": "Lopez Hugo",
135 + "email": "hugo.lpz@gmail.com"
136 + },
137 + {
138 + "name": "Meral",
139 + "email": "meral.harbes@gmail.com"
140 + },
141 + {
142 + "name": "Michael Nguyen",
143 + "email": "tehtotalpwnage@gmail.com"
144 + },
145 + {
146 + "name": "Nicolas Gotchac",
147 + "email": "ngotchac@gmail.com"
148 + },
149 + {
150 + "name": "Parikshit Hooda",
151 + "email": "phooda804@live.com"
152 + },
153 + {
154 + "name": "Pietro",
155 + "email": "pietro.passarelli@gmail.com"
156 + },
157 + {
158 + "name": "Sagi Nadir",
159 + "email": "saginadir@gmail.com"
160 + },
161 + {
162 + "name": "bartronicus",
163 + "email": "matthewdavidbarton@gmail.com"
164 + },
165 + {
166 + "name": "btmdave",
167 + "email": "dave@bluetopmedia.com"
168 + },
169 + {
170 + "name": "coderaiser",
171 + "email": "mnemonic.enemy@gmail.com"
172 + }
173 + ],
174 + "dependencies": {
175 + "hh-mm-ss": "~1.2.0",
176 + "mkdirp": "~0.5.1",
177 + "request": "~2.88.0",
178 + "streamify": "~0.2.9"
179 + },
180 + "deprecated": false,
181 + "description": "youtube-dl driver for node",
182 + "devDependencies": {
183 + "@commitlint/cli": "latest",
184 + "@commitlint/config-conventional": "latest",
185 + "finepack": "latest",
186 + "git-authors-cli": "latest",
187 + "husky": "latest",
188 + "lint-staged": "latest",
189 + "prettier-standard": "latest",
190 + "standard": "latest",
191 + "standard-markdown": "latest",
192 + "standard-version": "latest",
193 + "vows": "latest"
194 + },
195 + "engines": {
196 + "node": ">= 8"
197 + },
198 + "files": [
199 + "lib",
200 + "scripts"
201 + ],
202 + "homepage": "https://github.com/przemyslawpluta/node-youtube-dl#readme",
203 + "husky": {
204 + "hooks": {
205 + "commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
206 + "pre-commit": "lint-staged"
207 + }
208 + },
209 + "keywords": [
210 + "download",
211 + "video",
212 + "youtube"
213 + ],
214 + "license": "MIT",
215 + "lint-staged": {
216 + "linters": {
217 + "package.json": [
218 + "finepack",
219 + "git add"
220 + ],
221 + "*.js": [
222 + "prettier-standard",
223 + "git add"
224 + ],
225 + "*.md": [
226 + "standard-markdown",
227 + "git add"
228 + ]
229 + }
230 + },
231 + "main": "./lib/youtube-dl.js",
232 + "name": "@microlink/youtube-dl",
233 + "repository": {
234 + "type": "git",
235 + "url": "git://github.com/przemyslawpluta/node-youtube-dl.git"
236 + },
237 + "scripts": {
238 + "lint": "standard-markdown README.md && standard",
239 + "postinstall": "node ./scripts/download.js",
240 + "release": "bumped release",
241 + "test": "vows ./test/*.js --spec",
242 + "update": "node ./scripts/download.js"
243 + },
244 + "version": "2.0.0"
245 +}
1 +var downloader = require('../lib/downloader')
2 +
3 +downloader(function error (err, done) {
4 + if (err) return console.log(err.stack)
5 + console.log(done)
6 +})
1 +Hashish
2 +=======
3 +
4 +Hashish is a node.js library for manipulating hash data structures.
5 +It is distilled from the finest that ruby, perl, and haskell have to offer by
6 +way of hash/map interfaces.
7 +
8 +Hashish provides a chaining interface, where you can do:
9 +
10 + var Hash = require('hashish');
11 +
12 + Hash({ a : 1, b : 2, c : 3, d : 4 })
13 + .map(function (x) { return x * 10 })
14 + .filter(function (x) { return x < 30 })
15 + .forEach(function (x, key) {
16 + console.log(key + ' => ' + x);
17 + })
18 + ;
19 +
20 +Output:
21 +
22 + a => 10
23 + b => 20
24 +
25 +Some functions and attributes in the chaining interface are terminal, like
26 +`.items` or `.detect()`. They return values of their own instead of the chain
27 +context.
28 +
29 +Each function in the chainable interface is also attached to `Hash` in chainless
30 +form:
31 +
32 + var Hash = require('hashish');
33 + var obj = { a : 1, b : 2, c : 3, d : 4 };
34 +
35 + var mapped = Hash.map(obj, function (x) {
36 + return x * 10
37 + });
38 +
39 + console.dir(mapped);
40 +
41 +Output:
42 +
43 + { a: 10, b: 20, c: 30, d: 40 }
44 +
45 +In either case, the 'this' context of the function calls is the same object that
46 +the chained functions return, so you can make nested chains.
47 +
48 +Methods
49 +=======
50 +
51 +forEach(cb)
52 +-----------
53 +
54 +For each key/value in the hash, calls `cb(value, key)`.
55 +
56 +map(cb)
57 +-------
58 +
59 +For each key/value in the hash, calls `cb(value, key)`.
60 +The return value of `cb` is the new value at `key` in the resulting hash.
61 +
62 +filter(cb)
63 +----------
64 +
65 +For each key/value in the hash, calls `cb(value, key)`.
66 +The resulting hash omits key/value pairs where `cb` returned a falsy value.
67 +
68 +detect(cb)
69 +----------
70 +
71 +Returns the first value in the hash for which `cb(value, key)` is non-falsy.
72 +Order of hashes is not well-defined so watch out for that.
73 +
74 +reduce(cb)
75 +----------
76 +
77 +Returns the accumulated value of a left-fold over the key/value pairs.
78 +
79 +some(cb)
80 +--------
81 +
82 +Returns a boolean: whether or not `cb(value, key)` ever returned a non-falsy
83 +value.
84 +
85 +update(obj1, [obj2, obj3, ...])
86 +-----------
87 +
88 +Mutate the context hash, merging the key/value pairs from the passed objects
89 +and overwriting keys from the context hash if the current `obj` has keys of
90 +the same name. Falsy arguments are silently ignored.
91 +
92 +updateAll([ obj1, obj2, ... ])
93 +------------------------------
94 +
95 +Like multi-argument `update()` but operate on an array directly.
96 +
97 +merge(obj1, [obj2, obj3, ...])
98 +----------
99 +
100 +Merge the key/value pairs from the passed objects into the resultant hash
101 +without modifying the context hash. Falsy arguments are silently ignored.
102 +
103 +mergeAll([ obj1, obj2, ... ])
104 +------------------------------
105 +
106 +Like multi-argument `merge()` but operate on an array directly.
107 +
108 +has(key)
109 +--------
110 +
111 +Return whether the hash has a key, `key`.
112 +
113 +valuesAt(keys)
114 +--------------
115 +
116 +Return an Array with the values at the keys from `keys`.
117 +
118 +tap(cb)
119 +-------
120 +
121 +Call `cb` with the present raw hash.
122 +This function is chainable.
123 +
124 +extract(keys)
125 +-------------
126 +
127 +Filter by including only those keys in `keys` in the resulting hash.
128 +
129 +exclude(keys)
130 +-------------
131 +
132 +Filter by excluding those keys in `keys` in the resulting hash.
133 +
134 +Attributes
135 +==========
136 +
137 +These are attributes in the chaining interface and functions in the `Hash.xxx`
138 +interface.
139 +
140 +keys
141 +----
142 +
143 +Return all the enumerable attribute keys in the hash.
144 +
145 +values
146 +------
147 +
148 +Return all the enumerable attribute values in the hash.
149 +
150 +compact
151 +-------
152 +
153 +Filter out values which are `=== undefined`.
154 +
155 +clone
156 +-----
157 +
158 +Make a deep copy of the hash.
159 +
160 +copy
161 +----
162 +
163 +Make a shallow copy of the hash.
164 +
165 +length
166 +------
167 +
168 +Return the number of key/value pairs in the hash.
169 +Note: use `Hash.size()` for non-chain mode.
170 +
171 +size
172 +----
173 +
174 +Alias for `length` since `Hash.length` is masked by `Function.prototype`.
175 +
176 +See Also
177 +========
178 +
179 +See also [creationix's pattern/hash](http://github.com/creationix/pattern),
180 +which does a similar thing except with hash inputs and array outputs.
181 +
182 +Installation
183 +============
184 +
185 +To install with [npm](http://github.com/isaacs/npm):
186 +
187 + npm install hashish
188 +
189 +To run the tests with [expresso](http://github.com/visionmedia/expresso):
190 +
191 + expresso
1 +var Hash = require('hashish');
2 +
3 +Hash({ a : 1, b : 2, c : 3, d : 4 })
4 + .map(function (x) { return x * 10 })
5 + .filter(function (x) { return x < 30 })
6 + .forEach(function (x, key) {
7 + console.log(key + ' => ' + x);
8 + })
9 +;
1 +var Hash = require('hashish');
2 +var obj = { a : 1, b : 2, c : 3, d : 4 };
3 +
4 +var mapped = Hash.map(obj, function (x) {
5 + return x * 10
6 +});
7 +console.dir(mapped);
1 +module.exports = Hash;
2 +var Traverse = require('traverse');
3 +
4 +function Hash (hash, xs) {
5 + if (Array.isArray(hash) && Array.isArray(xs)) {
6 + var to = Math.min(hash.length, xs.length);
7 + var acc = {};
8 + for (var i = 0; i < to; i++) {
9 + acc[hash[i]] = xs[i];
10 + }
11 + return Hash(acc);
12 + }
13 +
14 + if (hash === undefined) return Hash({});
15 +
16 + var self = {
17 + map : function (f) {
18 + var acc = { __proto__ : hash.__proto__ };
19 + Object.keys(hash).forEach(function (key) {
20 + acc[key] = f.call(self, hash[key], key);
21 + });
22 + return Hash(acc);
23 + },
24 + forEach : function (f) {
25 + Object.keys(hash).forEach(function (key) {
26 + f.call(self, hash[key], key);
27 + });
28 + return self;
29 + },
30 + filter : function (f) {
31 + var acc = { __proto__ : hash.__proto__ };
32 + Object.keys(hash).forEach(function (key) {
33 + if (f.call(self, hash[key], key)) {
34 + acc[key] = hash[key];
35 + }
36 + });
37 + return Hash(acc);
38 + },
39 + detect : function (f) {
40 + for (var key in hash) {
41 + if (f.call(self, hash[key], key)) {
42 + return hash[key];
43 + }
44 + }
45 + return undefined;
46 + },
47 + reduce : function (f, acc) {
48 + var keys = Object.keys(hash);
49 + if (acc === undefined) acc = keys.shift();
50 + keys.forEach(function (key) {
51 + acc = f.call(self, acc, hash[key], key);
52 + });
53 + return acc;
54 + },
55 + some : function (f) {
56 + for (var key in hash) {
57 + if (f.call(self, hash[key], key)) return true;
58 + }
59 + return false;
60 + },
61 + update : function (obj) {
62 + if (arguments.length > 1) {
63 + self.updateAll([].slice.call(arguments));
64 + }
65 + else {
66 + Object.keys(obj).forEach(function (key) {
67 + hash[key] = obj[key];
68 + });
69 + }
70 + return self;
71 + },
72 + updateAll : function (xs) {
73 + xs.filter(Boolean).forEach(function (x) {
74 + self.update(x);
75 + });
76 + return self;
77 + },
78 + merge : function (obj) {
79 + if (arguments.length > 1) {
80 + return self.copy.updateAll([].slice.call(arguments));
81 + }
82 + else {
83 + return self.copy.update(obj);
84 + }
85 + },
86 + mergeAll : function (xs) {
87 + return self.copy.updateAll(xs);
88 + },
89 + has : function (key) { // only operates on enumerables
90 + return Array.isArray(key)
91 + ? key.every(function (k) { return self.has(k) })
92 + : self.keys.indexOf(key.toString()) >= 0;
93 + },
94 + valuesAt : function (keys) {
95 + return Array.isArray(keys)
96 + ? keys.map(function (key) { return hash[key] })
97 + : hash[keys]
98 + ;
99 + },
100 + tap : function (f) {
101 + f.call(self, hash);
102 + return self;
103 + },
104 + extract : function (keys) {
105 + var acc = {};
106 + keys.forEach(function (key) {
107 + acc[key] = hash[key];
108 + });
109 + return Hash(acc);
110 + },
111 + exclude : function (keys) {
112 + return self.filter(function (_, key) {
113 + return keys.indexOf(key) < 0
114 + });
115 + },
116 + end : hash,
117 + items : hash
118 + };
119 +
120 + var props = {
121 + keys : function () { return Object.keys(hash) },
122 + values : function () {
123 + return Object.keys(hash).map(function (key) { return hash[key] });
124 + },
125 + compact : function () {
126 + return self.filter(function (x) { return x !== undefined });
127 + },
128 + clone : function () { return Hash(Hash.clone(hash)) },
129 + copy : function () { return Hash(Hash.copy(hash)) },
130 + length : function () { return Object.keys(hash).length },
131 + size : function () { return self.length }
132 + };
133 +
134 + if (Object.defineProperty) {
135 + // es5-shim has an Object.defineProperty but it throws for getters
136 + try {
137 + for (var key in props) {
138 + Object.defineProperty(self, key, { get : props[key] });
139 + }
140 + }
141 + catch (err) {
142 + for (var key in props) {
143 + if (key !== 'clone' && key !== 'copy' && key !== 'compact') {
144 + // ^ those keys use Hash() so can't call them without
145 + // a stack overflow
146 + self[key] = props[key]();
147 + }
148 + }
149 + }
150 + }
151 + else if (self.__defineGetter__) {
152 + for (var key in props) {
153 + self.__defineGetter__(key, props[key]);
154 + }
155 + }
156 + else {
157 + // non-lazy version for browsers that suck >_<
158 + for (var key in props) {
159 + self[key] = props[key]();
160 + }
161 + }
162 +
163 + return self;
164 +};
165 +
166 +// deep copy
167 +Hash.clone = function (ref) {
168 + return Traverse.clone(ref);
169 +};
170 +
171 +// shallow copy
172 +Hash.copy = function (ref) {
173 + var hash = { __proto__ : ref.__proto__ };
174 + Object.keys(ref).forEach(function (key) {
175 + hash[key] = ref[key];
176 + });
177 + return hash;
178 +};
179 +
180 +Hash.map = function (ref, f) {
181 + return Hash(ref).map(f).items;
182 +};
183 +
184 +Hash.forEach = function (ref, f) {
185 + Hash(ref).forEach(f);
186 +};
187 +
188 +Hash.filter = function (ref, f) {
189 + return Hash(ref).filter(f).items;
190 +};
191 +
192 +Hash.detect = function (ref, f) {
193 + return Hash(ref).detect(f);
194 +};
195 +
196 +Hash.reduce = function (ref, f, acc) {
197 + return Hash(ref).reduce(f, acc);
198 +};
199 +
200 +Hash.some = function (ref, f) {
201 + return Hash(ref).some(f);
202 +};
203 +
204 +Hash.update = function (a /*, b, c, ... */) {
205 + var args = Array.prototype.slice.call(arguments, 1);
206 + var hash = Hash(a);
207 + return hash.update.apply(hash, args).items;
208 +};
209 +
210 +Hash.merge = function (a /*, b, c, ... */) {
211 + var args = Array.prototype.slice.call(arguments, 1);
212 + var hash = Hash(a);
213 + return hash.merge.apply(hash, args).items;
214 +};
215 +
216 +Hash.has = function (ref, key) {
217 + return Hash(ref).has(key);
218 +};
219 +
220 +Hash.valuesAt = function (ref, keys) {
221 + return Hash(ref).valuesAt(keys);
222 +};
223 +
224 +Hash.tap = function (ref, f) {
225 + return Hash(ref).tap(f).items;
226 +};
227 +
228 +Hash.extract = function (ref, keys) {
229 + return Hash(ref).extract(keys).items;
230 +};
231 +
232 +Hash.exclude = function (ref, keys) {
233 + return Hash(ref).exclude(keys).items;
234 +};
235 +
236 +Hash.concat = function (xs) {
237 + var hash = Hash({});
238 + xs.forEach(function (x) { hash.update(x) });
239 + return hash.items;
240 +};
241 +
242 +Hash.zip = function (xs, ys) {
243 + return Hash(xs, ys).items;
244 +};
245 +
246 +// .length is already defined for function prototypes
247 +Hash.size = function (ref) {
248 + return Hash(ref).size;
249 +};
250 +
251 +Hash.compact = function (ref) {
252 + return Hash(ref).compact.items;
253 +};
1 +{
2 + "_from": "hashish@~0.0.4",
3 + "_id": "hashish@0.0.4",
4 + "_inBundle": false,
5 + "_integrity": "sha1-bWC8b/r3Ebav1g5CbQd5iAFOZVQ=",
6 + "_location": "/hashish",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "range",
10 + "registry": true,
11 + "raw": "hashish@~0.0.4",
12 + "name": "hashish",
13 + "escapedName": "hashish",
14 + "rawSpec": "~0.0.4",
15 + "saveSpec": null,
16 + "fetchSpec": "~0.0.4"
17 + },
18 + "_requiredBy": [
19 + "/streamify"
20 + ],
21 + "_resolved": "https://registry.npmjs.org/hashish/-/hashish-0.0.4.tgz",
22 + "_shasum": "6d60bc6ffaf711b6afd60e426d077988014e6554",
23 + "_spec": "hashish@~0.0.4",
24 + "_where": "C:\\Users\\user\\Desktop\\오소git\\오소플젝\\Youtube_MPL\\node_modules\\streamify",
25 + "author": {
26 + "name": "James Halliday",
27 + "email": "mail@substack.net",
28 + "url": "http://substack.net"
29 + },
30 + "bugs": {
31 + "url": "https://github.com/substack/node-hashish/issues"
32 + },
33 + "bundleDependencies": false,
34 + "dependencies": {
35 + "traverse": ">=0.2.4"
36 + },
37 + "deprecated": false,
38 + "description": "Hash data structure manipulation functions",
39 + "devDependencies": {
40 + "expresso": ">=0.6.0"
41 + },
42 + "engine": [
43 + "node >=0.2.0"
44 + ],
45 + "engines": {
46 + "node": "*"
47 + },
48 + "homepage": "https://github.com/substack/node-hashish#readme",
49 + "keywords": [
50 + "hash",
51 + "object",
52 + "convenience",
53 + "manipulation",
54 + "data structure"
55 + ],
56 + "license": "MIT/X11",
57 + "main": "./index.js",
58 + "name": "hashish",
59 + "repository": {
60 + "type": "git",
61 + "url": "git+ssh://git@github.com/substack/node-hashish.git"
62 + },
63 + "scripts": {
64 + "test": "expresso"
65 + },
66 + "version": "0.0.4"
67 +}
1 +var Hash = require('hashish');
2 +var assert = require('assert');
3 +
4 +exports.map = function () {
5 + var ref = { a : 1, b : 2 };
6 + var items = Hash(ref).map(function (v) { return v + 1 }).items;
7 + var hash = Hash.map(ref, function (v) { return v + 1 });
8 + assert.deepEqual(ref, { a : 1, b : 2 });
9 + assert.deepEqual(items, { a : 2, b : 3 });
10 + assert.deepEqual(hash, { a : 2, b : 3 });
11 +};
12 +
13 +exports['cloned map'] = function () {
14 + var ref = { foo : [1,2], bar : [4,5] };
15 + var hash = Hash(ref).clone.map(
16 + function (v) { v.unshift(v[0] - 1); return v }
17 + ).items;
18 + assert.deepEqual(ref.foo, [1,2]);
19 + assert.deepEqual(ref.bar, [4,5]);
20 + assert.deepEqual(hash.foo, [0,1,2]);
21 + assert.deepEqual(hash.bar, [3,4,5]);
22 +};
23 +
24 +exports.forEach = function () {
25 + var ref = { a : 5, b : 2, c : 7, 1337 : 'leet' };
26 + var xs = [];
27 + Hash(ref).forEach(function (x, i) {
28 + xs.push([ i, x ]);
29 + });
30 +
31 + assert.eql(
32 + xs.map(function (x) { return x[0] }).sort(),
33 + [ '1337', 'a', 'b', 'c' ]
34 + );
35 +
36 + assert.eql(
37 + xs.map(function (x) { return x[1] }).sort(),
38 + [ 2, 5, 7, 'leet' ]
39 + );
40 +
41 + var ys = [];
42 + Hash.forEach(ref, function (x, i) {
43 + ys.push([ i, x ]);
44 + });
45 +
46 + assert.eql(xs.sort(), ys.sort());
47 +};
48 +
49 +exports.filter_items = function () {
50 + var ref = { a : 5, b : 2, c : 7, 1337 : 'leet' };
51 + var items = Hash(ref).filter(function (v, k) {
52 + return v > 5 || k > 5
53 + }).items;
54 + var hash = Hash.filter(ref, function (v, k) { return v > 5 || k > 5 });
55 + assert.deepEqual(items, { 1337 : 'leet', c : 7 });
56 + assert.deepEqual(hash, { 1337 : 'leet', c : 7 });
57 + assert.deepEqual(ref, { a : 5, b : 2, c : 7, 1337 : 'leet' });
58 + assert.equal(Hash(ref).length, 4);
59 +};
60 +
61 +exports.detect = function () {
62 + var h = { a : 5, b : 6, c : 7, d : 8 };
63 + var hh = Hash(h);
64 + var gt6hh = hh.detect(function (x) { return x > 6 });
65 + assert.ok(gt6hh == 7 || gt6hh == 8);
66 + var gt6h = Hash.detect(h, function (x) { return x > 6 });
67 + assert.ok(gt6h == 7 || gt6h == 8);
68 + assert.equal(hh.detect(function (x) { return x > 100 }), undefined);
69 +};
70 +
71 +exports.reduce = function () {
72 + var ref = { foo : [1,2], bar : [4,5] };
73 +
74 + var sum1 = Hash(ref).reduce(function (acc, v) {
75 + return acc + v.length
76 + }, 0);
77 + assert.equal(sum1, 4);
78 +
79 + var sum2 = Hash.reduce(ref, function (acc, v) {
80 + return acc + v.length
81 + }, 0);
82 + assert.equal(sum2, 4);
83 +};
84 +
85 +exports.some = function () {
86 + var h = { a : 5, b : 6, c : 7, d : 8 };
87 + var hh = Hash(h);
88 + assert.ok(Hash.some(h, function (x) { return x > 7 }));
89 + assert.ok(Hash.some(h, function (x) { return x < 6 }));
90 + assert.ok(!Hash.some(h, function (x) { return x > 10 }));
91 + assert.ok(!Hash.some(h, function (x) { return x < 0 }));
92 +
93 + assert.ok(hh.some(function (x) { return x > 7 }));
94 + assert.ok(hh.some(function (x) { return x < 6 }));
95 + assert.ok(!hh.some(function (x) { return x > 10 }));
96 + assert.ok(!hh.some(function (x) { return x < 0 }));
97 +};
98 +
99 +exports.update = function () {
100 + var ref = { a : 1, b : 2 };
101 + var items = Hash(ref).clone.update({ c : 3, a : 0 }).items;
102 + assert.deepEqual(ref, { a : 1, b : 2 });
103 + assert.deepEqual(items, { a : 0, b : 2, c : 3 });
104 +
105 + var hash = Hash.update(ref, { c : 3, a : 0 });
106 + assert.deepEqual(ref, hash);
107 + assert.deepEqual(hash, { a : 0, b : 2, c : 3 });
108 +
109 + var ref2 = {a: 1};
110 + var hash2 = Hash.update(ref2, { b: 2, c: 3 }, undefined, { d: 4 });
111 + assert.deepEqual(ref2, { a: 1, b: 2, c: 3, d: 4 });
112 +};
113 +
114 +exports.merge = function () {
115 + var ref = { a : 1, b : 2 };
116 + var items = Hash(ref).merge({ b : 3, c : 3.14 }).items;
117 + var hash = Hash.merge(ref, { b : 3, c : 3.14 });
118 +
119 + assert.deepEqual(ref, { a : 1, b : 2 });
120 + assert.deepEqual(items, { a : 1, b : 3, c : 3.14 });
121 + assert.deepEqual(hash, { a : 1, b : 3, c : 3.14 });
122 +
123 + var ref2 = { a : 1 };
124 + var hash2 = Hash.merge(ref, { b: 2, c: 3 }, undefined, { d: 4 });
125 + assert.deepEqual(hash2, { a: 1, b: 2, c: 3, d: 4 });
126 +};
127 +
128 +exports.has = function () {
129 + var h = { a : 4, b : 5 };
130 + var hh = Hash(h);
131 +
132 + assert.ok(hh.has('a'));
133 + assert.equal(hh.has('c'), false);
134 + assert.ok(hh.has(['a','b']));
135 + assert.equal(hh.has(['a','b','c']), false);
136 +
137 + assert.ok(Hash.has(h, 'a'));
138 + assert.equal(Hash.has(h, 'c'), false);
139 + assert.ok(Hash.has(h, ['a','b']));
140 + assert.equal(Hash.has(h, ['a','b','c']), false);
141 +};
142 +
143 +exports.valuesAt = function () {
144 + var h = { a : 4, b : 5, c : 6 };
145 + assert.equal(Hash(h).valuesAt('a'), 4);
146 + assert.equal(Hash(h).valuesAt(['a'])[0], 4);
147 + assert.deepEqual(Hash(h).valuesAt(['a','b']), [4,5]);
148 + assert.equal(Hash.valuesAt(h, 'a'), 4);
149 + assert.deepEqual(Hash.valuesAt(h, ['a']), [4]);
150 + assert.deepEqual(Hash.valuesAt(h, ['a','b']), [4,5]);
151 +};
152 +
153 +exports.tap = function () {
154 + var h = { a : 4, b : 5, c : 6 };
155 + var hh = Hash(h);
156 + hh.tap(function (x) {
157 + assert.ok(this === hh)
158 + assert.eql(x, h);
159 + });
160 +
161 + Hash.tap(h, function (x) {
162 + assert.eql(
163 + Object.keys(this).sort(),
164 + Object.keys(hh).sort()
165 + );
166 + assert.eql(x, h);
167 + });
168 +};
169 +
170 +exports.extract = function () {
171 + var hash = Hash({ a : 1, b : 2, c : 3 }).clone;
172 + var extracted = hash.extract(['a','b']);
173 + assert.equal(extracted.length, 2);
174 + assert.deepEqual(extracted.items, { a : 1, b : 2 });
175 +};
176 +
177 +exports.exclude = function () {
178 + var hash = Hash({ a : 1, b : 2, c : 3 }).clone;
179 + var extracted = hash.exclude(['a','b']);
180 + assert.equal(extracted.length, 1);
181 + assert.deepEqual(extracted.items, { c : 3 });
182 +};
183 +
184 +exports.concat = function () {
185 + var ref1 = { a : 1, b : 2 };
186 + var ref2 = { foo : 100, bar : 200 };
187 + var ref3 = { b : 3, c : 4, bar : 300 };
188 +
189 + assert.deepEqual(
190 + Hash.concat([ ref1, ref2 ]),
191 + { a : 1, b : 2, foo : 100, bar : 200 }
192 + );
193 +
194 + assert.deepEqual(
195 + Hash.concat([ ref1, ref2, ref3 ]),
196 + { a : 1, b : 3, c : 4, foo : 100, bar : 300 }
197 + );
198 +};
199 +
200 +exports.zip = function () {
201 + var xs = ['a','b','c'];
202 + var ys = [1,2,3,4];
203 + var h = Hash(xs,ys);
204 + assert.equal(h.length, 3);
205 + assert.deepEqual(h.items, { a : 1, b : 2, c : 3 });
206 +
207 + var zipped = Hash.zip(xs,ys);
208 + assert.deepEqual(zipped, { a : 1, b : 2, c : 3 });
209 +};
210 +
211 +exports.length = function () {
212 + assert.equal(Hash({ a : 1, b : [2,3], c : 4 }).length, 3);
213 + assert.equal(Hash({ a : 1, b : [2,3], c : 4 }).size, 3);
214 + assert.equal(Hash.size({ a : 1, b : [2,3], c : 4 }), 3);
215 +};
216 +
217 +exports.compact = function () {
218 + var hash = {
219 + a : 1,
220 + b : undefined,
221 + c : false,
222 + d : 4,
223 + e : [ undefined, 4 ],
224 + f : null
225 + };
226 + var compacted = Hash(hash).compact;
227 + assert.deepEqual(
228 + {
229 + a : 1,
230 + b : undefined,
231 + c : false,
232 + d : 4,
233 + e : [ undefined, 4 ],
234 + f : null
235 + },
236 + hash, 'compact modified the hash'
237 + );
238 + assert.deepEqual(
239 + compacted.items,
240 + {
241 + a : 1,
242 + c : false,
243 + d : 4,
244 + e : [ undefined, 4 ],
245 + f : null
246 + }
247 + );
248 + var h = Hash.compact(hash);
249 + assert.deepEqual(h, compacted.items);
250 +};
1 +var Hash = require('hashish');
2 +var assert = require('assert');
3 +var vm = require('vm');
4 +var fs = require('fs');
5 +
6 +var src = fs.readFileSync(__dirname + '/../index.js', 'utf8');
7 +
8 +exports.defineGetter = function () {
9 + var context = {
10 + module : { exports : {} },
11 + Object : {
12 + keys : Object.keys,
13 + defineProperty : undefined,
14 + },
15 + require : require,
16 + };
17 + context.exports = context.module.exports;
18 +
19 + vm.runInNewContext('(function () {' + src + '})()', context);
20 + var Hash_ = context.module.exports;
21 +
22 + var times = 0;
23 + Hash_.__proto__.__proto__.__defineGetter__ = function () {
24 + times ++;
25 + return Object.__defineGetter__.apply(this, arguments);
26 + };
27 +
28 + assert.equal(vm.runInNewContext('Object.defineProperty', context), null);
29 +
30 + assert.deepEqual(
31 + Hash_({ a : 1, b : 2, c : 3 }).values,
32 + [ 1, 2, 3 ]
33 + );
34 +
35 + assert.ok(times > 5);
36 +};
37 +
38 +exports.defineProperty = function () {
39 + var times = 0;
40 + var context = {
41 + module : { exports : {} },
42 + Object : {
43 + keys : Object.keys,
44 + defineProperty : function (prop) {
45 + times ++;
46 + if (prop.get) throw new TypeError('engine does not support')
47 + assert.fail('should have asserted by now');
48 + },
49 + },
50 + require : require
51 + };
52 + context.exports = context.module.exports;
53 +
54 + vm.runInNewContext('(function () {' + src + '})()', context);
55 + var Hash_ = context.module.exports;
56 +
57 + Hash_.__proto__.__proto__.__defineGetter__ = function () {
58 + assert.fail('getter called when a perfectly good'
59 + + ' defineProperty was available'
60 + );
61 + };
62 +
63 + assert.deepEqual(
64 + Hash_({ a : 1, b : 2, c : 3 }).values,
65 + [ 1, 2, 3 ]
66 + );
67 +
68 + assert.equal(times, 1);
69 +};
1 +language: node_js
2 +node_js:
3 + - 'node'
1 +The MIT License (MIT)
2 +
3 +Copyright (c) Adam Gotlib
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy of
6 +this software and associated documentation files (the "Software"), to deal in
7 +the Software without restriction, including without limitation the rights to
8 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 +the Software, and to permit persons to whom the Software is furnished to do so,
10 +subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in all
13 +copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1 +# hh-mm-ss: time formatting utility
2 +[![Build Status](https://travis-ci.org/Goldob/hh-mm-ss.svg?branch=master)](https://travis-ci.org/Goldob/hh-mm-ss)
3 +[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
4 +
5 +
6 +:watch: Convert seconds or miliseconds to `hh:mm:ss` format and vice versa.
7 +
8 +```js
9 +var TimeFormat = require('hh-mm-ss')
10 +
11 +TimeFormat.toS('137:00:00') // 493200
12 +TimeFormat.toS('02:00') // 120
13 +TimeFormat.toS('02:00', 'hh:mm') // 7200
14 +
15 +TimeFormat.fromS(194) // '03:14'
16 +TimeFormat.fromS(150, 'hh:mm:ss') // '00:02:30'
17 +TimeFormat.fromS(8100, 'hh:mm') // '02:15'
18 +
19 +TimeFormat.fromMs(12345) // '00:12.345'
20 +```
21 +
22 +## Usage
23 +
24 +### `toMs(time, format)`
25 +
26 +Convert given `hh:mm:ss` formatted string to miliseconds
27 +
28 +#### Parameters
29 +- `time` String representation
30 +- `format` _(optional)_ Default input format. If present, it will be used to resolve amiguities during interpretation. If not specified, `mm:ss` is implied. See section below for supported format list
31 +
32 +### `toS(time, format)`
33 +
34 +Convert given `hh:mm:ss` formatted string to seconds
35 +
36 +#### Parameters
37 +- `time` String representation
38 +- `format` _(optional)_ Default input format. If present, it will be used to resolve amiguities during interpretation. If not specified, `mm:ss` is implied. See section below for supported format list
39 +
40 +### `fromMs(ms, format)`
41 +
42 +Generate formatted string from time in miliseconds
43 +
44 +#### Parameters
45 +- `ms` Time in miliseconds
46 +- `format` _(optional)_ Default output format. If not specified, `mm:ss` is implied. See section below for supported format list.
47 +
48 +### `fromS(s, format)`
49 +
50 +Generate formatted string from time in seconds
51 +
52 +#### Parameters
53 +- `s` Time in seconds
54 +- `format` _(optional)_ Default output format. If not specified, `mm:ss` is implied. See section below for supported format list
55 +
56 +### Supported time formats
57 +The following formats are supported: `mm:ss`, `hh:mm`, `hh:mm:ss`, `mm:ss.sss`, `hh:mm:ss.sss`.
58 +
59 +- `hh` - hours
60 +- `mm` - minutes
61 +- `ss` - second
62 +- `sss` - miliseconds
63 +
64 +Specified format constitutes a baseline for corresponding functions, but will be appropriately extended as needed. For example, `fromMs(9000, 'mm:ss')` will return `01:30`, yet `fromMs(9500, 'mm:ss')` will return `01:30.500` to account for the miliseconds part.
65 +
66 +## Install
67 +
68 +`npm install hh-mm-ss --save`
69 +
70 +## License
71 +
72 +MIT
1 +'use strict'
2 +
3 +module.exports = {
4 + fromMs,
5 + fromS,
6 + toMs,
7 + toS
8 +}
9 +
10 +const zeroFill = require('zero-fill')
11 +
12 +// Time units with their corresponding values in miliseconds
13 +const HOUR = 3600000
14 +const MINUTE = 60000
15 +const SECOND = 1000
16 +
17 +const TIME_FORMAT_ERRMSG = 'Time format error'
18 +
19 +// =============================================================================
20 +// Export functions
21 +// =============================================================================
22 +
23 +function fromMs (ms, format = 'mm:ss') {
24 + if (typeof ms !== 'number' || Number.isNaN(ms)) {
25 + throw new Error('NaN error')
26 + }
27 +
28 + let absMs = Math.abs(ms)
29 +
30 + let negative = (ms < 0)
31 + let hours = Math.floor(absMs / HOUR)
32 + let minutes = Math.floor(absMs % HOUR / MINUTE)
33 + let seconds = Math.floor(absMs % MINUTE / SECOND)
34 + let miliseconds = Math.floor(absMs % SECOND)
35 +
36 + return formatTime({
37 + negative, hours, minutes, seconds, miliseconds
38 + }, format)
39 +}
40 +
41 +function fromS (s, format = 'mm:ss') {
42 + if (typeof s !== 'number' || Number.isNaN(s)) {
43 + throw new Error('NaN error')
44 + }
45 +
46 + let ms = s * SECOND
47 +
48 + return fromMs(ms, format)
49 +}
50 +
51 +function toMs (time, format = 'mm:ss') {
52 + let re
53 +
54 + if (['mm:ss', 'mm:ss.sss', 'hh:mm:ss', 'hh:mm:ss.sss'].includes(format)) {
55 + re = /^(-)?(?:(\d\d+):)?(\d\d):(\d\d)(\.\d+)?$/
56 + } else if (format === 'hh:mm') {
57 + re = /^(-)?(\d\d):(\d\d)(?::(\d\d)(?:(\.\d+))?)?$/
58 + } else {
59 + throw new Error(TIME_FORMAT_ERRMSG)
60 + }
61 +
62 + let result = re.exec(time)
63 + if (!result) throw new Error()
64 +
65 + let negative = result[1] === '-'
66 + let hours = result[2] | 0
67 + let minutes = result[3] | 0
68 + let seconds = result[4] | 0
69 + let miliseconds = Math.floor(1000 * result[5] | 0)
70 +
71 + if (minutes > 60 || seconds > 60) {
72 + throw new Error()
73 + }
74 +
75 + return (negative ? -1 : 1) * (
76 + hours * HOUR + minutes * MINUTE + seconds * SECOND + miliseconds
77 + )
78 +}
79 +
80 +function toS (time, format = 'mm:ss') {
81 + let ms = toMs(time, format)
82 + return Math.floor(ms / SECOND)
83 +}
84 +
85 +// =============================================================================
86 +// Utility functions
87 +// =============================================================================
88 +
89 +function formatTime (time, format) {
90 + let showMs
91 + let showSc
92 + let showHr
93 +
94 + switch (format.toLowerCase()) {
95 + case 'hh:mm:ss.sss':
96 + showMs = true
97 + showSc = true
98 + showHr = true
99 + break
100 + case 'hh:mm:ss':
101 + showMs = !(!time.miliseconds)
102 + showSc = true
103 + showHr = true
104 + break
105 + case 'hh:mm':
106 + showMs = !(!time.miliseconds)
107 + showSc = showMs || !(!time.seconds)
108 + showHr = true
109 + break
110 + case 'mm:ss':
111 + showMs = !(!time.miliseconds)
112 + showSc = true
113 + showHr = !(!time.hours)
114 + break
115 + case 'mm:ss.sss':
116 + showMs = true
117 + showSc = true
118 + showHr = !(!time.hours)
119 + break
120 + default:
121 + throw new Error(TIME_FORMAT_ERRMSG)
122 + }
123 +
124 + let hh = zeroFill(2, time.hours)
125 + let mm = zeroFill(2, time.minutes)
126 + let ss = zeroFill(2, time.seconds)
127 + let sss = zeroFill(3, time.miliseconds)
128 +
129 + return (time.negative ? '-' : '') + (showHr ? (
130 + showMs ? `${hh}:${mm}:${ss}.${sss}` : showSc ? `${hh}:${mm}:${ss}` : `${hh}:${mm}`
131 + ) : (
132 + showMs ? `${mm}:${ss}.${sss}` : `${mm}:${ss}`
133 + ))
134 +}
1 +{
2 + "_from": "hh-mm-ss@~1.2.0",
3 + "_id": "hh-mm-ss@1.2.0",
4 + "_inBundle": false,
5 + "_integrity": "sha512-f4I9Hz1dLpX/3mrEs7yq30+FiuO3tt5NWAqAGeBTaoeoBfB8vhcQ3BphuDc5DjZb/K809agqrAaFlP0jhEU/8w==",
6 + "_location": "/hh-mm-ss",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "range",
10 + "registry": true,
11 + "raw": "hh-mm-ss@~1.2.0",
12 + "name": "hh-mm-ss",
13 + "escapedName": "hh-mm-ss",
14 + "rawSpec": "~1.2.0",
15 + "saveSpec": null,
16 + "fetchSpec": "~1.2.0"
17 + },
18 + "_requiredBy": [
19 + "/youtube-dl"
20 + ],
21 + "_resolved": "https://registry.npmjs.org/hh-mm-ss/-/hh-mm-ss-1.2.0.tgz",
22 + "_shasum": "6d0f0b8280824a634cb1d1f20e0bc7bc8b689948",
23 + "_spec": "hh-mm-ss@~1.2.0",
24 + "_where": "C:\\Users\\user\\Desktop\\오소git\\오소플젝\\Youtube_MPL\\node_modules\\youtube-dl",
25 + "author": {
26 + "name": "Adam Gotlib"
27 + },
28 + "bugs": {
29 + "url": "https://github.com/Goldob/hh-mm-ss/issues"
30 + },
31 + "bundleDependencies": false,
32 + "dependencies": {
33 + "zero-fill": "^2.2.3"
34 + },
35 + "deprecated": false,
36 + "description": "Simple hh:mm:ss time formatting utility",
37 + "devDependencies": {
38 + "standard": "^7.1.2",
39 + "tape": "^4.6.0"
40 + },
41 + "homepage": "https://github.com/Goldob/hh-mm-ss#readme",
42 + "keywords": [
43 + "time format",
44 + "hours",
45 + "minutes",
46 + "seconds",
47 + "miliseconds",
48 + "hh:mm:ss"
49 + ],
50 + "license": "MIT",
51 + "main": "index.js",
52 + "name": "hh-mm-ss",
53 + "repository": {
54 + "type": "git",
55 + "url": "git+https://github.com/Goldob/hh-mm-ss.git"
56 + },
57 + "scripts": {
58 + "test": "standard & node test"
59 + },
60 + "version": "1.2.0"
61 +}
1 +'use-strict'
2 +
3 +const test = require('tape')
4 +const {fromMs, fromS, toMs, toS} = require('../')
5 +
6 +// =============================================================================
7 +// Test cases
8 +// =============================================================================
9 +
10 +test('fromMs() test', (t) => {
11 + // Basic functionality
12 + t.equal(fromMs(75000), '01:15')
13 + t.equal(fromMs(442800000), '123:00:00')
14 + t.equal(fromMs(90576), '01:30.576')
15 + t.equal(fromMs(-157250), '-02:37.250')
16 +
17 + // Output formatting
18 + t.equal(fromMs(38000, 'mm:ss.sss'), '00:38.000')
19 + t.equal(fromMs(0, 'hh:mm:ss'), '00:00:00')
20 + t.equal(fromMs(3600000, 'mm:ss'), '01:00:00')
21 + t.equal(fromMs(4500000, 'hh:mm'), '01:15')
22 + t.equal(fromMs(-9900000, 'hh:mm'), '-02:45')
23 +
24 + // Input validation
25 + t.throws(() => fromMs(null))
26 + t.throws(() => fromMs('text'))
27 + t.throws(() => fromMs(0, 'mm:hh:ss'))
28 +
29 + t.end()
30 +})
31 +
32 +test('fromS() test', (t) => {
33 + // Basic functionality
34 + t.equal(fromS(75), '01:15')
35 + t.equal(fromS(442800), '123:00:00')
36 + t.equal(fromS(-442800), '-123:00:00')
37 +
38 + // Output formatting
39 + t.equal(fromS(38, 'mm:ss.sss'), '00:38.000')
40 + t.equal(fromS(0, 'hh:mm:ss'), '00:00:00')
41 + t.equal(fromS(3600, 'mm:ss'), '01:00:00')
42 + t.equal(fromS(4500, 'hh:mm'), '01:15')
43 + t.equal(fromS(-9900, 'hh:mm'), '-02:45')
44 +
45 + // Input validation
46 + t.throws(() => fromS(null))
47 + t.throws(() => fromS('text'))
48 + t.throws(() => fromS(0, 'mm:hh:ss'))
49 +
50 + t.end()
51 +})
52 +
53 +test('toMs() test', (t) => {
54 + // Basic functionality
55 + t.equal(toMs('01:05:17'), 3917000)
56 + t.equal(toMs('137:00:00.0'), 493200000)
57 + t.equal(toMs('00:10.230'), 10230)
58 + t.equal(toMs('00:00:07.10845'), 7108)
59 + t.equal(toMs('-02:07:12'), -7632000)
60 + t.equal(toMs('02:00'), 120000)
61 + t.equal(toMs('02:00', 'hh:mm'), 7200000)
62 + t.equal(toMs('-04:35', 'hh:mm'), -16500000)
63 + t.equal(toMs('00:00:07.10845', 'hh:mm'), 7108)
64 +
65 + // Input validation
66 + t.throws(() => toMs('13:05:02:11'))
67 + t.throws(() => toMs('153'))
68 + t.throws(() => toMs(null))
69 + t.throws(() => toMs('00:62'))
70 + t.throws(() => toS('01:30', 'mm:hh:ss'))
71 +
72 + t.end()
73 +})
74 +
75 +test('toS() test', (t) => {
76 + // Basic functionality
77 + t.equal(toS('01:05:17'), 3917)
78 + t.equal(toS('137:00:00.0'), 493200)
79 + t.equal(toS('00:10.230'), 10)
80 + t.equal(toS('00:00:07.10845'), 7)
81 + t.equal(toS('-02:07:12'), -7632)
82 + t.equal(toS('02:00'), 120)
83 + t.equal(toS('02:00', 'hh:mm'), 7200)
84 + t.equal(toS('-04:35', 'hh:mm'), -16500)
85 + t.equal(toS('00:00:07.10845', 'hh:mm'), 7)
86 +
87 + // Input validation
88 + t.throws(() => toS('13:05:02:11'))
89 + t.throws(() => toS('153'))
90 + t.throws(() => toS(null))
91 + t.throws(() => toS('00:62'))
92 + t.throws(() => toS('01:30', 'mm:hh:ss'))
93 +
94 + t.end()
95 +})
96 +
97 +test('symmetrical conversion test', (t) => {
98 + /*
99 + * fromMs() and toMs() for all formats
100 + */
101 +
102 + // 90000ms = 1m 30s
103 + t.equal(toMs(fromMs(90000, 'mm:ss'), 'mm:ss'), 90000)
104 + t.equal(toMs(fromMs(90000, 'mm:ss.sss'), 'mm:ss.sss'), 90000)
105 + t.equal(toMs(fromMs(90000, 'hh:mm'), 'hh:mm'), 90000)
106 + t.equal(toMs(fromMs(90000, 'hh:mm:ss'), 'hh:mm:ss'), 90000)
107 + t.equal(toMs(fromMs(90000, 'hh:mm:ss.sss'), 'hh:mm:ss.sss'), 90000)
108 +
109 + // 7517245ms = 2h 5m 17.245s
110 + t.equal(toMs(fromMs(7517245, 'mm:ss'), 'mm:ss'), 7517245)
111 + t.equal(toMs(fromMs(7517245, 'mm:ss.sss'), 'mm:ss.sss'), 7517245)
112 + t.equal(toMs(fromMs(7517245, 'hh:mm'), 'hh:mm'), 7517245)
113 + t.equal(toMs(fromMs(7517245, 'hh:mm:ss'), 'hh:mm:ss'), 7517245)
114 + t.equal(toMs(fromMs(7517245, 'hh:mm:ss.sss'), 'hh:mm:ss.sss'), 7517245)
115 +
116 + // -10800000ms = -3h
117 + t.equal(toMs(fromMs(-10800000, 'mm:ss'), 'mm:ss'), -10800000)
118 + t.equal(toMs(fromMs(-10800000, 'mm:ss.sss'), 'mm:ss.sss'), -10800000)
119 + t.equal(toMs(fromMs(-10800000, 'hh:mm'), 'hh:mm'), -10800000)
120 + t.equal(toMs(fromMs(-10800000, 'hh:mm:ss'), 'hh:mm:ss'), -10800000)
121 + t.equal(toMs(fromMs(-10800000, 'hh:mm:ss.sss'), 'hh:mm:ss.sss'), -10800000)
122 +
123 + /*
124 + * fromS() and toMs() for all formats
125 + */
126 +
127 + // 930s = 15m 30s
128 + t.equal(toS(fromS(930, 'mm:ss'), 'mm:ss'), 930)
129 + t.equal(toS(fromS(930, 'mm:ss.sss'), 'mm:ss.sss'), 930)
130 + t.equal(toS(fromS(930, 'hh:mm'), 'hh:mm'), 930)
131 + t.equal(toS(fromS(930, 'hh:mm:ss'), 'hh:mm:ss'), 930)
132 + t.equal(toS(fromS(930, 'hh:mm:ss.sss'), 'hh:mm:ss.sss'), 930)
133 +
134 + // 4850s = 1h 20m 50s
135 + t.equal(toS(fromS(4850, 'mm:ss'), 'mm:ss'), 4850)
136 + t.equal(toS(fromS(4850, 'mm:ss.sss'), 'mm:ss.sss'), 4850)
137 + t.equal(toS(fromS(4850, 'hh:mm'), 'hh:mm'), 4850)
138 + t.equal(toS(fromS(4850, 'hh:mm:ss'), 'hh:mm:ss'), 4850)
139 + t.equal(toS(fromS(4850, 'hh:mm:ss.sss'), 'hh:mm:ss.sss'), 4850)
140 +
141 + // -300s = -5m
142 + t.equal(toS(fromS(-300, 'mm:ss'), 'mm:ss'), -300)
143 + t.equal(toS(fromS(-300, 'mm:ss.sss'), 'mm:ss.sss'), -300)
144 + t.equal(toS(fromS(-300, 'hh:mm'), 'hh:mm'), -300)
145 + t.equal(toS(fromS(-300, 'hh:mm:ss'), 'hh:mm:ss'), -300)
146 + t.equal(toS(fromS(-300, 'hh:mm:ss.sss'), 'hh:mm:ss.sss'), -300)
147 +
148 + t.end()
149 +})
1 +language: node_js
2 +node_js:
3 + - "0.8"
4 + - "0.10"
1 +This software is released under the MIT license:
2 +
3 +Permission is hereby granted, free of charge, to any person obtaining a copy of
4 +this software and associated documentation files (the "Software"), to deal in
5 +the Software without restriction, including without limitation the rights to
6 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7 +the Software, and to permit persons to whom the Software is furnished to do so,
8 +subject to the following conditions:
9 +
10 +The above copyright notice and this permission notice shall be included in all
11 +copies or substantial portions of the Software.
12 +
13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1 +var argv = require('../')(process.argv.slice(2));
2 +console.dir(argv);
1 +module.exports = function (args, opts) {
2 + if (!opts) opts = {};
3 +
4 + var flags = { bools : {}, strings : {} };
5 +
6 + [].concat(opts['boolean']).filter(Boolean).forEach(function (key) {
7 + flags.bools[key] = true;
8 + });
9 +
10 + [].concat(opts.string).filter(Boolean).forEach(function (key) {
11 + flags.strings[key] = true;
12 + });
13 +
14 + var aliases = {};
15 + Object.keys(opts.alias || {}).forEach(function (key) {
16 + aliases[key] = [].concat(opts.alias[key]);
17 + aliases[key].forEach(function (x) {
18 + aliases[x] = [key].concat(aliases[key].filter(function (y) {
19 + return x !== y;
20 + }));
21 + });
22 + });
23 +
24 + var defaults = opts['default'] || {};
25 +
26 + var argv = { _ : [] };
27 + Object.keys(flags.bools).forEach(function (key) {
28 + setArg(key, defaults[key] === undefined ? false : defaults[key]);
29 + });
30 +
31 + var notFlags = [];
32 +
33 + if (args.indexOf('--') !== -1) {
34 + notFlags = args.slice(args.indexOf('--')+1);
35 + args = args.slice(0, args.indexOf('--'));
36 + }
37 +
38 + function setArg (key, val) {
39 + var value = !flags.strings[key] && isNumber(val)
40 + ? Number(val) : val
41 + ;
42 + setKey(argv, key.split('.'), value);
43 +
44 + (aliases[key] || []).forEach(function (x) {
45 + setKey(argv, x.split('.'), value);
46 + });
47 + }
48 +
49 + for (var i = 0; i < args.length; i++) {
50 + var arg = args[i];
51 +
52 + if (/^--.+=/.test(arg)) {
53 + // Using [\s\S] instead of . because js doesn't support the
54 + // 'dotall' regex modifier. See:
55 + // http://stackoverflow.com/a/1068308/13216
56 + var m = arg.match(/^--([^=]+)=([\s\S]*)$/);
57 + setArg(m[1], m[2]);
58 + }
59 + else if (/^--no-.+/.test(arg)) {
60 + var key = arg.match(/^--no-(.+)/)[1];
61 + setArg(key, false);
62 + }
63 + else if (/^--.+/.test(arg)) {
64 + var key = arg.match(/^--(.+)/)[1];
65 + var next = args[i + 1];
66 + if (next !== undefined && !/^-/.test(next)
67 + && !flags.bools[key]
68 + && (aliases[key] ? !flags.bools[aliases[key]] : true)) {
69 + setArg(key, next);
70 + i++;
71 + }
72 + else if (/^(true|false)$/.test(next)) {
73 + setArg(key, next === 'true');
74 + i++;
75 + }
76 + else {
77 + setArg(key, flags.strings[key] ? '' : true);
78 + }
79 + }
80 + else if (/^-[^-]+/.test(arg)) {
81 + var letters = arg.slice(1,-1).split('');
82 +
83 + var broken = false;
84 + for (var j = 0; j < letters.length; j++) {
85 + var next = arg.slice(j+2);
86 +
87 + if (next === '-') {
88 + setArg(letters[j], next)
89 + continue;
90 + }
91 +
92 + if (/[A-Za-z]/.test(letters[j])
93 + && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
94 + setArg(letters[j], next);
95 + broken = true;
96 + break;
97 + }
98 +
99 + if (letters[j+1] && letters[j+1].match(/\W/)) {
100 + setArg(letters[j], arg.slice(j+2));
101 + broken = true;
102 + break;
103 + }
104 + else {
105 + setArg(letters[j], flags.strings[letters[j]] ? '' : true);
106 + }
107 + }
108 +
109 + var key = arg.slice(-1)[0];
110 + if (!broken && key !== '-') {
111 + if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1])
112 + && !flags.bools[key]
113 + && (aliases[key] ? !flags.bools[aliases[key]] : true)) {
114 + setArg(key, args[i+1]);
115 + i++;
116 + }
117 + else if (args[i+1] && /true|false/.test(args[i+1])) {
118 + setArg(key, args[i+1] === 'true');
119 + i++;
120 + }
121 + else {
122 + setArg(key, flags.strings[key] ? '' : true);
123 + }
124 + }
125 + }
126 + else {
127 + argv._.push(
128 + flags.strings['_'] || !isNumber(arg) ? arg : Number(arg)
129 + );
130 + }
131 + }
132 +
133 + Object.keys(defaults).forEach(function (key) {
134 + if (!hasKey(argv, key.split('.'))) {
135 + setKey(argv, key.split('.'), defaults[key]);
136 +
137 + (aliases[key] || []).forEach(function (x) {
138 + setKey(argv, x.split('.'), defaults[key]);
139 + });
140 + }
141 + });
142 +
143 + notFlags.forEach(function(key) {
144 + argv._.push(key);
145 + });
146 +
147 + return argv;
148 +};
149 +
150 +function hasKey (obj, keys) {
151 + var o = obj;
152 + keys.slice(0,-1).forEach(function (key) {
153 + o = (o[key] || {});
154 + });
155 +
156 + var key = keys[keys.length - 1];
157 + return key in o;
158 +}
159 +
160 +function setKey (obj, keys, value) {
161 + var o = obj;
162 + keys.slice(0,-1).forEach(function (key) {
163 + if (o[key] === undefined) o[key] = {};
164 + o = o[key];
165 + });
166 +
167 + var key = keys[keys.length - 1];
168 + if (o[key] === undefined || typeof o[key] === 'boolean') {
169 + o[key] = value;
170 + }
171 + else if (Array.isArray(o[key])) {
172 + o[key].push(value);
173 + }
174 + else {
175 + o[key] = [ o[key], value ];
176 + }
177 +}
178 +
179 +function isNumber (x) {
180 + if (typeof x === 'number') return true;
181 + if (/^0x[0-9a-f]+$/i.test(x)) return true;
182 + return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
183 +}
184 +
185 +function longest (xs) {
186 + return Math.max.apply(null, xs.map(function (x) { return x.length }));
187 +}
1 +{
2 + "_from": "minimist@0.0.8",
3 + "_id": "minimist@0.0.8",
4 + "_inBundle": false,
5 + "_integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
6 + "_location": "/minimist",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "version",
10 + "registry": true,
11 + "raw": "minimist@0.0.8",
12 + "name": "minimist",
13 + "escapedName": "minimist",
14 + "rawSpec": "0.0.8",
15 + "saveSpec": null,
16 + "fetchSpec": "0.0.8"
17 + },
18 + "_requiredBy": [
19 + "/mkdirp"
20 + ],
21 + "_resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
22 + "_shasum": "857fcabfc3397d2625b8228262e86aa7a011b05d",
23 + "_spec": "minimist@0.0.8",
24 + "_where": "C:\\Users\\user\\Desktop\\오소git\\오소플젝\\Youtube_MPL\\node_modules\\mkdirp",
25 + "author": {
26 + "name": "James Halliday",
27 + "email": "mail@substack.net",
28 + "url": "http://substack.net"
29 + },
30 + "bugs": {
31 + "url": "https://github.com/substack/minimist/issues"
32 + },
33 + "bundleDependencies": false,
34 + "deprecated": false,
35 + "description": "parse argument options",
36 + "devDependencies": {
37 + "tap": "~0.4.0",
38 + "tape": "~1.0.4"
39 + },
40 + "homepage": "https://github.com/substack/minimist",
41 + "keywords": [
42 + "argv",
43 + "getopt",
44 + "parser",
45 + "optimist"
46 + ],
47 + "license": "MIT",
48 + "main": "index.js",
49 + "name": "minimist",
50 + "repository": {
51 + "type": "git",
52 + "url": "git://github.com/substack/minimist.git"
53 + },
54 + "scripts": {
55 + "test": "tap test/*.js"
56 + },
57 + "testling": {
58 + "files": "test/*.js",
59 + "browsers": [
60 + "ie/6..latest",
61 + "ff/5",
62 + "firefox/latest",
63 + "chrome/10",
64 + "chrome/latest",
65 + "safari/5.1",
66 + "safari/latest",
67 + "opera/12"
68 + ]
69 + },
70 + "version": "0.0.8"
71 +}
1 +# minimist
2 +
3 +parse argument options
4 +
5 +This module is the guts of optimist's argument parser without all the
6 +fanciful decoration.
7 +
8 +[![browser support](https://ci.testling.com/substack/minimist.png)](http://ci.testling.com/substack/minimist)
9 +
10 +[![build status](https://secure.travis-ci.org/substack/minimist.png)](http://travis-ci.org/substack/minimist)
11 +
12 +# example
13 +
14 +``` js
15 +var argv = require('minimist')(process.argv.slice(2));
16 +console.dir(argv);
17 +```
18 +
19 +```
20 +$ node example/parse.js -a beep -b boop
21 +{ _: [], a: 'beep', b: 'boop' }
22 +```
23 +
24 +```
25 +$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
26 +{ _: [ 'foo', 'bar', 'baz' ],
27 + x: 3,
28 + y: 4,
29 + n: 5,
30 + a: true,
31 + b: true,
32 + c: true,
33 + beep: 'boop' }
34 +```
35 +
36 +# methods
37 +
38 +``` js
39 +var parseArgs = require('minimist')
40 +```
41 +
42 +## var argv = parseArgs(args, opts={})
43 +
44 +Return an argument object `argv` populated with the array arguments from `args`.
45 +
46 +`argv._` contains all the arguments that didn't have an option associated with
47 +them.
48 +
49 +Numeric-looking arguments will be returned as numbers unless `opts.string` or
50 +`opts.boolean` is set for that argument name.
51 +
52 +Any arguments after `'--'` will not be parsed and will end up in `argv._`.
53 +
54 +options can be:
55 +
56 +* `opts.string` - a string or array of strings argument names to always treat as
57 +strings
58 +* `opts.boolean` - a string or array of strings to always treat as booleans
59 +* `opts.alias` - an object mapping string names to strings or arrays of string
60 +argument names to use as aliases
61 +* `opts.default` - an object mapping string argument names to default values
62 +
63 +# install
64 +
65 +With [npm](https://npmjs.org) do:
66 +
67 +```
68 +npm install minimist
69 +```
70 +
71 +# license
72 +
73 +MIT
1 +var parse = require('../');
2 +var test = require('tape');
3 +
4 +test('-', function (t) {
5 + t.plan(5);
6 + t.deepEqual(parse([ '-n', '-' ]), { n: '-', _: [] });
7 + t.deepEqual(parse([ '-' ]), { _: [ '-' ] });
8 + t.deepEqual(parse([ '-f-' ]), { f: '-', _: [] });
9 + t.deepEqual(
10 + parse([ '-b', '-' ], { boolean: 'b' }),
11 + { b: true, _: [ '-' ] }
12 + );
13 + t.deepEqual(
14 + parse([ '-s', '-' ], { string: 's' }),
15 + { s: '-', _: [] }
16 + );
17 +});
18 +
19 +test('-a -- b', function (t) {
20 + t.plan(3);
21 + t.deepEqual(parse([ '-a', '--', 'b' ]), { a: true, _: [ 'b' ] });
22 + t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] });
23 + t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] });
24 +});
1 +var test = require('tape');
2 +var parse = require('../');
3 +
4 +test('boolean default true', function (t) {
5 + var argv = parse([], {
6 + boolean: 'sometrue',
7 + default: { sometrue: true }
8 + });
9 + t.equal(argv.sometrue, true);
10 + t.end();
11 +});
12 +
13 +test('boolean default false', function (t) {
14 + var argv = parse([], {
15 + boolean: 'somefalse',
16 + default: { somefalse: false }
17 + });
18 + t.equal(argv.somefalse, false);
19 + t.end();
20 +});
1 +var parse = require('../');
2 +var test = require('tape');
3 +
4 +test('dotted alias', function (t) {
5 + var argv = parse(['--a.b', '22'], {default: {'a.b': 11}, alias: {'a.b': 'aa.bb'}});
6 + t.equal(argv.a.b, 22);
7 + t.equal(argv.aa.bb, 22);
8 + t.end();
9 +});
10 +
11 +test('dotted default', function (t) {
12 + var argv = parse('', {default: {'a.b': 11}, alias: {'a.b': 'aa.bb'}});
13 + t.equal(argv.a.b, 11);
14 + t.equal(argv.aa.bb, 11);
15 + t.end();
16 +});
1 +var test = require('tape');
2 +var parse = require('../');
3 +
4 +test('long opts', function (t) {
5 + t.deepEqual(
6 + parse([ '--bool' ]),
7 + { bool : true, _ : [] },
8 + 'long boolean'
9 + );
10 + t.deepEqual(
11 + parse([ '--pow', 'xixxle' ]),
12 + { pow : 'xixxle', _ : [] },
13 + 'long capture sp'
14 + );
15 + t.deepEqual(
16 + parse([ '--pow=xixxle' ]),
17 + { pow : 'xixxle', _ : [] },
18 + 'long capture eq'
19 + );
20 + t.deepEqual(
21 + parse([ '--host', 'localhost', '--port', '555' ]),
22 + { host : 'localhost', port : 555, _ : [] },
23 + 'long captures sp'
24 + );
25 + t.deepEqual(
26 + parse([ '--host=localhost', '--port=555' ]),
27 + { host : 'localhost', port : 555, _ : [] },
28 + 'long captures eq'
29 + );
30 + t.end();
31 +});
1 +var parse = require('../');
2 +var test = require('tape');
3 +
4 +test('parse args', function (t) {
5 + t.deepEqual(
6 + parse([ '--no-moo' ]),
7 + { moo : false, _ : [] },
8 + 'no'
9 + );
10 + t.deepEqual(
11 + parse([ '-v', 'a', '-v', 'b', '-v', 'c' ]),
12 + { v : ['a','b','c'], _ : [] },
13 + 'multi'
14 + );
15 + t.end();
16 +});
17 +
18 +test('comprehensive', function (t) {
19 + t.deepEqual(
20 + parse([
21 + '--name=meowmers', 'bare', '-cats', 'woo',
22 + '-h', 'awesome', '--multi=quux',
23 + '--key', 'value',
24 + '-b', '--bool', '--no-meep', '--multi=baz',
25 + '--', '--not-a-flag', 'eek'
26 + ]),
27 + {
28 + c : true,
29 + a : true,
30 + t : true,
31 + s : 'woo',
32 + h : 'awesome',
33 + b : true,
34 + bool : true,
35 + key : 'value',
36 + multi : [ 'quux', 'baz' ],
37 + meep : false,
38 + name : 'meowmers',
39 + _ : [ 'bare', '--not-a-flag', 'eek' ]
40 + }
41 + );
42 + t.end();
43 +});
44 +
45 +test('nums', function (t) {
46 + var argv = parse([
47 + '-x', '1234',
48 + '-y', '5.67',
49 + '-z', '1e7',
50 + '-w', '10f',
51 + '--hex', '0xdeadbeef',
52 + '789'
53 + ]);
54 + t.deepEqual(argv, {
55 + x : 1234,
56 + y : 5.67,
57 + z : 1e7,
58 + w : '10f',
59 + hex : 0xdeadbeef,
60 + _ : [ 789 ]
61 + });
62 + t.deepEqual(typeof argv.x, 'number');
63 + t.deepEqual(typeof argv.y, 'number');
64 + t.deepEqual(typeof argv.z, 'number');
65 + t.deepEqual(typeof argv.w, 'string');
66 + t.deepEqual(typeof argv.hex, 'number');
67 + t.deepEqual(typeof argv._[0], 'number');
68 + t.end();
69 +});
70 +
71 +test('flag boolean', function (t) {
72 + var argv = parse([ '-t', 'moo' ], { boolean: 't' });
73 + t.deepEqual(argv, { t : true, _ : [ 'moo' ] });
74 + t.deepEqual(typeof argv.t, 'boolean');
75 + t.end();
76 +});
77 +
78 +test('flag boolean value', function (t) {
79 + var argv = parse(['--verbose', 'false', 'moo', '-t', 'true'], {
80 + boolean: [ 't', 'verbose' ],
81 + default: { verbose: true }
82 + });
83 +
84 + t.deepEqual(argv, {
85 + verbose: false,
86 + t: true,
87 + _: ['moo']
88 + });
89 +
90 + t.deepEqual(typeof argv.verbose, 'boolean');
91 + t.deepEqual(typeof argv.t, 'boolean');
92 + t.end();
93 +});
94 +
95 +test('flag boolean default false', function (t) {
96 + var argv = parse(['moo'], {
97 + boolean: ['t', 'verbose'],
98 + default: { verbose: false, t: false }
99 + });
100 +
101 + t.deepEqual(argv, {
102 + verbose: false,
103 + t: false,
104 + _: ['moo']
105 + });
106 +
107 + t.deepEqual(typeof argv.verbose, 'boolean');
108 + t.deepEqual(typeof argv.t, 'boolean');
109 + t.end();
110 +
111 +});
112 +
113 +test('boolean groups', function (t) {
114 + var argv = parse([ '-x', '-z', 'one', 'two', 'three' ], {
115 + boolean: ['x','y','z']
116 + });
117 +
118 + t.deepEqual(argv, {
119 + x : true,
120 + y : false,
121 + z : true,
122 + _ : [ 'one', 'two', 'three' ]
123 + });
124 +
125 + t.deepEqual(typeof argv.x, 'boolean');
126 + t.deepEqual(typeof argv.y, 'boolean');
127 + t.deepEqual(typeof argv.z, 'boolean');
128 + t.end();
129 +});
130 +
131 +test('newlines in params' , function (t) {
132 + var args = parse([ '-s', "X\nX" ])
133 + t.deepEqual(args, { _ : [], s : "X\nX" });
134 +
135 + // reproduce in bash:
136 + // VALUE="new
137 + // line"
138 + // node program.js --s="$VALUE"
139 + args = parse([ "--s=X\nX" ])
140 + t.deepEqual(args, { _ : [], s : "X\nX" });
141 + t.end();
142 +});
143 +
144 +test('strings' , function (t) {
145 + var s = parse([ '-s', '0001234' ], { string: 's' }).s;
146 + t.equal(s, '0001234');
147 + t.equal(typeof s, 'string');
148 +
149 + var x = parse([ '-x', '56' ], { string: 'x' }).x;
150 + t.equal(x, '56');
151 + t.equal(typeof x, 'string');
152 + t.end();
153 +});
154 +
155 +test('stringArgs', function (t) {
156 + var s = parse([ ' ', ' ' ], { string: '_' })._;
157 + t.same(s.length, 2);
158 + t.same(typeof s[0], 'string');
159 + t.same(s[0], ' ');
160 + t.same(typeof s[1], 'string');
161 + t.same(s[1], ' ');
162 + t.end();
163 +});
164 +
165 +test('empty strings', function(t) {
166 + var s = parse([ '-s' ], { string: 's' }).s;
167 + t.equal(s, '');
168 + t.equal(typeof s, 'string');
169 +
170 + var str = parse([ '--str' ], { string: 'str' }).str;
171 + t.equal(str, '');
172 + t.equal(typeof str, 'string');
173 +
174 + var letters = parse([ '-art' ], {
175 + string: [ 'a', 't' ]
176 + });
177 +
178 + t.equal(letters.a, '');
179 + t.equal(letters.r, true);
180 + t.equal(letters.t, '');
181 +
182 + t.end();
183 +});
184 +
185 +
186 +test('slashBreak', function (t) {
187 + t.same(
188 + parse([ '-I/foo/bar/baz' ]),
189 + { I : '/foo/bar/baz', _ : [] }
190 + );
191 + t.same(
192 + parse([ '-xyz/foo/bar/baz' ]),
193 + { x : true, y : true, z : '/foo/bar/baz', _ : [] }
194 + );
195 + t.end();
196 +});
197 +
198 +test('alias', function (t) {
199 + var argv = parse([ '-f', '11', '--zoom', '55' ], {
200 + alias: { z: 'zoom' }
201 + });
202 + t.equal(argv.zoom, 55);
203 + t.equal(argv.z, argv.zoom);
204 + t.equal(argv.f, 11);
205 + t.end();
206 +});
207 +
208 +test('multiAlias', function (t) {
209 + var argv = parse([ '-f', '11', '--zoom', '55' ], {
210 + alias: { z: [ 'zm', 'zoom' ] }
211 + });
212 + t.equal(argv.zoom, 55);
213 + t.equal(argv.z, argv.zoom);
214 + t.equal(argv.z, argv.zm);
215 + t.equal(argv.f, 11);
216 + t.end();
217 +});
218 +
219 +test('nested dotted objects', function (t) {
220 + var argv = parse([
221 + '--foo.bar', '3', '--foo.baz', '4',
222 + '--foo.quux.quibble', '5', '--foo.quux.o_O',
223 + '--beep.boop'
224 + ]);
225 +
226 + t.same(argv.foo, {
227 + bar : 3,
228 + baz : 4,
229 + quux : {
230 + quibble : 5,
231 + o_O : true
232 + }
233 + });
234 + t.same(argv.beep, { boop : true });
235 + t.end();
236 +});
237 +
238 +test('boolean and alias with chainable api', function (t) {
239 + var aliased = [ '-h', 'derp' ];
240 + var regular = [ '--herp', 'derp' ];
241 + var opts = {
242 + herp: { alias: 'h', boolean: true }
243 + };
244 + var aliasedArgv = parse(aliased, {
245 + boolean: 'herp',
246 + alias: { h: 'herp' }
247 + });
248 + var propertyArgv = parse(regular, {
249 + boolean: 'herp',
250 + alias: { h: 'herp' }
251 + });
252 + var expected = {
253 + herp: true,
254 + h: true,
255 + '_': [ 'derp' ]
256 + };
257 +
258 + t.same(aliasedArgv, expected);
259 + t.same(propertyArgv, expected);
260 + t.end();
261 +});
262 +
263 +test('boolean and alias with options hash', function (t) {
264 + var aliased = [ '-h', 'derp' ];
265 + var regular = [ '--herp', 'derp' ];
266 + var opts = {
267 + alias: { 'h': 'herp' },
268 + boolean: 'herp'
269 + };
270 + var aliasedArgv = parse(aliased, opts);
271 + var propertyArgv = parse(regular, opts);
272 + var expected = {
273 + herp: true,
274 + h: true,
275 + '_': [ 'derp' ]
276 + };
277 + t.same(aliasedArgv, expected);
278 + t.same(propertyArgv, expected);
279 + t.end();
280 +});
281 +
282 +test('boolean and alias using explicit true', function (t) {
283 + var aliased = [ '-h', 'true' ];
284 + var regular = [ '--herp', 'true' ];
285 + var opts = {
286 + alias: { h: 'herp' },
287 + boolean: 'h'
288 + };
289 + var aliasedArgv = parse(aliased, opts);
290 + var propertyArgv = parse(regular, opts);
291 + var expected = {
292 + herp: true,
293 + h: true,
294 + '_': [ ]
295 + };
296 +
297 + t.same(aliasedArgv, expected);
298 + t.same(propertyArgv, expected);
299 + t.end();
300 +});
301 +
302 +// regression, see https://github.com/substack/node-optimist/issues/71
303 +test('boolean and --x=true', function(t) {
304 + var parsed = parse(['--boool', '--other=true'], {
305 + boolean: 'boool'
306 + });
307 +
308 + t.same(parsed.boool, true);
309 + t.same(parsed.other, 'true');
310 +
311 + parsed = parse(['--boool', '--other=false'], {
312 + boolean: 'boool'
313 + });
314 +
315 + t.same(parsed.boool, true);
316 + t.same(parsed.other, 'false');
317 + t.end();
318 +});
1 +var parse = require('../');
2 +var test = require('tape');
3 +
4 +test('parse with modifier functions' , function (t) {
5 + t.plan(1);
6 +
7 + var argv = parse([ '-b', '123' ], { boolean: 'b' });
8 + t.deepEqual(argv, { b: true, _: ['123'] });
9 +});
1 +var parse = require('../');
2 +var test = require('tape');
3 +
4 +test('numeric short args', function (t) {
5 + t.plan(2);
6 + t.deepEqual(parse([ '-n123' ]), { n: 123, _: [] });
7 + t.deepEqual(
8 + parse([ '-123', '456' ]),
9 + { 1: true, 2: true, 3: 456, _: [] }
10 + );
11 +});
12 +
13 +test('short', function (t) {
14 + t.deepEqual(
15 + parse([ '-b' ]),
16 + { b : true, _ : [] },
17 + 'short boolean'
18 + );
19 + t.deepEqual(
20 + parse([ 'foo', 'bar', 'baz' ]),
21 + { _ : [ 'foo', 'bar', 'baz' ] },
22 + 'bare'
23 + );
24 + t.deepEqual(
25 + parse([ '-cats' ]),
26 + { c : true, a : true, t : true, s : true, _ : [] },
27 + 'group'
28 + );
29 + t.deepEqual(
30 + parse([ '-cats', 'meow' ]),
31 + { c : true, a : true, t : true, s : 'meow', _ : [] },
32 + 'short group next'
33 + );
34 + t.deepEqual(
35 + parse([ '-h', 'localhost' ]),
36 + { h : 'localhost', _ : [] },
37 + 'short capture'
38 + );
39 + t.deepEqual(
40 + parse([ '-h', 'localhost', '-p', '555' ]),
41 + { h : 'localhost', p : 555, _ : [] },
42 + 'short captures'
43 + );
44 + t.end();
45 +});
46 +
47 +test('mixed short bool and capture', function (t) {
48 + t.same(
49 + parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]),
50 + {
51 + f : true, p : 555, h : 'localhost',
52 + _ : [ 'script.js' ]
53 + }
54 + );
55 + t.end();
56 +});
57 +
58 +test('short and long', function (t) {
59 + t.deepEqual(
60 + parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]),
61 + {
62 + f : true, p : 555, h : 'localhost',
63 + _ : [ 'script.js' ]
64 + }
65 + );
66 + t.end();
67 +});
1 +var parse = require('../');
2 +var test = require('tape');
3 +
4 +test('whitespace should be whitespace' , function (t) {
5 + t.plan(1);
6 + var x = parse([ '-x', '\t' ]).x;
7 + t.equal(x, '\t');
8 +});
1 +language: node_js
2 +node_js:
3 + - "0.8"
4 + - "0.10"
5 + - "0.12"
6 + - "iojs"
7 +before_install:
8 + - npm install -g npm@~1.4.6
1 +Copyright 2010 James Halliday (mail@substack.net)
2 +
3 +This project is free software released under the MIT/X11 license:
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in
13 +all copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 +THE SOFTWARE.
1 +#!/usr/bin/env node
2 +
3 +var mkdirp = require('../');
4 +var minimist = require('minimist');
5 +var fs = require('fs');
6 +
7 +var argv = minimist(process.argv.slice(2), {
8 + alias: { m: 'mode', h: 'help' },
9 + string: [ 'mode' ]
10 +});
11 +if (argv.help) {
12 + fs.createReadStream(__dirname + '/usage.txt').pipe(process.stdout);
13 + return;
14 +}
15 +
16 +var paths = argv._.slice();
17 +var mode = argv.mode ? parseInt(argv.mode, 8) : undefined;
18 +
19 +(function next () {
20 + if (paths.length === 0) return;
21 + var p = paths.shift();
22 +
23 + if (mode === undefined) mkdirp(p, cb)
24 + else mkdirp(p, mode, cb)
25 +
26 + function cb (err) {
27 + if (err) {
28 + console.error(err.message);
29 + process.exit(1);
30 + }
31 + else next();
32 + }
33 +})();
1 +usage: mkdirp [DIR1,DIR2..] {OPTIONS}
2 +
3 + Create each supplied directory including any necessary parent directories that
4 + don't yet exist.
5 +
6 + If the directory already exists, do nothing.
7 +
8 +OPTIONS are:
9 +
10 + -m, --mode If a directory needs to be created, set the mode as an octal
11 + permission string.
12 +
1 +var mkdirp = require('mkdirp');
2 +
3 +mkdirp('/tmp/foo/bar/baz', function (err) {
4 + if (err) console.error(err)
5 + else console.log('pow!')
6 +});
1 +var path = require('path');
2 +var fs = require('fs');
3 +var _0777 = parseInt('0777', 8);
4 +
5 +module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
6 +
7 +function mkdirP (p, opts, f, made) {
8 + if (typeof opts === 'function') {
9 + f = opts;
10 + opts = {};
11 + }
12 + else if (!opts || typeof opts !== 'object') {
13 + opts = { mode: opts };
14 + }
15 +
16 + var mode = opts.mode;
17 + var xfs = opts.fs || fs;
18 +
19 + if (mode === undefined) {
20 + mode = _0777 & (~process.umask());
21 + }
22 + if (!made) made = null;
23 +
24 + var cb = f || function () {};
25 + p = path.resolve(p);
26 +
27 + xfs.mkdir(p, mode, function (er) {
28 + if (!er) {
29 + made = made || p;
30 + return cb(null, made);
31 + }
32 + switch (er.code) {
33 + case 'ENOENT':
34 + mkdirP(path.dirname(p), opts, function (er, made) {
35 + if (er) cb(er, made);
36 + else mkdirP(p, opts, cb, made);
37 + });
38 + break;
39 +
40 + // In the case of any other error, just see if there's a dir
41 + // there already. If so, then hooray! If not, then something
42 + // is borked.
43 + default:
44 + xfs.stat(p, function (er2, stat) {
45 + // if the stat fails, then that's super weird.
46 + // let the original error be the failure reason.
47 + if (er2 || !stat.isDirectory()) cb(er, made)
48 + else cb(null, made);
49 + });
50 + break;
51 + }
52 + });
53 +}
54 +
55 +mkdirP.sync = function sync (p, opts, made) {
56 + if (!opts || typeof opts !== 'object') {
57 + opts = { mode: opts };
58 + }
59 +
60 + var mode = opts.mode;
61 + var xfs = opts.fs || fs;
62 +
63 + if (mode === undefined) {
64 + mode = _0777 & (~process.umask());
65 + }
66 + if (!made) made = null;
67 +
68 + p = path.resolve(p);
69 +
70 + try {
71 + xfs.mkdirSync(p, mode);
72 + made = made || p;
73 + }
74 + catch (err0) {
75 + switch (err0.code) {
76 + case 'ENOENT' :
77 + made = sync(path.dirname(p), opts, made);
78 + sync(p, opts, made);
79 + break;
80 +
81 + // In the case of any other error, just see if there's a dir
82 + // there already. If so, then hooray! If not, then something
83 + // is borked.
84 + default:
85 + var stat;
86 + try {
87 + stat = xfs.statSync(p);
88 + }
89 + catch (err1) {
90 + throw err0;
91 + }
92 + if (!stat.isDirectory()) throw err0;
93 + break;
94 + }
95 + }
96 +
97 + return made;
98 +};
1 +{
2 + "_from": "mkdirp@~0.5.1",
3 + "_id": "mkdirp@0.5.1",
4 + "_inBundle": false,
5 + "_integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
6 + "_location": "/mkdirp",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "range",
10 + "registry": true,
11 + "raw": "mkdirp@~0.5.1",
12 + "name": "mkdirp",
13 + "escapedName": "mkdirp",
14 + "rawSpec": "~0.5.1",
15 + "saveSpec": null,
16 + "fetchSpec": "~0.5.1"
17 + },
18 + "_requiredBy": [
19 + "/youtube-dl"
20 + ],
21 + "_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
22 + "_shasum": "30057438eac6cf7f8c4767f38648d6697d75c903",
23 + "_spec": "mkdirp@~0.5.1",
24 + "_where": "C:\\Users\\user\\Desktop\\오소git\\오소플젝\\Youtube_MPL\\node_modules\\youtube-dl",
25 + "author": {
26 + "name": "James Halliday",
27 + "email": "mail@substack.net",
28 + "url": "http://substack.net"
29 + },
30 + "bin": {
31 + "mkdirp": "bin/cmd.js"
32 + },
33 + "bugs": {
34 + "url": "https://github.com/substack/node-mkdirp/issues"
35 + },
36 + "bundleDependencies": false,
37 + "dependencies": {
38 + "minimist": "0.0.8"
39 + },
40 + "deprecated": false,
41 + "description": "Recursively mkdir, like `mkdir -p`",
42 + "devDependencies": {
43 + "mock-fs": "2 >=2.7.0",
44 + "tap": "1"
45 + },
46 + "homepage": "https://github.com/substack/node-mkdirp#readme",
47 + "keywords": [
48 + "mkdir",
49 + "directory"
50 + ],
51 + "license": "MIT",
52 + "main": "index.js",
53 + "name": "mkdirp",
54 + "repository": {
55 + "type": "git",
56 + "url": "git+https://github.com/substack/node-mkdirp.git"
57 + },
58 + "scripts": {
59 + "test": "tap test/*.js"
60 + },
61 + "version": "0.5.1"
62 +}
1 +# mkdirp
2 +
3 +Like `mkdir -p`, but in node.js!
4 +
5 +[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)
6 +
7 +# example
8 +
9 +## pow.js
10 +
11 +```js
12 +var mkdirp = require('mkdirp');
13 +
14 +mkdirp('/tmp/foo/bar/baz', function (err) {
15 + if (err) console.error(err)
16 + else console.log('pow!')
17 +});
18 +```
19 +
20 +Output
21 +
22 +```
23 +pow!
24 +```
25 +
26 +And now /tmp/foo/bar/baz exists, huzzah!
27 +
28 +# methods
29 +
30 +```js
31 +var mkdirp = require('mkdirp');
32 +```
33 +
34 +## mkdirp(dir, opts, cb)
35 +
36 +Create a new directory and any necessary subdirectories at `dir` with octal
37 +permission string `opts.mode`. If `opts` is a non-object, it will be treated as
38 +the `opts.mode`.
39 +
40 +If `opts.mode` isn't specified, it defaults to `0777 & (~process.umask())`.
41 +
42 +`cb(err, made)` fires with the error or the first directory `made`
43 +that had to be created, if any.
44 +
45 +You can optionally pass in an alternate `fs` implementation by passing in
46 +`opts.fs`. Your implementation should have `opts.fs.mkdir(path, mode, cb)` and
47 +`opts.fs.stat(path, cb)`.
48 +
49 +## mkdirp.sync(dir, opts)
50 +
51 +Synchronously create a new directory and any necessary subdirectories at `dir`
52 +with octal permission string `opts.mode`. If `opts` is a non-object, it will be
53 +treated as the `opts.mode`.
54 +
55 +If `opts.mode` isn't specified, it defaults to `0777 & (~process.umask())`.
56 +
57 +Returns the first directory that had to be created, if any.
58 +
59 +You can optionally pass in an alternate `fs` implementation by passing in
60 +`opts.fs`. Your implementation should have `opts.fs.mkdirSync(path, mode)` and
61 +`opts.fs.statSync(path)`.
62 +
63 +# usage
64 +
65 +This package also ships with a `mkdirp` command.
66 +
67 +```
68 +usage: mkdirp [DIR1,DIR2..] {OPTIONS}
69 +
70 + Create each supplied directory including any necessary parent directories that
71 + don't yet exist.
72 +
73 + If the directory already exists, do nothing.
74 +
75 +OPTIONS are:
76 +
77 + -m, --mode If a directory needs to be created, set the mode as an octal
78 + permission string.
79 +
80 +```
81 +
82 +# install
83 +
84 +With [npm](http://npmjs.org) do:
85 +
86 +```
87 +npm install mkdirp
88 +```
89 +
90 +to get the library, or
91 +
92 +```
93 +npm install -g mkdirp
94 +```
95 +
96 +to get the command.
97 +
98 +# license
99 +
100 +MIT
1 +var mkdirp = require('../').mkdirp;
2 +var path = require('path');
3 +var fs = require('fs');
4 +var test = require('tap').test;
5 +var _0777 = parseInt('0777', 8);
6 +var _0755 = parseInt('0755', 8);
7 +var _0744 = parseInt('0744', 8);
8 +
9 +var ps = [ '', 'tmp' ];
10 +
11 +for (var i = 0; i < 25; i++) {
12 + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
13 + ps.push(dir);
14 +}
15 +
16 +var file = ps.join('/');
17 +
18 +test('chmod-pre', function (t) {
19 + var mode = _0744
20 + mkdirp(file, mode, function (er) {
21 + t.ifError(er, 'should not error');
22 + fs.stat(file, function (er, stat) {
23 + t.ifError(er, 'should exist');
24 + t.ok(stat && stat.isDirectory(), 'should be directory');
25 + t.equal(stat && stat.mode & _0777, mode, 'should be 0744');
26 + t.end();
27 + });
28 + });
29 +});
30 +
31 +test('chmod', function (t) {
32 + var mode = _0755
33 + mkdirp(file, mode, function (er) {
34 + t.ifError(er, 'should not error');
35 + fs.stat(file, function (er, stat) {
36 + t.ifError(er, 'should exist');
37 + t.ok(stat && stat.isDirectory(), 'should be directory');
38 + t.end();
39 + });
40 + });
41 +});
1 +var mkdirp = require('../').mkdirp;
2 +var path = require('path');
3 +var fs = require('fs');
4 +var test = require('tap').test;
5 +var _0755 = parseInt('0755', 8);
6 +
7 +var ps = [ '', 'tmp' ];
8 +
9 +for (var i = 0; i < 25; i++) {
10 + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
11 + ps.push(dir);
12 +}
13 +
14 +var file = ps.join('/');
15 +
16 +// a file in the way
17 +var itw = ps.slice(0, 3).join('/');
18 +
19 +
20 +test('clobber-pre', function (t) {
21 + console.error("about to write to "+itw)
22 + fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.');
23 +
24 + fs.stat(itw, function (er, stat) {
25 + t.ifError(er)
26 + t.ok(stat && stat.isFile(), 'should be file')
27 + t.end()
28 + })
29 +})
30 +
31 +test('clobber', function (t) {
32 + t.plan(2);
33 + mkdirp(file, _0755, function (err) {
34 + t.ok(err);
35 + t.equal(err.code, 'ENOTDIR');
36 + t.end();
37 + });
38 +});
1 +var mkdirp = require('../');
2 +var path = require('path');
3 +var fs = require('fs');
4 +var exists = fs.exists || path.exists;
5 +var test = require('tap').test;
6 +var _0777 = parseInt('0777', 8);
7 +var _0755 = parseInt('0755', 8);
8 +
9 +test('woo', function (t) {
10 + t.plan(5);
11 + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
12 + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
13 + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
14 +
15 + var file = '/tmp/' + [x,y,z].join('/');
16 +
17 + mkdirp(file, _0755, function (err) {
18 + t.ifError(err);
19 + exists(file, function (ex) {
20 + t.ok(ex, 'file created');
21 + fs.stat(file, function (err, stat) {
22 + t.ifError(err);
23 + t.equal(stat.mode & _0777, _0755);
24 + t.ok(stat.isDirectory(), 'target not a directory');
25 + })
26 + })
27 + });
28 +});
1 +var mkdirp = require('../');
2 +var path = require('path');
3 +var test = require('tap').test;
4 +var mockfs = require('mock-fs');
5 +var _0777 = parseInt('0777', 8);
6 +var _0755 = parseInt('0755', 8);
7 +
8 +test('opts.fs', function (t) {
9 + t.plan(5);
10 +
11 + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
12 + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
13 + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
14 +
15 + var file = '/beep/boop/' + [x,y,z].join('/');
16 + var xfs = mockfs.fs();
17 +
18 + mkdirp(file, { fs: xfs, mode: _0755 }, function (err) {
19 + t.ifError(err);
20 + xfs.exists(file, function (ex) {
21 + t.ok(ex, 'created file');
22 + xfs.stat(file, function (err, stat) {
23 + t.ifError(err);
24 + t.equal(stat.mode & _0777, _0755);
25 + t.ok(stat.isDirectory(), 'target not a directory');
26 + });
27 + });
28 + });
29 +});
1 +var mkdirp = require('../');
2 +var path = require('path');
3 +var test = require('tap').test;
4 +var mockfs = require('mock-fs');
5 +var _0777 = parseInt('0777', 8);
6 +var _0755 = parseInt('0755', 8);
7 +
8 +test('opts.fs sync', function (t) {
9 + t.plan(4);
10 +
11 + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
12 + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
13 + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
14 +
15 + var file = '/beep/boop/' + [x,y,z].join('/');
16 + var xfs = mockfs.fs();
17 +
18 + mkdirp.sync(file, { fs: xfs, mode: _0755 });
19 + xfs.exists(file, function (ex) {
20 + t.ok(ex, 'created file');
21 + xfs.stat(file, function (err, stat) {
22 + t.ifError(err);
23 + t.equal(stat.mode & _0777, _0755);
24 + t.ok(stat.isDirectory(), 'target not a directory');
25 + });
26 + });
27 +});
1 +var mkdirp = require('../');
2 +var path = require('path');
3 +var fs = require('fs');
4 +var exists = fs.exists || path.exists;
5 +var test = require('tap').test;
6 +var _0777 = parseInt('0777', 8);
7 +var _0755 = parseInt('0755', 8);
8 +
9 +test('async perm', function (t) {
10 + t.plan(5);
11 + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16);
12 +
13 + mkdirp(file, _0755, function (err) {
14 + t.ifError(err);
15 + exists(file, function (ex) {
16 + t.ok(ex, 'file created');
17 + fs.stat(file, function (err, stat) {
18 + t.ifError(err);
19 + t.equal(stat.mode & _0777, _0755);
20 + t.ok(stat.isDirectory(), 'target not a directory');
21 + })
22 + })
23 + });
24 +});
25 +
26 +test('async root perm', function (t) {
27 + mkdirp('/tmp', _0755, function (err) {
28 + if (err) t.fail(err);
29 + t.end();
30 + });
31 + t.end();
32 +});
1 +var mkdirp = require('../');
2 +var path = require('path');
3 +var fs = require('fs');
4 +var exists = fs.exists || path.exists;
5 +var test = require('tap').test;
6 +var _0777 = parseInt('0777', 8);
7 +var _0755 = parseInt('0755', 8);
8 +
9 +test('sync perm', function (t) {
10 + t.plan(4);
11 + var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json';
12 +
13 + mkdirp.sync(file, _0755);
14 + exists(file, function (ex) {
15 + t.ok(ex, 'file created');
16 + fs.stat(file, function (err, stat) {
17 + t.ifError(err);
18 + t.equal(stat.mode & _0777, _0755);
19 + t.ok(stat.isDirectory(), 'target not a directory');
20 + });
21 + });
22 +});
23 +
24 +test('sync root perm', function (t) {
25 + t.plan(3);
26 +
27 + var file = '/tmp';
28 + mkdirp.sync(file, _0755);
29 + exists(file, function (ex) {
30 + t.ok(ex, 'file created');
31 + fs.stat(file, function (err, stat) {
32 + t.ifError(err);
33 + t.ok(stat.isDirectory(), 'target not a directory');
34 + })
35 + });
36 +});
1 +var mkdirp = require('../').mkdirp;
2 +var path = require('path');
3 +var fs = require('fs');
4 +var exists = fs.exists || path.exists;
5 +var test = require('tap').test;
6 +var _0777 = parseInt('0777', 8);
7 +var _0755 = parseInt('0755', 8);
8 +
9 +test('race', function (t) {
10 + t.plan(10);
11 + var ps = [ '', 'tmp' ];
12 +
13 + for (var i = 0; i < 25; i++) {
14 + var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
15 + ps.push(dir);
16 + }
17 + var file = ps.join('/');
18 +
19 + var res = 2;
20 + mk(file);
21 +
22 + mk(file);
23 +
24 + function mk (file, cb) {
25 + mkdirp(file, _0755, function (err) {
26 + t.ifError(err);
27 + exists(file, function (ex) {
28 + t.ok(ex, 'file created');
29 + fs.stat(file, function (err, stat) {
30 + t.ifError(err);
31 + t.equal(stat.mode & _0777, _0755);
32 + t.ok(stat.isDirectory(), 'target not a directory');
33 + });
34 + })
35 + });
36 + }
37 +});
1 +var mkdirp = require('../');
2 +var path = require('path');
3 +var fs = require('fs');
4 +var exists = fs.exists || path.exists;
5 +var test = require('tap').test;
6 +var _0777 = parseInt('0777', 8);
7 +var _0755 = parseInt('0755', 8);
8 +
9 +test('rel', function (t) {
10 + t.plan(5);
11 + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
12 + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
13 + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
14 +
15 + var cwd = process.cwd();
16 + process.chdir('/tmp');
17 +
18 + var file = [x,y,z].join('/');
19 +
20 + mkdirp(file, _0755, function (err) {
21 + t.ifError(err);
22 + exists(file, function (ex) {
23 + t.ok(ex, 'file created');
24 + fs.stat(file, function (err, stat) {
25 + t.ifError(err);
26 + process.chdir(cwd);
27 + t.equal(stat.mode & _0777, _0755);
28 + t.ok(stat.isDirectory(), 'target not a directory');
29 + })
30 + })
31 + });
32 +});
1 +var mkdirp = require('../');
2 +var path = require('path');
3 +var fs = require('fs');
4 +var test = require('tap').test;
5 +
6 +test('return value', function (t) {
7 + t.plan(4);
8 + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
9 + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
10 + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
11 +
12 + var file = '/tmp/' + [x,y,z].join('/');
13 +
14 + // should return the first dir created.
15 + // By this point, it would be profoundly surprising if /tmp didn't
16 + // already exist, since every other test makes things in there.
17 + mkdirp(file, function (err, made) {
18 + t.ifError(err);
19 + t.equal(made, '/tmp/' + x);
20 + mkdirp(file, function (err, made) {
21 + t.ifError(err);
22 + t.equal(made, null);
23 + });
24 + });
25 +});
1 +var mkdirp = require('../');
2 +var path = require('path');
3 +var fs = require('fs');
4 +var test = require('tap').test;
5 +
6 +test('return value', function (t) {
7 + t.plan(2);
8 + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
9 + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
10 + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
11 +
12 + var file = '/tmp/' + [x,y,z].join('/');
13 +
14 + // should return the first dir created.
15 + // By this point, it would be profoundly surprising if /tmp didn't
16 + // already exist, since every other test makes things in there.
17 + // Note that this will throw on failure, which will fail the test.
18 + var made = mkdirp.sync(file);
19 + t.equal(made, '/tmp/' + x);
20 +
21 + // making the same file again should have no effect.
22 + made = mkdirp.sync(file);
23 + t.equal(made, null);
24 +});
1 +var mkdirp = require('../');
2 +var path = require('path');
3 +var fs = require('fs');
4 +var test = require('tap').test;
5 +var _0755 = parseInt('0755', 8);
6 +
7 +test('root', function (t) {
8 + // '/' on unix, 'c:/' on windows.
9 + var file = path.resolve('/');
10 +
11 + mkdirp(file, _0755, function (err) {
12 + if (err) throw err
13 + fs.stat(file, function (er, stat) {
14 + if (er) throw er
15 + t.ok(stat.isDirectory(), 'target is a directory');
16 + t.end();
17 + })
18 + });
19 +});
1 +var mkdirp = require('../');
2 +var path = require('path');
3 +var fs = require('fs');
4 +var exists = fs.exists || path.exists;
5 +var test = require('tap').test;
6 +var _0777 = parseInt('0777', 8);
7 +var _0755 = parseInt('0755', 8);
8 +
9 +test('sync', function (t) {
10 + t.plan(4);
11 + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
12 + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
13 + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
14 +
15 + var file = '/tmp/' + [x,y,z].join('/');
16 +
17 + try {
18 + mkdirp.sync(file, _0755);
19 + } catch (err) {
20 + t.fail(err);
21 + return t.end();
22 + }
23 +
24 + exists(file, function (ex) {
25 + t.ok(ex, 'file created');
26 + fs.stat(file, function (err, stat) {
27 + t.ifError(err);
28 + t.equal(stat.mode & _0777, _0755);
29 + t.ok(stat.isDirectory(), 'target not a directory');
30 + });
31 + });
32 +});
1 +var mkdirp = require('../');
2 +var path = require('path');
3 +var fs = require('fs');
4 +var exists = fs.exists || path.exists;
5 +var test = require('tap').test;
6 +var _0777 = parseInt('0777', 8);
7 +var _0755 = parseInt('0755', 8);
8 +
9 +test('implicit mode from umask', function (t) {
10 + t.plan(5);
11 + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
12 + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
13 + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
14 +
15 + var file = '/tmp/' + [x,y,z].join('/');
16 +
17 + mkdirp(file, function (err) {
18 + t.ifError(err);
19 + exists(file, function (ex) {
20 + t.ok(ex, 'file created');
21 + fs.stat(file, function (err, stat) {
22 + t.ifError(err);
23 + t.equal(stat.mode & _0777, _0777 & (~process.umask()));
24 + t.ok(stat.isDirectory(), 'target not a directory');
25 + });
26 + })
27 + });
28 +});
1 +var mkdirp = require('../');
2 +var path = require('path');
3 +var fs = require('fs');
4 +var exists = fs.exists || path.exists;
5 +var test = require('tap').test;
6 +var _0777 = parseInt('0777', 8);
7 +var _0755 = parseInt('0755', 8);
8 +
9 +test('umask sync modes', function (t) {
10 + t.plan(4);
11 + var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
12 + var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
13 + var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
14 +
15 + var file = '/tmp/' + [x,y,z].join('/');
16 +
17 + try {
18 + mkdirp.sync(file);
19 + } catch (err) {
20 + t.fail(err);
21 + return t.end();
22 + }
23 +
24 + exists(file, function (ex) {
25 + t.ok(ex, 'file created');
26 + fs.stat(file, function (err, stat) {
27 + t.ifError(err);
28 + t.equal(stat.mode & _0777, (_0777 & (~process.umask())));
29 + t.ok(stat.isDirectory(), 'target not a directory');
30 + });
31 + });
32 +});
1 +Copyright (C) 2012 by Roly Fentanes
2 +
3 +Permission is hereby granted, free of charge, to any person obtaining a copy
4 +of this software and associated documentation files (the "Software"), to deal
5 +in the Software without restriction, including without limitation the rights
6 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 +copies of the Software, and to permit persons to whom the Software is
8 +furnished to do so, subject to the following conditions:
9 +
10 +The above copyright notice and this permission notice shall be included in
11 +all copies or substantial portions of the Software.
12 +
13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 +THE SOFTWARE.
1 +# node-streamify
2 +
3 +Streamify helps you easily provide a streaming interface for your code.
4 +
5 +[![Build Status](https://secure.travis-ci.org/fent/node-streamify.svg)](http://travis-ci.org/fent/node-streamify)
6 +[![Dependency Status](https://david-dm.org/fent/node-streamify.svg)](https://david-dm.org/fent/node-streamify)
7 +[![codecov](https://codecov.io/gh/fent/node-streamify/branch/master/graph/badge.svg)](https://codecov.io/gh/fent/node-streamify)
8 +
9 +# Usage
10 +
11 +```js
12 +var streamify = require('streamify');
13 +var request = require('request');
14 +
15 +exports.doSomething = function doSomething() {
16 + var stream = streamify();
17 +
18 + request(url1, function(err, res, body) {
19 + // do something with `body`
20 +
21 + // once the actual stream you want to return is ready,
22 + // call `stream.resolve()`
23 + stream.resolve(request(url2));
24 + });
25 +
26 + // your function can return back a stream!!
27 + return stream;
28 +}
29 +
30 +// because `doSomething()` returns a stream, it can be piped
31 +exports.doSomething().pipe(anotherStream);
32 +```
33 +
34 +
35 +# API
36 +### streamify([options])
37 +
38 +Returns an instance of a stream. `options` can be
39 +
40 +* `superCtor` - The object from which it inherits. Defaults to `require('stream').Stream`. Sometimes you may want to use this if your stream might be checked with the `instanceof` operator against objects such as `http.ServerResponse`.
41 +* `readable` - Defaults to `true`.
42 +* `writable` - Defaults to `true`.
43 +
44 +### Stream#resolve(stream)
45 +
46 +Must be called only once when the actual stream you are proxying to becomes available after an asynchronous operation.
47 +
48 +### Stream#unresolve()
49 +
50 +Can be used to unbind a a resolved stream to later call `resolve()` again.
51 +
52 +### Stream#addSource(stream)
53 +
54 +Add a source readable stream.
55 +
56 +### Stream#removeSource()
57 +
58 +Remove previously added source stream.
59 +
60 +### Stream#addDest(stream)
61 +
62 +Add a destination writable stream.
63 +
64 +### Stream#removeDest()
65 +
66 +Remove a previously added destination stream.
67 +
68 +
69 +# Install
70 +
71 + npm install streamify
72 +
73 +
74 +# Tests
75 +Tests are written with [mocha](https://mochajs.org)
76 +
77 +```bash
78 +npm test
79 +```
80 +
81 +# License
82 +MIT
1 +var Readable = require('stream').Readable;
2 +var Writable = require('stream').Writable;
3 +var Duplex = require('stream').Duplex;
4 +var hashish = require('hashish');
5 +
6 +
7 +/**
8 + * Proxy some events from underlying readable and writable streams.
9 + */
10 +var SOURCE_EVENTS = ['error', 'close'];
11 +var DEST_EVENTS = ['drain', 'close'];
12 +
13 +
14 +/**
15 + * Creates property to use with `Object.create()`
16 + *
17 + * @param {Object} value
18 + * @return {Object}
19 + */
20 +function prop(value) {
21 + return {
22 + writable: true,
23 + enumerable: true,
24 + configurable: true,
25 + value: value
26 + };
27 +}
28 +
29 +
30 +/**
31 + * @constructor
32 + * @param {Object} options
33 + * {Object} superCtor
34 + * {Boolean} readable
35 + * {Boolean} writable
36 + * @return {Duplex}
37 + */
38 +var Streamify = module.exports = function Streamify(options) {
39 + options = options || {};
40 + options.readable = typeof options.readable !== 'undefined' ?
41 + options.readable : true;
42 + options.writable = typeof options.writable !== 'undefined' ?
43 + options.writable : true;
44 +
45 + var superCtor = getConstructor(options);
46 +
47 + // Add `Streamify.prototype` methods.
48 + var properties = hashish.map(Streamify.prototype, prop);
49 +
50 + var o = Object.create(superCtor.prototype, properties);
51 + superCtor.call(o);
52 + o.readable = options.readable;
53 + o.writable = options.writable;
54 + o.__options = options;
55 + o._onevent = function onevent() {
56 + };
57 + o._destWritten = [];
58 +
59 + if (options.writable) {
60 + o.once('finish', function() {
61 + if (o._dest) {
62 + o._dest.stream.end();
63 + }
64 + });
65 + }
66 + return o;
67 +};
68 +
69 +
70 +/**
71 + * Required implementation by streaming API.
72 + *
73 + * @param {Number} size
74 + */
75 +Streamify.prototype._read = function(size) {
76 + if (this._source) {
77 + var self = this;
78 + var onreadable = this._source.onreadable = function onreadable() {
79 + if (!self._source) { return; }
80 + var data = self._source.stream.read(size);
81 + if (data) {
82 + self.push(data);
83 + } else {
84 + self._source.stream.once('readable', onreadable);
85 + }
86 + };
87 + onreadable();
88 +
89 + } else {
90 + this._sourceRead = size;
91 + }
92 +};
93 +
94 +
95 +/**
96 + * Required implementation by streaming API.
97 + *
98 + * @param {Buffer|String} chunk
99 + * @param {!String} encoding
100 + * @param {Function(!Error)} callback
101 + */
102 +Streamify.prototype._write = function(chunk, encoding, callback) {
103 + if (this._dest) {
104 + this._dest.stream.write(chunk, encoding, callback);
105 + } else {
106 + this._destWritten.push(arguments);
107 + }
108 +};
109 +
110 +
111 +/**
112 + * Add a stream to be the readable stream source.
113 + *
114 + * @param {Readable|Stream} stream
115 + */
116 +Streamify.prototype.addSource = function(stream) {
117 + if (this._source) {
118 + throw Error('A source stream has already been added.');
119 + }
120 + stream = getReadable(stream);
121 +
122 + this._source = { stream: stream, listeners: {}, onend: onend };
123 + var self = this;
124 +
125 + SOURCE_EVENTS.forEach(function(event) {
126 + var onevent = self._source.listeners[event] = function onevent() {
127 + var args = Array.prototype.slice.call(arguments);
128 + self.emit.apply(self, [event].concat(args));
129 + };
130 + stream.on(event, onevent);
131 + });
132 +
133 + // Listen for `end` event to signal for end of data.
134 + function onend() {
135 + self.push(null);
136 + }
137 + stream.on('end', onend);
138 +
139 + // Check if `Readable#_read()` has already been called.
140 + this._read(this._sourceRead);
141 +};
142 +
143 +
144 +/**
145 + * Remove a stream from being the source.
146 + */
147 +Streamify.prototype.removeSource = function() {
148 + if (!this._source) {
149 + throw Error('A source stream has not been added.');
150 + }
151 +
152 + var source = this._source;
153 + SOURCE_EVENTS.forEach(function(event) {
154 + source.stream.removeListener(event, source.listeners[event]);
155 + });
156 + source.stream.removeListener('readable', source.onreadable);
157 + source.stream.removeListener('end', source.onend);
158 +
159 + delete this._source;
160 +};
161 +
162 +
163 +/**
164 + * Add a stream to be the writable stream destination.
165 + *
166 + * @param {Writable|Stream} stream
167 + */
168 +Streamify.prototype.addDest = function(stream) {
169 + if (this._dest) {
170 + throw Error('A destination stream has already been added.');
171 + }
172 +
173 + this._dest = { stream: stream, listeners: {} };
174 + var self = this;
175 +
176 + DEST_EVENTS.forEach(function(event) {
177 + var onevent = self._dest.listeners[event] = function onevent() {
178 + var args = Array.prototype.slice.call(arguments);
179 + self.emit.apply(self, [event].concat(args));
180 + };
181 + stream.on(event, onevent);
182 + });
183 +
184 + if (this._destWritten.length) {
185 + this._destWritten.forEach(function(args) {
186 + stream.write.apply(stream, args);
187 + });
188 + }
189 +};
190 +
191 +
192 +/**
193 + * Remove a stream from being the destination.
194 + */
195 +Streamify.prototype.removeDest = function() {
196 + if (!this._dest) {
197 + throw Error('A destination stream has not been added.');
198 + }
199 +
200 + var dest = this._dest;
201 + DEST_EVENTS.forEach(function(event) {
202 + dest.stream.removeListener(event, dest.listeners[event]);
203 + });
204 +
205 + delete this._dest;
206 + this._destWritten = [];
207 +};
208 +
209 +
210 +/**
211 + * Begins fueling data from actual stream into Streamify instance.
212 + *
213 + * @param {Readable|Writable|Duplex|Stream} stream
214 + */
215 +Streamify.prototype.resolve = function(stream) {
216 + if (this.__options.readable && stream.readable) {
217 + this.addSource(stream);
218 + }
219 +
220 + if (this.__options.writable && stream.writable) {
221 + this.addDest(stream);
222 + }
223 +};
224 +
225 +
226 +/**
227 + * Removes a stream from this, possibly because another is replacing it.
228 + */
229 +Streamify.prototype.unresolve = function() {
230 + if (this._source) {
231 + this.removeSource();
232 + }
233 +
234 + if (this._dest) {
235 + this.removeDest();
236 + }
237 +};
238 +
239 +
240 +/**
241 + * Returns a readable new stream API stream if the stream is using the
242 + * old API. Otherwise it returns the same stream.
243 + *
244 + * @param {Readable|Stream} stream
245 + * @return {Readable}
246 + */
247 +function getReadable(stream) {
248 + if (isOldStyleStream(stream)) {
249 + var readable = new Readable();
250 + readable.wrap(stream);
251 + return readable;
252 + } else {
253 + return stream;
254 + }
255 +}
256 +
257 +
258 +/**
259 + * Returns true if a stream is an old style API stream.
260 + *
261 + * @param {Readable|Stream} stream
262 + * @return {Boolean}
263 + */
264 +function isOldStyleStream(stream) {
265 + return typeof stream.read !== 'function' ||
266 + typeof stream._read !== 'function' ||
267 + typeof stream.push !== 'function' ||
268 + typeof stream.unshift !== 'function' ||
269 + typeof stream.wrap !== 'function';
270 +}
271 +
272 +
273 +function getConstructor (options) {
274 + var superCtor = Duplex;
275 + if (options.readable && !options.writable) {
276 + superCtor = Readable;
277 + }
278 +
279 + if (options.writable && !options.readable) {
280 + superCtor = Writable;
281 + }
282 +
283 + return superCtor;
284 +}
...\ No newline at end of file ...\ No newline at end of file
1 +{
2 + "_from": "streamify@~0.2.9",
3 + "_id": "streamify@0.2.9",
4 + "_inBundle": false,
5 + "_integrity": "sha512-8pUxeLEef9UO1FxtTt5iikAiyzGI4SZRnGuJ3sz8axZ5Xk+/7ezEV5kuJQsMEFxw7AKYw3xp0Ow+20mmSaJbQQ==",
6 + "_location": "/streamify",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "range",
10 + "registry": true,
11 + "raw": "streamify@~0.2.9",
12 + "name": "streamify",
13 + "escapedName": "streamify",
14 + "rawSpec": "~0.2.9",
15 + "saveSpec": null,
16 + "fetchSpec": "~0.2.9"
17 + },
18 + "_requiredBy": [
19 + "/youtube-dl"
20 + ],
21 + "_resolved": "https://registry.npmjs.org/streamify/-/streamify-0.2.9.tgz",
22 + "_shasum": "8938b14db491e2b6be4f8d99cc4133c9f0384f0b",
23 + "_spec": "streamify@~0.2.9",
24 + "_where": "C:\\Users\\user\\Desktop\\오소git\\오소플젝\\Youtube_MPL\\node_modules\\youtube-dl",
25 + "author": {
26 + "name": "Roly Fentanes",
27 + "url": "https://github.com/fent"
28 + },
29 + "bugs": {
30 + "url": "https://github.com/fent/node-streamify/issues"
31 + },
32 + "bundleDependencies": false,
33 + "dependencies": {
34 + "hashish": "~0.0.4"
35 + },
36 + "deprecated": false,
37 + "description": "Streamify helps you easily provide a streaming interface for code.",
38 + "devDependencies": {
39 + "istanbul": "*",
40 + "mocha": "*",
41 + "stream-equal": "~1.0.0"
42 + },
43 + "directories": {
44 + "lib": "./lib"
45 + },
46 + "engines": {
47 + "node": ">=0.12"
48 + },
49 + "files": [
50 + "lib"
51 + ],
52 + "homepage": "https://github.com/fent/node-streamify#readme",
53 + "keywords": [
54 + "stream",
55 + "input",
56 + "output",
57 + "api"
58 + ],
59 + "license": "MIT",
60 + "main": "./lib/index.js",
61 + "name": "streamify",
62 + "repository": {
63 + "type": "git",
64 + "url": "git://github.com/fent/node-streamify.git"
65 + },
66 + "scripts": {
67 + "test": "istanbul cover node_modules/.bin/_mocha -- test/*-test.js"
68 + },
69 + "version": "0.2.9"
70 +}
1 +language: node_js
2 +node_js:
3 + - 0.6
1 +Copyright 2010 James Halliday (mail@substack.net)
2 +
3 +This project is free software released under the MIT/X11 license:
4 +http://www.opensource.org/licenses/mit-license.php
5 +
6 +Copyright 2010 James Halliday (mail@substack.net)
7 +
8 +Permission is hereby granted, free of charge, to any person obtaining a copy
9 +of this software and associated documentation files (the "Software"), to deal
10 +in the Software without restriction, including without limitation the rights
11 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 +copies of the Software, and to permit persons to whom the Software is
13 +furnished to do so, subject to the following conditions:
14 +
15 +The above copyright notice and this permission notice shall be included in
16 +all copies or substantial portions of the Software.
17 +
18 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 +THE SOFTWARE.
1 +var traverse = require('traverse');
2 +
3 +var id = 54;
4 +var callbacks = {};
5 +var obj = { moo : function () {}, foo : [2,3,4, function () {}] };
6 +
7 +var scrubbed = traverse(obj).map(function (x) {
8 + if (typeof x === 'function') {
9 + callbacks[id] = { id : id, f : x, path : this.path };
10 + this.update('[Function]');
11 + id++;
12 + }
13 +});
14 +
15 +console.dir(scrubbed);
16 +console.dir(callbacks);
1 +var traverse = require('traverse');
2 +
3 +var obj = {
4 + a : [1,2,3],
5 + b : 4,
6 + c : [5,6],
7 + d : { e : [7,8], f : 9 },
8 +};
9 +
10 +var leaves = traverse(obj).reduce(function (acc, x) {
11 + if (this.isLeaf) acc.push(x);
12 + return acc;
13 +}, []);
14 +
15 +console.dir(leaves);
1 +var traverse = require('traverse');
2 +var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
3 +
4 +traverse(obj).forEach(function (x) {
5 + if (x < 0) this.update(x + 128);
6 +});
7 +
8 +console.dir(obj);
1 +// scrub out circular references
2 +var traverse = require('traverse');
3 +
4 +var obj = { a : 1, b : 2, c : [ 3, 4 ] };
5 +obj.c.push(obj);
6 +
7 +var scrubbed = traverse(obj).map(function (x) {
8 + if (this.circular) this.remove()
9 +});
10 +console.dir(scrubbed);
1 +#!/usr/bin/env node
2 +var traverse = require('traverse');
3 +
4 +var obj = [ 'five', 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
5 +
6 +var s = '';
7 +traverse(obj).forEach(function to_s (node) {
8 + if (Array.isArray(node)) {
9 + this.before(function () { s += '[' });
10 + this.post(function (child) {
11 + if (!child.isLast) s += ',';
12 + });
13 + this.after(function () { s += ']' });
14 + }
15 + else if (typeof node == 'object') {
16 + this.before(function () { s += '{' });
17 + this.pre(function (x, key) {
18 + to_s(key);
19 + s += ':';
20 + });
21 + this.post(function (child) {
22 + if (!child.isLast) s += ',';
23 + });
24 + this.after(function () { s += '}' });
25 + }
26 + else if (typeof node == 'string') {
27 + s += '"' + node.toString().replace(/"/g, '\\"') + '"';
28 + }
29 + else if (typeof node == 'function') {
30 + s += 'null';
31 + }
32 + else {
33 + s += node.toString();
34 + }
35 +});
36 +
37 +console.log('JSON.stringify: ' + JSON.stringify(obj));
38 +console.log('this stringify: ' + s);
1 +var traverse = module.exports = function (obj) {
2 + return new Traverse(obj);
3 +};
4 +
5 +function Traverse (obj) {
6 + this.value = obj;
7 +}
8 +
9 +Traverse.prototype.get = function (ps) {
10 + var node = this.value;
11 + for (var i = 0; i < ps.length; i ++) {
12 + var key = ps[i];
13 + if (!node || !hasOwnProperty.call(node, key)) {
14 + node = undefined;
15 + break;
16 + }
17 + node = node[key];
18 + }
19 + return node;
20 +};
21 +
22 +Traverse.prototype.has = function (ps) {
23 + var node = this.value;
24 + for (var i = 0; i < ps.length; i ++) {
25 + var key = ps[i];
26 + if (!node || !hasOwnProperty.call(node, key)) {
27 + return false;
28 + }
29 + node = node[key];
30 + }
31 + return true;
32 +};
33 +
34 +Traverse.prototype.set = function (ps, value) {
35 + var node = this.value;
36 + for (var i = 0; i < ps.length - 1; i ++) {
37 + var key = ps[i];
38 + if (!hasOwnProperty.call(node, key)) node[key] = {};
39 + node = node[key];
40 + }
41 + node[ps[i]] = value;
42 + return value;
43 +};
44 +
45 +Traverse.prototype.map = function (cb) {
46 + return walk(this.value, cb, true);
47 +};
48 +
49 +Traverse.prototype.forEach = function (cb) {
50 + this.value = walk(this.value, cb, false);
51 + return this.value;
52 +};
53 +
54 +Traverse.prototype.reduce = function (cb, init) {
55 + var skip = arguments.length === 1;
56 + var acc = skip ? this.value : init;
57 + this.forEach(function (x) {
58 + if (!this.isRoot || !skip) {
59 + acc = cb.call(this, acc, x);
60 + }
61 + });
62 + return acc;
63 +};
64 +
65 +Traverse.prototype.paths = function () {
66 + var acc = [];
67 + this.forEach(function (x) {
68 + acc.push(this.path);
69 + });
70 + return acc;
71 +};
72 +
73 +Traverse.prototype.nodes = function () {
74 + var acc = [];
75 + this.forEach(function (x) {
76 + acc.push(this.node);
77 + });
78 + return acc;
79 +};
80 +
81 +Traverse.prototype.clone = function () {
82 + var parents = [], nodes = [];
83 +
84 + return (function clone (src) {
85 + for (var i = 0; i < parents.length; i++) {
86 + if (parents[i] === src) {
87 + return nodes[i];
88 + }
89 + }
90 +
91 + if (typeof src === 'object' && src !== null) {
92 + var dst = copy(src);
93 +
94 + parents.push(src);
95 + nodes.push(dst);
96 +
97 + forEach(objectKeys(src), function (key) {
98 + dst[key] = clone(src[key]);
99 + });
100 +
101 + parents.pop();
102 + nodes.pop();
103 + return dst;
104 + }
105 + else {
106 + return src;
107 + }
108 + })(this.value);
109 +};
110 +
111 +function walk (root, cb, immutable) {
112 + var path = [];
113 + var parents = [];
114 + var alive = true;
115 +
116 + return (function walker (node_) {
117 + var node = immutable ? copy(node_) : node_;
118 + var modifiers = {};
119 +
120 + var keepGoing = true;
121 +
122 + var state = {
123 + node : node,
124 + node_ : node_,
125 + path : [].concat(path),
126 + parent : parents[parents.length - 1],
127 + parents : parents,
128 + key : path.slice(-1)[0],
129 + isRoot : path.length === 0,
130 + level : path.length,
131 + circular : null,
132 + update : function (x, stopHere) {
133 + if (!state.isRoot) {
134 + state.parent.node[state.key] = x;
135 + }
136 + state.node = x;
137 + if (stopHere) keepGoing = false;
138 + },
139 + 'delete' : function (stopHere) {
140 + delete state.parent.node[state.key];
141 + if (stopHere) keepGoing = false;
142 + },
143 + remove : function (stopHere) {
144 + if (isArray(state.parent.node)) {
145 + state.parent.node.splice(state.key, 1);
146 + }
147 + else {
148 + delete state.parent.node[state.key];
149 + }
150 + if (stopHere) keepGoing = false;
151 + },
152 + keys : null,
153 + before : function (f) { modifiers.before = f },
154 + after : function (f) { modifiers.after = f },
155 + pre : function (f) { modifiers.pre = f },
156 + post : function (f) { modifiers.post = f },
157 + stop : function () { alive = false },
158 + block : function () { keepGoing = false }
159 + };
160 +
161 + if (!alive) return state;
162 +
163 + function updateState() {
164 + if (typeof state.node === 'object' && state.node !== null) {
165 + if (!state.keys || state.node_ !== state.node) {
166 + state.keys = objectKeys(state.node)
167 + }
168 +
169 + state.isLeaf = state.keys.length == 0;
170 +
171 + for (var i = 0; i < parents.length; i++) {
172 + if (parents[i].node_ === node_) {
173 + state.circular = parents[i];
174 + break;
175 + }
176 + }
177 + }
178 + else {
179 + state.isLeaf = true;
180 + state.keys = null;
181 + }
182 +
183 + state.notLeaf = !state.isLeaf;
184 + state.notRoot = !state.isRoot;
185 + }
186 +
187 + updateState();
188 +
189 + // use return values to update if defined
190 + var ret = cb.call(state, state.node);
191 + if (ret !== undefined && state.update) state.update(ret);
192 +
193 + if (modifiers.before) modifiers.before.call(state, state.node);
194 +
195 + if (!keepGoing) return state;
196 +
197 + if (typeof state.node == 'object'
198 + && state.node !== null && !state.circular) {
199 + parents.push(state);
200 +
201 + updateState();
202 +
203 + forEach(state.keys, function (key, i) {
204 + path.push(key);
205 +
206 + if (modifiers.pre) modifiers.pre.call(state, state.node[key], key);
207 +
208 + var child = walker(state.node[key]);
209 + if (immutable && hasOwnProperty.call(state.node, key)) {
210 + state.node[key] = child.node;
211 + }
212 +
213 + child.isLast = i == state.keys.length - 1;
214 + child.isFirst = i == 0;
215 +
216 + if (modifiers.post) modifiers.post.call(state, child);
217 +
218 + path.pop();
219 + });
220 + parents.pop();
221 + }
222 +
223 + if (modifiers.after) modifiers.after.call(state, state.node);
224 +
225 + return state;
226 + })(root).node;
227 +}
228 +
229 +function copy (src) {
230 + if (typeof src === 'object' && src !== null) {
231 + var dst;
232 +
233 + if (isArray(src)) {
234 + dst = [];
235 + }
236 + else if (isDate(src)) {
237 + dst = new Date(src.getTime ? src.getTime() : src);
238 + }
239 + else if (isRegExp(src)) {
240 + dst = new RegExp(src);
241 + }
242 + else if (isError(src)) {
243 + dst = { message: src.message };
244 + }
245 + else if (isBoolean(src)) {
246 + dst = new Boolean(src);
247 + }
248 + else if (isNumber(src)) {
249 + dst = new Number(src);
250 + }
251 + else if (isString(src)) {
252 + dst = new String(src);
253 + }
254 + else if (Object.create && Object.getPrototypeOf) {
255 + dst = Object.create(Object.getPrototypeOf(src));
256 + }
257 + else if (src.constructor === Object) {
258 + dst = {};
259 + }
260 + else {
261 + var proto =
262 + (src.constructor && src.constructor.prototype)
263 + || src.__proto__
264 + || {}
265 + ;
266 + var T = function () {};
267 + T.prototype = proto;
268 + dst = new T;
269 + }
270 +
271 + forEach(objectKeys(src), function (key) {
272 + dst[key] = src[key];
273 + });
274 + return dst;
275 + }
276 + else return src;
277 +}
278 +
279 +var objectKeys = Object.keys || function keys (obj) {
280 + var res = [];
281 + for (var key in obj) res.push(key)
282 + return res;
283 +};
284 +
285 +function toS (obj) { return Object.prototype.toString.call(obj) }
286 +function isDate (obj) { return toS(obj) === '[object Date]' }
287 +function isRegExp (obj) { return toS(obj) === '[object RegExp]' }
288 +function isError (obj) { return toS(obj) === '[object Error]' }
289 +function isBoolean (obj) { return toS(obj) === '[object Boolean]' }
290 +function isNumber (obj) { return toS(obj) === '[object Number]' }
291 +function isString (obj) { return toS(obj) === '[object String]' }
292 +
293 +var isArray = Array.isArray || function isArray (xs) {
294 + return Object.prototype.toString.call(xs) === '[object Array]';
295 +};
296 +
297 +var forEach = function (xs, fn) {
298 + if (xs.forEach) return xs.forEach(fn)
299 + else for (var i = 0; i < xs.length; i++) {
300 + fn(xs[i], i, xs);
301 + }
302 +};
303 +
304 +forEach(objectKeys(Traverse.prototype), function (key) {
305 + traverse[key] = function (obj) {
306 + var args = [].slice.call(arguments, 1);
307 + var t = new Traverse(obj);
308 + return t[key].apply(t, args);
309 + };
310 +});
311 +
312 +var hasOwnProperty = Object.hasOwnProperty || function (obj, key) {
313 + return key in obj;
314 +};
1 +{
2 + "_from": "traverse@>=0.2.4",
3 + "_id": "traverse@0.6.6",
4 + "_inBundle": false,
5 + "_integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=",
6 + "_location": "/traverse",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "range",
10 + "registry": true,
11 + "raw": "traverse@>=0.2.4",
12 + "name": "traverse",
13 + "escapedName": "traverse",
14 + "rawSpec": ">=0.2.4",
15 + "saveSpec": null,
16 + "fetchSpec": ">=0.2.4"
17 + },
18 + "_requiredBy": [
19 + "/hashish"
20 + ],
21 + "_resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz",
22 + "_shasum": "cbdf560fd7b9af632502fed40f918c157ea97137",
23 + "_spec": "traverse@>=0.2.4",
24 + "_where": "C:\\Users\\user\\Desktop\\오소git\\오소플젝\\Youtube_MPL\\node_modules\\hashish",
25 + "author": {
26 + "name": "James Halliday",
27 + "email": "mail@substack.net",
28 + "url": "http://substack.net"
29 + },
30 + "bugs": {
31 + "url": "https://github.com/substack/js-traverse/issues"
32 + },
33 + "bundleDependencies": false,
34 + "deprecated": false,
35 + "description": "traverse and transform objects by visiting every node on a recursive walk",
36 + "devDependencies": {
37 + "tape": "~1.0.4"
38 + },
39 + "directories": {
40 + "example": "example",
41 + "test": "test"
42 + },
43 + "homepage": "https://github.com/substack/js-traverse",
44 + "keywords": [
45 + "traverse",
46 + "walk",
47 + "recursive",
48 + "map",
49 + "forEach",
50 + "deep",
51 + "clone"
52 + ],
53 + "license": "MIT",
54 + "main": "index.js",
55 + "name": "traverse",
56 + "repository": {
57 + "type": "git",
58 + "url": "git://github.com/substack/js-traverse.git"
59 + },
60 + "scripts": {
61 + "test": "tape test/*.js"
62 + },
63 + "testling": {
64 + "files": "test/*.js",
65 + "browsers": {
66 + "iexplore": [
67 + "6.0",
68 + "7.0",
69 + "8.0",
70 + "9.0"
71 + ],
72 + "chrome": [
73 + "10.0",
74 + "20.0"
75 + ],
76 + "firefox": [
77 + "10.0",
78 + "15.0"
79 + ],
80 + "safari": [
81 + "5.1"
82 + ],
83 + "opera": [
84 + "12.0"
85 + ]
86 + }
87 + },
88 + "version": "0.6.6"
89 +}
1 +# traverse
2 +
3 +Traverse and transform objects by visiting every node on a recursive walk.
4 +
5 +[![browser support](http://ci.testling.com/substack/js-traverse.png)](http://ci.testling.com/substack/js-traverse)
6 +
7 +[![build status](https://secure.travis-ci.org/substack/js-traverse.png)](http://travis-ci.org/substack/js-traverse)
8 +
9 +# examples
10 +
11 +## transform negative numbers in-place
12 +
13 +negative.js
14 +
15 +````javascript
16 +var traverse = require('traverse');
17 +var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
18 +
19 +traverse(obj).forEach(function (x) {
20 + if (x < 0) this.update(x + 128);
21 +});
22 +
23 +console.dir(obj);
24 +````
25 +
26 +Output:
27 +
28 + [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ]
29 +
30 +## collect leaf nodes
31 +
32 +leaves.js
33 +
34 +````javascript
35 +var traverse = require('traverse');
36 +
37 +var obj = {
38 + a : [1,2,3],
39 + b : 4,
40 + c : [5,6],
41 + d : { e : [7,8], f : 9 },
42 +};
43 +
44 +var leaves = traverse(obj).reduce(function (acc, x) {
45 + if (this.isLeaf) acc.push(x);
46 + return acc;
47 +}, []);
48 +
49 +console.dir(leaves);
50 +````
51 +
52 +Output:
53 +
54 + [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
55 +
56 +## scrub circular references
57 +
58 +scrub.js:
59 +
60 +````javascript
61 +var traverse = require('traverse');
62 +
63 +var obj = { a : 1, b : 2, c : [ 3, 4 ] };
64 +obj.c.push(obj);
65 +
66 +var scrubbed = traverse(obj).map(function (x) {
67 + if (this.circular) this.remove()
68 +});
69 +console.dir(scrubbed);
70 +````
71 +
72 +output:
73 +
74 + { a: 1, b: 2, c: [ 3, 4 ] }
75 +
76 +# methods
77 +
78 +Each method that takes an `fn` uses the context documented below in the context
79 +section.
80 +
81 +## .map(fn)
82 +
83 +Execute `fn` for each node in the object and return a new object with the
84 +results of the walk. To update nodes in the result use `this.update(value)`.
85 +
86 +## .forEach(fn)
87 +
88 +Execute `fn` for each node in the object but unlike `.map()`, when
89 +`this.update()` is called it updates the object in-place.
90 +
91 +## .reduce(fn, acc)
92 +
93 +For each node in the object, perform a
94 +[left-fold](http://en.wikipedia.org/wiki/Fold_(higher-order_function))
95 +with the return value of `fn(acc, node)`.
96 +
97 +If `acc` isn't specified, `acc` is set to the root object for the first step
98 +and the root element is skipped.
99 +
100 +## .paths()
101 +
102 +Return an `Array` of every possible non-cyclic path in the object.
103 +Paths are `Array`s of string keys.
104 +
105 +## .nodes()
106 +
107 +Return an `Array` of every node in the object.
108 +
109 +## .clone()
110 +
111 +Create a deep clone of the object.
112 +
113 +## .get(path)
114 +
115 +Get the element at the array `path`.
116 +
117 +## .set(path, value)
118 +
119 +Set the element at the array `path` to `value`.
120 +
121 +## .has(path)
122 +
123 +Return whether the element at the array `path` exists.
124 +
125 +# context
126 +
127 +Each method that takes a callback has a context (its `this` object) with these
128 +attributes:
129 +
130 +## this.node
131 +
132 +The present node on the recursive walk
133 +
134 +## this.path
135 +
136 +An array of string keys from the root to the present node
137 +
138 +## this.parent
139 +
140 +The context of the node's parent.
141 +This is `undefined` for the root node.
142 +
143 +## this.key
144 +
145 +The name of the key of the present node in its parent.
146 +This is `undefined` for the root node.
147 +
148 +## this.isRoot, this.notRoot
149 +
150 +Whether the present node is the root node
151 +
152 +## this.isLeaf, this.notLeaf
153 +
154 +Whether or not the present node is a leaf node (has no children)
155 +
156 +## this.level
157 +
158 +Depth of the node within the traversal
159 +
160 +## this.circular
161 +
162 +If the node equals one of its parents, the `circular` attribute is set to the
163 +context of that parent and the traversal progresses no deeper.
164 +
165 +## this.update(value, stopHere=false)
166 +
167 +Set a new value for the present node.
168 +
169 +All the elements in `value` will be recursively traversed unless `stopHere` is
170 +true.
171 +
172 +## this.remove(stopHere=false)
173 +
174 +Remove the current element from the output. If the node is in an Array it will
175 +be spliced off. Otherwise it will be deleted from its parent.
176 +
177 +## this.delete(stopHere=false)
178 +
179 +Delete the current element from its parent in the output. Calls `delete` even on
180 +Arrays.
181 +
182 +## this.before(fn)
183 +
184 +Call this function before any of the children are traversed.
185 +
186 +You can assign into `this.keys` here to traverse in a custom order.
187 +
188 +## this.after(fn)
189 +
190 +Call this function after any of the children are traversed.
191 +
192 +## this.pre(fn)
193 +
194 +Call this function before each of the children are traversed.
195 +
196 +## this.post(fn)
197 +
198 +Call this function after each of the children are traversed.
199 +
200 +
201 +# install
202 +
203 +Using [npm](http://npmjs.org) do:
204 +
205 + $ npm install traverse
206 +
207 +# license
208 +
209 +MIT
1 +var test = require('tape');
2 +var traverse = require('../');
3 +var deepEqual = require('./lib/deep_equal');
4 +var util = require('util');
5 +
6 +test('circular', function (t) {
7 + t.plan(1);
8 +
9 + var obj = { x : 3 };
10 + obj.y = obj;
11 + traverse(obj).forEach(function (x) {
12 + if (this.path.join('') == 'y') {
13 + t.equal(
14 + util.inspect(this.circular.node),
15 + util.inspect(obj)
16 + );
17 + }
18 + });
19 +});
20 +
21 +test('deepCirc', function (t) {
22 + t.plan(2);
23 + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
24 + obj.y[2] = obj;
25 +
26 + var times = 0;
27 + traverse(obj).forEach(function (x) {
28 + if (this.circular) {
29 + t.same(this.circular.path, []);
30 + t.same(this.path, [ 'y', 2 ]);
31 + }
32 + });
33 +});
34 +
35 +test('doubleCirc', function (t) {
36 + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
37 + obj.y[2] = obj;
38 + obj.x.push(obj.y);
39 +
40 + var circs = [];
41 + traverse(obj).forEach(function (x) {
42 + if (this.circular) {
43 + circs.push({ circ : this.circular, self : this, node : x });
44 + }
45 + });
46 +
47 + t.same(circs[0].self.path, [ 'x', 3, 2 ]);
48 + t.same(circs[0].circ.path, []);
49 +
50 + t.same(circs[1].self.path, [ 'y', 2 ]);
51 + t.same(circs[1].circ.path, []);
52 +
53 + t.same(circs.length, 2);
54 + t.end();
55 +});
56 +
57 +test('circDubForEach', function (t) {
58 + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
59 + obj.y[2] = obj;
60 + obj.x.push(obj.y);
61 +
62 + traverse(obj).forEach(function (x) {
63 + if (this.circular) this.update('...');
64 + });
65 +
66 + t.same(obj, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] });
67 + t.end();
68 +});
69 +
70 +test('circDubMap', function (t) {
71 + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
72 + obj.y[2] = obj;
73 + obj.x.push(obj.y);
74 +
75 + var c = traverse(obj).map(function (x) {
76 + if (this.circular) {
77 + this.update('...');
78 + }
79 + });
80 +
81 + t.same(c, { x : [ 1, 2, 3, [ 4, 5, '...' ] ], y : [ 4, 5, '...' ] });
82 + t.end();
83 +});
84 +
85 +test('circClone', function (t) {
86 + var obj = { x : [ 1, 2, 3 ], y : [ 4, 5 ] };
87 + obj.y[2] = obj;
88 + obj.x.push(obj.y);
89 +
90 + var clone = traverse.clone(obj);
91 + t.ok(obj !== clone);
92 +
93 + t.ok(clone.y[2] === clone);
94 + t.ok(clone.y[2] !== obj);
95 + t.ok(clone.x[3][2] === clone);
96 + t.ok(clone.x[3][2] !== obj);
97 + t.same(clone.x.slice(0,3), [1,2,3]);
98 + t.same(clone.y.slice(0,2), [4,5]);
99 + t.end();
100 +});
101 +
102 +test('circMapScrub', function (t) {
103 + var obj = { a : 1, b : 2 };
104 + obj.c = obj;
105 +
106 + var scrubbed = traverse(obj).map(function (node) {
107 + if (this.circular) this.remove();
108 + });
109 + t.same(
110 + Object.keys(scrubbed).sort(),
111 + [ 'a', 'b' ]
112 + );
113 + t.ok(deepEqual(scrubbed, { a : 1, b : 2 }));
114 +
115 + t.equal(obj.c, obj);
116 + t.end();
117 +});
1 +var test = require('tape');
2 +var traverse = require('../');
3 +
4 +test('dateEach', function (t) {
5 + var obj = { x : new Date, y : 10, z : 5 };
6 +
7 + var counts = {};
8 +
9 + traverse(obj).forEach(function (node) {
10 + var t = (node instanceof Date && 'Date') || typeof node;
11 + counts[t] = (counts[t] || 0) + 1;
12 + });
13 +
14 + t.same(counts, {
15 + object : 1,
16 + Date : 1,
17 + number : 2,
18 + });
19 + t.end();
20 +});
21 +
22 +test('dateMap', function (t) {
23 + var obj = { x : new Date, y : 10, z : 5 };
24 +
25 + var res = traverse(obj).map(function (node) {
26 + if (typeof node === 'number') this.update(node + 100);
27 + });
28 +
29 + t.ok(obj.x !== res.x);
30 + t.same(res, {
31 + x : obj.x,
32 + y : 110,
33 + z : 105,
34 + });
35 + t.end();
36 +});
37 +
1 +var test = require('tape');
2 +var traverse = require('../');
3 +var deepEqual = require('./lib/deep_equal');
4 +
5 +test('deepDates', function (t) {
6 + t.plan(2);
7 +
8 + t.ok(
9 + deepEqual(
10 + { d : new Date, x : [ 1, 2, 3 ] },
11 + { d : new Date, x : [ 1, 2, 3 ] }
12 + ),
13 + 'dates should be equal'
14 + );
15 +
16 + var d0 = new Date;
17 + setTimeout(function () {
18 + t.ok(
19 + !deepEqual(
20 + { d : d0, x : [ 1, 2, 3 ], },
21 + { d : new Date, x : [ 1, 2, 3 ] }
22 + ),
23 + 'microseconds should count in date equality'
24 + );
25 + }, 5);
26 +});
27 +
28 +test('deepCircular', function (t) {
29 + var a = [1];
30 + a.push(a); // a = [ 1, *a ]
31 +
32 + var b = [1];
33 + b.push(a); // b = [ 1, [ 1, *a ] ]
34 +
35 + t.ok(
36 + !deepEqual(a, b),
37 + 'circular ref mount points count towards equality'
38 + );
39 +
40 + var c = [1];
41 + c.push(c); // c = [ 1, *c ]
42 + t.ok(
43 + deepEqual(a, c),
44 + 'circular refs are structurally the same here'
45 + );
46 +
47 + var d = [1];
48 + d.push(a); // c = [ 1, [ 1, *d ] ]
49 + t.ok(
50 + deepEqual(b, d),
51 + 'non-root circular ref structural comparison'
52 + );
53 +
54 + t.end();
55 +});
56 +
57 +test('deepInstances', function (t) {
58 + t.ok(
59 + !deepEqual([ new Boolean(false) ], [ false ]),
60 + 'boolean instances are not real booleans'
61 + );
62 +
63 + t.ok(
64 + !deepEqual([ new String('x') ], [ 'x' ]),
65 + 'string instances are not real strings'
66 + );
67 +
68 + t.ok(
69 + !deepEqual([ new Number(4) ], [ 4 ]),
70 + 'number instances are not real numbers'
71 + );
72 +
73 + t.ok(
74 + deepEqual([ new RegExp('x') ], [ /x/ ]),
75 + 'regexp instances are real regexps'
76 + );
77 +
78 + t.ok(
79 + !deepEqual([ new RegExp(/./) ], [ /../ ]),
80 + 'these regexps aren\'t the same'
81 + );
82 +
83 + t.ok(
84 + !deepEqual(
85 + [ function (x) { return x * 2 } ],
86 + [ function (x) { return x * 2 } ]
87 + ),
88 + 'functions with the same .toString() aren\'t necessarily the same'
89 + );
90 +
91 + var f = function (x) { return x * 2 };
92 + t.ok(
93 + deepEqual([ f ], [ f ]),
94 + 'these functions are actually equal'
95 + );
96 +
97 + t.end();
98 +});
99 +
100 +test('deepEqual', function (t) {
101 + t.ok(
102 + !deepEqual([ 1, 2, 3 ], { 0 : 1, 1 : 2, 2 : 3 }),
103 + 'arrays are not objects'
104 + );
105 + t.end();
106 +});
107 +
108 +test('falsy', function (t) {
109 + t.ok(
110 + !deepEqual([ undefined ], [ null ]),
111 + 'null is not undefined!'
112 + );
113 +
114 + t.ok(
115 + !deepEqual([ null ], [ undefined ]),
116 + 'undefined is not null!'
117 + );
118 +
119 + t.ok(
120 + !deepEqual(
121 + { a : 1, b : 2, c : [ 3, undefined, 5 ] },
122 + { a : 1, b : 2, c : [ 3, null, 5 ] }
123 + ),
124 + 'undefined is not null, however deeply!'
125 + );
126 +
127 + t.ok(
128 + !deepEqual(
129 + { a : 1, b : 2, c : [ 3, undefined, 5 ] },
130 + { a : 1, b : 2, c : [ 3, null, 5 ] }
131 + ),
132 + 'null is not undefined, however deeply!'
133 + );
134 +
135 + t.ok(
136 + !deepEqual(
137 + { a : 1, b : 2, c : [ 3, undefined, 5 ] },
138 + { a : 1, b : 2, c : [ 3, null, 5 ] }
139 + ),
140 + 'null is not undefined, however deeply!'
141 + );
142 +
143 + t.end();
144 +});
145 +
146 +test('deletedArrayEqual', function (t) {
147 + var xs = [ 1, 2, 3, 4 ];
148 + delete xs[2];
149 +
150 + var ys = Object.create(Array.prototype);
151 + ys[0] = 1;
152 + ys[1] = 2;
153 + ys[3] = 4;
154 +
155 + t.ok(
156 + deepEqual(xs, ys),
157 + 'arrays with deleted elements are only equal to'
158 + + ' arrays with similarly deleted elements'
159 + );
160 +
161 + t.ok(
162 + !deepEqual(xs, [ 1, 2, undefined, 4 ]),
163 + 'deleted array elements cannot be undefined'
164 + );
165 +
166 + t.ok(
167 + !deepEqual(xs, [ 1, 2, null, 4 ]),
168 + 'deleted array elements cannot be null'
169 + );
170 +
171 + t.end();
172 +});
173 +
174 +test('deletedObjectEqual', function (t) {
175 + var obj = { a : 1, b : 2, c : 3 };
176 + delete obj.c;
177 +
178 + t.ok(
179 + deepEqual(obj, { a : 1, b : 2 }),
180 + 'deleted object elements should not show up'
181 + );
182 +
183 + t.ok(
184 + !deepEqual(obj, { a : 1, b : 2, c : undefined }),
185 + 'deleted object elements are not undefined'
186 + );
187 +
188 + t.ok(
189 + !deepEqual(obj, { a : 1, b : 2, c : null }),
190 + 'deleted object elements are not null'
191 + );
192 +
193 + t.end();
194 +});
195 +
196 +test('emptyKeyEqual', function (t) {
197 + t.ok(!deepEqual(
198 + { a : 1 }, { a : 1, '' : 55 }
199 + ));
200 +
201 + t.end();
202 +});
203 +
204 +test('deepArguments', function (t) {
205 + t.ok(
206 + !deepEqual(
207 + [ 4, 5, 6 ],
208 + (function () { return arguments })(4, 5, 6)
209 + ),
210 + 'arguments are not arrays'
211 + );
212 +
213 + t.ok(
214 + deepEqual(
215 + (function () { return arguments })(4, 5, 6),
216 + (function () { return arguments })(4, 5, 6)
217 + ),
218 + 'arguments should equal'
219 + );
220 +
221 + t.end();
222 +});
223 +
224 +test('deepUn', function (t) {
225 + t.ok(!deepEqual({ a : 1, b : 2 }, undefined));
226 + t.ok(!deepEqual({ a : 1, b : 2 }, {}));
227 + t.ok(!deepEqual(undefined, { a : 1, b : 2 }));
228 + t.ok(!deepEqual({}, { a : 1, b : 2 }));
229 + t.ok(deepEqual(undefined, undefined));
230 + t.ok(deepEqual(null, null));
231 + t.ok(!deepEqual(undefined, null));
232 +
233 + t.end();
234 +});
235 +
236 +test('deepLevels', function (t) {
237 + var xs = [ 1, 2, [ 3, 4, [ 5, 6 ] ] ];
238 + t.ok(!deepEqual(xs, []));
239 + t.end();
240 +});
1 +var test = require('tape');
2 +var traverse = require('../');
3 +
4 +test('traverse an Error', function (t) {
5 + var obj = new Error("test");
6 + var results = traverse(obj).map(function (node) {});
7 + t.same(results, { message: 'test' });
8 +
9 + t.end();
10 +});
11 +
1 +var test = require('tape');
2 +var traverse = require('../');
3 +
4 +test('has', function (t) {
5 + var obj = { a : 2, b : [ 4, 5, { c : 6 } ] };
6 +
7 + t.equal(traverse(obj).has([ 'b', 2, 'c' ]), true)
8 + t.equal(traverse(obj).has([ 'b', 2, 'c', 0 ]), false)
9 + t.equal(traverse(obj).has([ 'b', 2, 'd' ]), false)
10 + t.equal(traverse(obj).has([]), true)
11 + t.equal(traverse(obj).has([ 'a' ]), true)
12 + t.equal(traverse(obj).has([ 'a', 2 ]), false)
13 +
14 + t.end();
15 +});
1 +var test = require('tape');
2 +var traverse = require('../');
3 +var EventEmitter = require('events').EventEmitter;
4 +
5 +test('check instanceof on node elems', function (t) {
6 + var counts = { emitter : 0 };
7 +
8 + traverse([ new EventEmitter, 3, 4, { ev : new EventEmitter }])
9 + .forEach(function (node) {
10 + if (node instanceof EventEmitter) counts.emitter ++;
11 + })
12 + ;
13 +
14 + t.equal(counts.emitter, 2);
15 +
16 + t.end();
17 +});
1 +var test = require('tape');
2 +var traverse = require('../');
3 +
4 +test('interface map', function (t) {
5 + var obj = { a : [ 5,6,7 ], b : { c : [8] } };
6 +
7 + t.same(
8 + traverse.paths(obj)
9 + .sort()
10 + .map(function (path) { return path.join('/') })
11 + .slice(1)
12 + .join(' ')
13 + ,
14 + 'a a/0 a/1 a/2 b b/c b/c/0'
15 + );
16 +
17 + t.same(
18 + traverse.nodes(obj),
19 + [
20 + { a: [ 5, 6, 7 ], b: { c: [ 8 ] } },
21 + [ 5, 6, 7 ], 5, 6, 7,
22 + { c: [ 8 ] }, [ 8 ], 8
23 + ]
24 + );
25 +
26 + t.same(
27 + traverse.map(obj, function (node) {
28 + if (typeof node == 'number') {
29 + return node + 1000;
30 + }
31 + else if (Array.isArray(node)) {
32 + return node.join(' ');
33 + }
34 + }),
35 + { a: '5 6 7', b: { c: '8' } }
36 + );
37 +
38 + var nodes = 0;
39 + traverse.forEach(obj, function (node) { nodes ++ });
40 + t.same(nodes, 8);
41 +
42 + t.end();
43 +});
1 +var test = require('tape');
2 +var traverse = require('../');
3 +
4 +test('json test', function (t) {
5 + var id = 54;
6 + var callbacks = {};
7 + var obj = { moo : function () {}, foo : [2,3,4, function () {}] };
8 +
9 + var scrubbed = traverse(obj).map(function (x) {
10 + if (typeof x === 'function') {
11 + callbacks[id] = { id : id, f : x, path : this.path };
12 + this.update('[Function]');
13 + id++;
14 + }
15 + });
16 +
17 + t.equal(
18 + scrubbed.moo, '[Function]',
19 + 'obj.moo replaced with "[Function]"'
20 + );
21 +
22 + t.equal(
23 + scrubbed.foo[3], '[Function]',
24 + 'obj.foo[3] replaced with "[Function]"'
25 + );
26 +
27 + t.same(scrubbed, {
28 + moo : '[Function]',
29 + foo : [ 2, 3, 4, "[Function]" ]
30 + }, 'Full JSON string matches');
31 +
32 + t.same(
33 + typeof obj.moo, 'function',
34 + 'Original obj.moo still a function'
35 + );
36 +
37 + t.same(
38 + typeof obj.foo[3], 'function',
39 + 'Original obj.foo[3] still a function'
40 + );
41 +
42 + t.same(callbacks, {
43 + 54: { id: 54, f : obj.moo, path: [ 'moo' ] },
44 + 55: { id: 55, f : obj.foo[3], path: [ 'foo', '3' ] },
45 + }, 'Check the generated callbacks list');
46 +
47 + t.end();
48 +});
49 +
1 +var test = require('tape');
2 +var traverse = require('../');
3 +
4 +test('sort test', function (t) {
5 + var acc = [];
6 + traverse({
7 + a: 30,
8 + b: 22,
9 + id: 9
10 + }).forEach(function (node) {
11 + if ((! Array.isArray(node)) && typeof node === 'object') {
12 + this.before(function(node) {
13 + this.keys = Object.keys(node);
14 + this.keys.sort(function(a, b) {
15 + a = [a === "id" ? 0 : 1, a];
16 + b = [b === "id" ? 0 : 1, b];
17 + return a < b ? -1 : a > b ? 1 : 0;
18 + });
19 + });
20 + }
21 + if (this.isLeaf) acc.push(node);
22 + });
23 +
24 + t.equal(
25 + acc.join(' '),
26 + '9 30 22',
27 + 'Traversal in a custom order'
28 + );
29 +
30 + t.end();
31 +});
1 +var test = require('tape');
2 +var traverse = require('../');
3 +
4 +test('leaves test', function (t) {
5 + var acc = [];
6 + traverse({
7 + a : [1,2,3],
8 + b : 4,
9 + c : [5,6],
10 + d : { e : [7,8], f : 9 }
11 + }).forEach(function (x) {
12 + if (this.isLeaf) acc.push(x);
13 + });
14 +
15 + t.equal(
16 + acc.join(' '),
17 + '1 2 3 4 5 6 7 8 9',
18 + 'Traversal in the right(?) order'
19 + );
20 +
21 + t.end();
22 +});
1 +var traverse = require('../../');
2 +
3 +module.exports = function (a, b) {
4 + if (arguments.length !== 2) {
5 + throw new Error(
6 + 'deepEqual requires exactly two objects to compare against'
7 + );
8 + }
9 +
10 + var equal = true;
11 + var node = b;
12 +
13 + traverse(a).forEach(function (y) {
14 + var notEqual = (function () {
15 + equal = false;
16 + //this.stop();
17 + return undefined;
18 + }).bind(this);
19 +
20 + //if (node === undefined || node === null) return notEqual();
21 +
22 + if (!this.isRoot) {
23 + /*
24 + if (!Object.hasOwnProperty.call(node, this.key)) {
25 + return notEqual();
26 + }
27 + */
28 + if (typeof node !== 'object') return notEqual();
29 + node = node[this.key];
30 + }
31 +
32 + var x = node;
33 +
34 + this.post(function () {
35 + node = x;
36 + });
37 +
38 + var toS = function (o) {
39 + return Object.prototype.toString.call(o);
40 + };
41 +
42 + if (this.circular) {
43 + if (traverse(b).get(this.circular.path) !== x) notEqual();
44 + }
45 + else if (typeof x !== typeof y) {
46 + notEqual();
47 + }
48 + else if (x === null || y === null || x === undefined || y === undefined) {
49 + if (x !== y) notEqual();
50 + }
51 + else if (x.__proto__ !== y.__proto__) {
52 + notEqual();
53 + }
54 + else if (x === y) {
55 + // nop
56 + }
57 + else if (typeof x === 'function') {
58 + if (x instanceof RegExp) {
59 + // both regexps on account of the __proto__ check
60 + if (x.toString() != y.toString()) notEqual();
61 + }
62 + else if (x !== y) notEqual();
63 + }
64 + else if (typeof x === 'object') {
65 + if (toS(y) === '[object Arguments]'
66 + || toS(x) === '[object Arguments]') {
67 + if (toS(x) !== toS(y)) {
68 + notEqual();
69 + }
70 + }
71 + else if (toS(y) === '[object RegExp]'
72 + || toS(x) === '[object RegExp]') {
73 + if (!x || !y || x.toString() !== y.toString()) notEqual();
74 + }
75 + else if (x instanceof Date || y instanceof Date) {
76 + if (!(x instanceof Date) || !(y instanceof Date)
77 + || x.getTime() !== y.getTime()) {
78 + notEqual();
79 + }
80 + }
81 + else {
82 + var kx = Object.keys(x);
83 + var ky = Object.keys(y);
84 + if (kx.length !== ky.length) return notEqual();
85 + for (var i = 0; i < kx.length; i++) {
86 + var k = kx[i];
87 + if (!Object.hasOwnProperty.call(y, k)) {
88 + notEqual();
89 + }
90 + }
91 + }
92 + }
93 + });
94 +
95 + return equal;
96 +};
1 +var test = require('tape');
2 +var traverse = require('../');
3 +var deepEqual = require('./lib/deep_equal');
4 +
5 +test('mutate', function (t) {
6 + var obj = { a : 1, b : 2, c : [ 3, 4 ] };
7 + var res = traverse(obj).forEach(function (x) {
8 + if (typeof x === 'number' && x % 2 === 0) {
9 + this.update(x * 10);
10 + }
11 + });
12 + t.same(obj, res);
13 + t.same(obj, { a : 1, b : 20, c : [ 3, 40 ] });
14 + t.end();
15 +});
16 +
17 +test('mutateT', function (t) {
18 + var obj = { a : 1, b : 2, c : [ 3, 4 ] };
19 + var res = traverse.forEach(obj, function (x) {
20 + if (typeof x === 'number' && x % 2 === 0) {
21 + this.update(x * 10);
22 + }
23 + });
24 + t.same(obj, res);
25 + t.same(obj, { a : 1, b : 20, c : [ 3, 40 ] });
26 + t.end();
27 +});
28 +
29 +test('map', function (t) {
30 + var obj = { a : 1, b : 2, c : [ 3, 4 ] };
31 + var res = traverse(obj).map(function (x) {
32 + if (typeof x === 'number' && x % 2 === 0) {
33 + this.update(x * 10);
34 + }
35 + });
36 + t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] });
37 + t.same(res, { a : 1, b : 20, c : [ 3, 40 ] });
38 + t.end();
39 +});
40 +
41 +test('mapT', function (t) {
42 + var obj = { a : 1, b : 2, c : [ 3, 4 ] };
43 + var res = traverse.map(obj, function (x) {
44 + if (typeof x === 'number' && x % 2 === 0) {
45 + this.update(x * 10);
46 + }
47 + });
48 + t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] });
49 + t.same(res, { a : 1, b : 20, c : [ 3, 40 ] });
50 + t.end();
51 +});
52 +
53 +test('clone', function (t) {
54 + var obj = { a : 1, b : 2, c : [ 3, 4 ] };
55 + var res = traverse(obj).clone();
56 + t.same(obj, res);
57 + t.ok(obj !== res);
58 + obj.a ++;
59 + t.same(res.a, 1);
60 + obj.c.push(5);
61 + t.same(res.c, [ 3, 4 ]);
62 + t.end();
63 +});
64 +
65 +test('cloneT', function (t) {
66 + var obj = { a : 1, b : 2, c : [ 3, 4 ] };
67 + var res = traverse.clone(obj);
68 + t.same(obj, res);
69 + t.ok(obj !== res);
70 + obj.a ++;
71 + t.same(res.a, 1);
72 + obj.c.push(5);
73 + t.same(res.c, [ 3, 4 ]);
74 + t.end();
75 +});
76 +
77 +test('reduce', function (t) {
78 + var obj = { a : 1, b : 2, c : [ 3, 4 ] };
79 + var res = traverse(obj).reduce(function (acc, x) {
80 + if (this.isLeaf) acc.push(x);
81 + return acc;
82 + }, []);
83 + t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] });
84 + t.same(res, [ 1, 2, 3, 4 ]);
85 + t.end();
86 +});
87 +
88 +test('reduceInit', function (t) {
89 + var obj = { a : 1, b : 2, c : [ 3, 4 ] };
90 + var res = traverse(obj).reduce(function (acc, x) {
91 + if (this.isRoot) assert.fail('got root');
92 + return acc;
93 + });
94 + t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] });
95 + t.same(res, obj);
96 + t.end();
97 +});
98 +
99 +test('remove', function (t) {
100 + var obj = { a : 1, b : 2, c : [ 3, 4 ] };
101 + traverse(obj).forEach(function (x) {
102 + if (this.isLeaf && x % 2 == 0) this.remove();
103 + });
104 +
105 + t.same(obj, { a : 1, c : [ 3 ] });
106 + t.end();
107 +});
108 +
109 +exports.removeNoStop = function() {
110 + var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 };
111 +
112 + var keys = [];
113 + traverse(obj).forEach(function (x) {
114 + keys.push(this.key)
115 + if (this.key == 'c') this.remove();
116 + });
117 +
118 + t.same(keys, [undefined, 'a', 'b', 'c', 'd', 'e', 'f'])
119 + t.end();
120 +}
121 +
122 +exports.removeStop = function() {
123 + var obj = { a : 1, b : 2, c : { d: 3, e: 4 }, f: 5 };
124 +
125 + var keys = [];
126 + traverse(obj).forEach(function (x) {
127 + keys.push(this.key)
128 + if (this.key == 'c') this.remove(true);
129 + });
130 +
131 + t.same(keys, [undefined, 'a', 'b', 'c', 'f'])
132 + t.end();
133 +}
134 +
135 +test('removeMap', function (t) {
136 + var obj = { a : 1, b : 2, c : [ 3, 4 ] };
137 + var res = traverse(obj).map(function (x) {
138 + if (this.isLeaf && x % 2 == 0) this.remove();
139 + });
140 +
141 + t.same(obj, { a : 1, b : 2, c : [ 3, 4 ] });
142 + t.same(res, { a : 1, c : [ 3 ] });
143 + t.end();
144 +});
145 +
146 +test('delete', function (t) {
147 + var obj = { a : 1, b : 2, c : [ 3, 4 ] };
148 + traverse(obj).forEach(function (x) {
149 + if (this.isLeaf && x % 2 == 0) this.delete();
150 + });
151 +
152 + t.ok(!deepEqual(
153 + obj, { a : 1, c : [ 3, undefined ] }
154 + ));
155 +
156 + t.ok(deepEqual(
157 + obj, { a : 1, c : [ 3 ] }
158 + ));
159 +
160 + t.ok(!deepEqual(
161 + obj, { a : 1, c : [ 3, null ] }
162 + ));
163 + t.end();
164 +});
165 +
166 +test('deleteNoStop', function (t) {
167 + var obj = { a : 1, b : 2, c : { d: 3, e: 4 } };
168 +
169 + var keys = [];
170 + traverse(obj).forEach(function (x) {
171 + keys.push(this.key)
172 + if (this.key == 'c') this.delete();
173 + });
174 +
175 + t.same(keys, [undefined, 'a', 'b', 'c', 'd', 'e'])
176 + t.end();
177 +});
178 +
179 +test('deleteStop', function (t) {
180 + var obj = { a : 1, b : 2, c : { d: 3, e: 4 } };
181 +
182 + var keys = [];
183 + traverse(obj).forEach(function (x) {
184 + keys.push(this.key)
185 + if (this.key == 'c') this.delete(true);
186 + });
187 +
188 + t.same(keys, [undefined, 'a', 'b', 'c'])
189 + t.end();
190 +});
191 +
192 +test('deleteRedux', function (t) {
193 + var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] };
194 + traverse(obj).forEach(function (x) {
195 + if (this.isLeaf && x % 2 == 0) this.delete();
196 + });
197 +
198 + t.ok(!deepEqual(
199 + obj, { a : 1, c : [ 3, undefined, 5 ] }
200 + ));
201 +
202 + t.ok(deepEqual(
203 + obj, { a : 1, c : [ 3 ,, 5 ] }
204 + ));
205 +
206 + t.ok(!deepEqual(
207 + obj, { a : 1, c : [ 3, null, 5 ] }
208 + ));
209 +
210 + t.ok(!deepEqual(
211 + obj, { a : 1, c : [ 3, 5 ] }
212 + ));
213 +
214 + t.end();
215 +});
216 +
217 +test('deleteMap', function (t) {
218 + var obj = { a : 1, b : 2, c : [ 3, 4 ] };
219 + var res = traverse(obj).map(function (x) {
220 + if (this.isLeaf && x % 2 == 0) this.delete();
221 + });
222 +
223 + t.ok(deepEqual(
224 + obj,
225 + { a : 1, b : 2, c : [ 3, 4 ] }
226 + ));
227 +
228 + var xs = [ 3, 4 ];
229 + delete xs[1];
230 +
231 + t.ok(deepEqual(
232 + res, { a : 1, c : xs }
233 + ));
234 +
235 + t.ok(deepEqual(
236 + res, { a : 1, c : [ 3, ] }
237 + ));
238 +
239 + t.ok(deepEqual(
240 + res, { a : 1, c : [ 3 ] }
241 + ));
242 +
243 + t.end();
244 +});
245 +
246 +test('deleteMapRedux', function (t) {
247 + var obj = { a : 1, b : 2, c : [ 3, 4, 5 ] };
248 + var res = traverse(obj).map(function (x) {
249 + if (this.isLeaf && x % 2 == 0) this.delete();
250 + });
251 +
252 + t.ok(deepEqual(
253 + obj,
254 + { a : 1, b : 2, c : [ 3, 4, 5 ] }
255 + ));
256 +
257 + var xs = [ 3, 4, 5 ];
258 + delete xs[1];
259 +
260 + t.ok(deepEqual(
261 + res, { a : 1, c : xs }
262 + ));
263 +
264 + t.ok(!deepEqual(
265 + res, { a : 1, c : [ 3, 5 ] }
266 + ));
267 +
268 + t.ok(deepEqual(
269 + res, { a : 1, c : [ 3 ,, 5 ] }
270 + ));
271 +
272 + t.end();
273 +});
274 +
275 +test('objectToString', function (t) {
276 + var obj = { a : 1, b : 2, c : [ 3, 4 ] };
277 + var res = traverse(obj).forEach(function (x) {
278 + if (typeof x === 'object' && !this.isRoot) {
279 + this.update(JSON.stringify(x));
280 + }
281 + });
282 + t.same(obj, res);
283 + t.same(obj, { a : 1, b : 2, c : "[3,4]" });
284 + t.end();
285 +});
286 +
287 +test('stringToObject', function (t) {
288 + var obj = { a : 1, b : 2, c : "[3,4]" };
289 + var res = traverse(obj).forEach(function (x) {
290 + if (typeof x === 'string') {
291 + this.update(JSON.parse(x));
292 + }
293 + else if (typeof x === 'number' && x % 2 === 0) {
294 + this.update(x * 10);
295 + }
296 + });
297 + t.deepEqual(obj, res);
298 + t.deepEqual(obj, { a : 1, b : 20, c : [ 3, 40 ] });
299 + t.end();
300 +});
1 +var traverse = require('../');
2 +var test = require('tape');
3 +
4 +test('negative update test', function (t) {
5 + var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
6 + var fixed = traverse.map(obj, function (x) {
7 + if (x < 0) this.update(x + 128);
8 + });
9 +
10 + t.same(fixed,
11 + [ 5, 6, 125, [ 7, 8, 126, 1 ], { f: 10, g: 115 } ],
12 + 'Negative values += 128'
13 + );
14 +
15 + t.same(obj,
16 + [ 5, 6, -3, [ 7, 8, -2, 1 ], { f: 10, g: -13 } ],
17 + 'Original references not modified'
18 + );
19 +
20 + t.end();
21 +});
1 +var test = require('tape');
2 +var traverse = require('../');
3 +
4 +test('traverse an object with nested functions', function (t) {
5 + t.plan(1);
6 +
7 + function Cons (x) {
8 + t.equal(x, 10)
9 + };
10 + traverse(new Cons(10));
11 +});
1 +var test = require('tape');
2 +var traverse = require('../');
3 +
4 +test('siblings', function (t) {
5 + var obj = { a : 1, b : 2, c : [ 4, 5, 6 ] };
6 +
7 + var res = traverse(obj).reduce(function (acc, x) {
8 + var p = '/' + this.path.join('/');
9 + if (this.parent) {
10 + acc[p] = {
11 + siblings : this.parent.keys,
12 + key : this.key,
13 + index : this.parent.keys.indexOf(this.key)
14 + };
15 + }
16 + else {
17 + acc[p] = {
18 + siblings : [],
19 + key : this.key,
20 + index : -1
21 + }
22 + }
23 + return acc;
24 + }, {});
25 +
26 + t.same(res, {
27 + '/' : { siblings : [], key : undefined, index : -1 },
28 + '/a' : { siblings : [ 'a', 'b', 'c' ], key : 'a', index : 0 },
29 + '/b' : { siblings : [ 'a', 'b', 'c' ], key : 'b', index : 1 },
30 + '/c' : { siblings : [ 'a', 'b', 'c' ], key : 'c', index : 2 },
31 + '/c/0' : { siblings : [ '0', '1', '2' ], key : '0', index : 0 },
32 + '/c/1' : { siblings : [ '0', '1', '2' ], key : '1', index : 1 },
33 + '/c/2' : { siblings : [ '0', '1', '2' ], key : '2', index : 2 }
34 + });
35 +
36 + t.end();
37 +});
1 +var test = require('tape');
2 +var traverse = require('../');
3 +
4 +test('stop', function (t) {
5 + var visits = 0;
6 + traverse('abcdefghij'.split('')).forEach(function (node) {
7 + if (typeof node === 'string') {
8 + visits ++;
9 + if (node === 'e') this.stop()
10 + }
11 + });
12 +
13 + t.equal(visits, 5);
14 + t.end();
15 +});
16 +
17 +test('stopMap', function (t) {
18 + var s = traverse('abcdefghij'.split('')).map(function (node) {
19 + if (typeof node === 'string') {
20 + if (node === 'e') this.stop()
21 + return node.toUpperCase();
22 + }
23 + }).join('');
24 +
25 + t.equal(s, 'ABCDEfghij');
26 + t.end();
27 +});
28 +
29 +test('stopReduce', function (t) {
30 + var obj = {
31 + a : [ 4, 5 ],
32 + b : [ 6, [ 7, 8, 9 ] ]
33 + };
34 + var xs = traverse(obj).reduce(function (acc, node) {
35 + if (this.isLeaf) {
36 + if (node === 7) this.stop();
37 + else acc.push(node)
38 + }
39 + return acc;
40 + }, []);
41 +
42 + t.same(xs, [ 4, 5, 6 ]);
43 + t.end();
44 +});
1 +var test = require('tape');
2 +var traverse = require('../');
3 +
4 +test('stringify', function (t) {
5 + var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
6 +
7 + var s = '';
8 + traverse(obj).forEach(function (node) {
9 + if (Array.isArray(node)) {
10 + this.before(function () { s += '[' });
11 + this.post(function (child) {
12 + if (!child.isLast) s += ',';
13 + });
14 + this.after(function () { s += ']' });
15 + }
16 + else if (typeof node == 'object') {
17 + this.before(function () { s += '{' });
18 + this.pre(function (x, key) {
19 + s += '"' + key + '"' + ':';
20 + });
21 + this.post(function (child) {
22 + if (!child.isLast) s += ',';
23 + });
24 + this.after(function () { s += '}' });
25 + }
26 + else if (typeof node == 'function') {
27 + s += 'null';
28 + }
29 + else {
30 + s += node.toString();
31 + }
32 + });
33 +
34 + t.equal(s, JSON.stringify(obj));
35 + t.end();
36 +});
1 +var traverse = require('../');
2 +var test = require('tape');
3 +
4 +test('subexpr', function (t) {
5 + var obj = [ 'a', 4, 'b', 5, 'c', 6 ];
6 + var r = traverse(obj).map(function (x) {
7 + if (typeof x === 'number') {
8 + this.update([ x - 0.1, x, x + 0.1 ], true);
9 + }
10 + });
11 +
12 + t.same(obj, [ 'a', 4, 'b', 5, 'c', 6 ]);
13 + t.same(r, [
14 + 'a', [ 3.9, 4, 4.1 ],
15 + 'b', [ 4.9, 5, 5.1 ],
16 + 'c', [ 5.9, 6, 6.1 ],
17 + ]);
18 + t.end();
19 +});
20 +
21 +test('block', function (t) {
22 + var obj = [ [ 1 ], [ 2 ], [ 3 ] ];
23 + var r = traverse(obj).map(function (x) {
24 + if (Array.isArray(x) && !this.isRoot) {
25 + if (x[0] === 5) this.block()
26 + else this.update([ [ x[0] + 1 ] ])
27 + }
28 + });
29 +
30 + t.same(r, [
31 + [ [ [ [ [ 5 ] ] ] ] ],
32 + [ [ [ [ 5 ] ] ] ],
33 + [ [ [ 5 ] ] ],
34 + ]);
35 + t.end();
36 +});
1 +var test = require('tape');
2 +var traverse = require('../');
3 +var deepEqual = require('./lib/deep_equal');
4 +
5 +test('super_deep', function (t) {
6 + var util = require('util');
7 + var a0 = make();
8 + var a1 = make();
9 + t.ok(deepEqual(a0, a1));
10 +
11 + a0.c.d.moo = true;
12 + t.ok(!deepEqual(a0, a1));
13 +
14 + a1.c.d.moo = true;
15 + t.ok(deepEqual(a0, a1));
16 +
17 + // TODO: this one
18 + //a0.c.a = a1;
19 + //t.ok(!deepEqual(a0, a1));
20 + t.end();
21 +});
22 +
23 +function make () {
24 + var a = { self : 'a' };
25 + var b = { self : 'b' };
26 + var c = { self : 'c' };
27 + var d = { self : 'd' };
28 + var e = { self : 'e' };
29 +
30 + a.a = a;
31 + a.b = b;
32 + a.c = c;
33 +
34 + b.a = a;
35 + b.b = b;
36 + b.c = c;
37 +
38 + c.a = a;
39 + c.b = b;
40 + c.c = c;
41 + c.d = d;
42 +
43 + d.a = a;
44 + d.b = b;
45 + d.c = c;
46 + d.d = d;
47 + d.e = e;
48 +
49 + e.a = a;
50 + e.b = b;
51 + e.c = c;
52 + e.d = d;
53 + e.e = e;
54 +
55 + return a;
56 +}
1 +var traverse = require('./');
2 +var test = require('testling');
3 +
4 +test('leaves', function (t) {
5 + var obj = {
6 + a : [1,2,3],
7 + b : 4,
8 + c : [5,6],
9 + d : { e : [7,8], f : 9 }
10 + };
11 +
12 + var acc = [];
13 + traverse(obj).forEach(function (x) {
14 + if (this.isLeaf) acc.push(x);
15 + });
16 +
17 + t.deepEqual(
18 + acc, [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ],
19 + 'traversal in the proper order'
20 + );
21 + t.end();
22 +});
1 +<a name="1.13.1"></a>
2 +## 1.13.1 (2019-02-04)
3 +
4 +* Fixed typo & removed redundant line ([156bbd5](https://github.com/przemyslawpluta/node-youtube-dl/commit/156bbd5))
5 +
6 +
7 +
8 +<a name="1.13.0"></a>
9 +# 1.13.0 (2019-01-25)
10 +
11 +* build: add release process ([8cc1b05](https://github.com/przemyslawpluta/node-youtube-dl/commit/8cc1b05))
12 +* test: update snapshots ([65fb75e](https://github.com/przemyslawpluta/node-youtube-dl/commit/65fb75e))
13 +* add editorconfig ([8a92f0b](https://github.com/przemyslawpluta/node-youtube-dl/commit/8a92f0b))
14 +* add hms to duration, twitch test ([9ea3ff1](https://github.com/przemyslawpluta/node-youtube-dl/commit/9ea3ff1))
15 +* add sensible `execFile` good defaults ([2524d75](https://github.com/przemyslawpluta/node-youtube-dl/commit/2524d75)), closes [#173](https://github.com/przemyslawpluta/node-youtube-dl/issues/173)
16 +* Adding dashes before the video ID ([da8f4dd](https://github.com/przemyslawpluta/node-youtube-dl/commit/da8f4dd))
17 +* changed to _filename in line 33 readme ([87d3891](https://github.com/przemyslawpluta/node-youtube-dl/commit/87d3891))
18 +* Consider copyright videos as not available in order to continue on error ([e19d8d1](https://github.com/przemyslawpluta/node-youtube-dl/commit/e19d8d1))
19 +* Consider not made available videos as not available in order to continue on error ([ae7ea3b](https://github.com/przemyslawpluta/node-youtube-dl/commit/ae7ea3b))
20 +* Correct extension in playlist.js ([5d77436](https://github.com/przemyslawpluta/node-youtube-dl/commit/5d77436))
21 +* Correct test with correct video info ([0ee2609](https://github.com/przemyslawpluta/node-youtube-dl/commit/0ee2609))
22 +* Disable non-functional test ([ca1aa42](https://github.com/przemyslawpluta/node-youtube-dl/commit/ca1aa42))
23 +* download best and combine is ffmpeg available ([2193220](https://github.com/przemyslawpluta/node-youtube-dl/commit/2193220))
24 +* Download correct binary for windows systems ([3874a88](https://github.com/przemyslawpluta/node-youtube-dl/commit/3874a88))
25 +* drop tests for 4,5 and version bump ([3634c67](https://github.com/przemyslawpluta/node-youtube-dl/commit/3634c67))
26 +* Fix encoding issue on windows ([d65114d](https://github.com/przemyslawpluta/node-youtube-dl/commit/d65114d))
27 +* Get and set path from youtube-dl ([161ed2a](https://github.com/przemyslawpluta/node-youtube-dl/commit/161ed2a))
28 +* handle thumbnails download ([a0832dc](https://github.com/przemyslawpluta/node-youtube-dl/commit/a0832dc))
29 +* hms and raw duration ([eb0e9de](https://github.com/przemyslawpluta/node-youtube-dl/commit/eb0e9de))
30 +* meta tweaks ([f685ad7](https://github.com/przemyslawpluta/node-youtube-dl/commit/f685ad7))
31 +* minor typo ([429b1f7](https://github.com/przemyslawpluta/node-youtube-dl/commit/429b1f7))
32 +* missing ; ([05f8f62](https://github.com/przemyslawpluta/node-youtube-dl/commit/05f8f62))
33 +* remove dead code ([4b1ba39](https://github.com/przemyslawpluta/node-youtube-dl/commit/4b1ba39))
34 +* remove deprecated badge ([19a7b33](https://github.com/przemyslawpluta/node-youtube-dl/commit/19a7b33))
35 +* remove lock ([0131daf](https://github.com/przemyslawpluta/node-youtube-dl/commit/0131daf))
36 +* Remove size from download test, not relevant ([e22ee14](https://github.com/przemyslawpluta/node-youtube-dl/commit/e22ee14))
37 +* remove vimeo tests ([1f717cc](https://github.com/przemyslawpluta/node-youtube-dl/commit/1f717cc))
38 +* update dependencies ([bf28967](https://github.com/przemyslawpluta/node-youtube-dl/commit/bf28967))
39 +* update snapshot ([70ec50a](https://github.com/przemyslawpluta/node-youtube-dl/commit/70ec50a))
40 +* Update test about twitch (twitch id are not anymore the video title) ([b9f0317](https://github.com/przemyslawpluta/node-youtube-dl/commit/b9f0317))
41 +* update travis builds ([efe313c](https://github.com/przemyslawpluta/node-youtube-dl/commit/efe313c))
42 +* Updated test case since video title changed on twitch's end ([7c22361](https://github.com/przemyslawpluta/node-youtube-dl/commit/7c22361))
43 +* use const over var ([6ed5a1c](https://github.com/przemyslawpluta/node-youtube-dl/commit/6ed5a1c))
44 +
45 +
46 +
47 +<a name="1.12.1"></a>
48 +## 1.12.1 (2017-09-28)
49 +
50 +* cleanup ([68ea1df](https://github.com/przemyslawpluta/node-youtube-dl/commit/68ea1df))
51 +* cleanup ([5efbce3](https://github.com/przemyslawpluta/node-youtube-dl/commit/5efbce3))
52 +* concat args ([25ed267](https://github.com/przemyslawpluta/node-youtube-dl/commit/25ed267))
53 +* correct repo url ([88ec7c8](https://github.com/przemyslawpluta/node-youtube-dl/commit/88ec7c8))
54 +* Document how to increase buffer size ([3bb3e4d](https://github.com/przemyslawpluta/node-youtube-dl/commit/3bb3e4d))
55 +* drop getFormats, update vimeo test ([da47d4d](https://github.com/przemyslawpluta/node-youtube-dl/commit/da47d4d))
56 +* drop io.js tests ([b1fa4fb](https://github.com/przemyslawpluta/node-youtube-dl/commit/b1fa4fb))
57 +* drop soundcloud due to ssl error on travis ([0c7168d](https://github.com/przemyslawpluta/node-youtube-dl/commit/0c7168d))
58 +* drop tests for 0.10 ([473cdf6](https://github.com/przemyslawpluta/node-youtube-dl/commit/473cdf6))
59 +* fix ([a6d6d36](https://github.com/przemyslawpluta/node-youtube-dl/commit/a6d6d36))
60 +* Fix issue with duration not formatting correctly ([d9dd0ec](https://github.com/przemyslawpluta/node-youtube-dl/commit/d9dd0ec))
61 +* fix package name ([5642547](https://github.com/przemyslawpluta/node-youtube-dl/commit/5642547))
62 +* fix tests, update formatting ([796f922](https://github.com/przemyslawpluta/node-youtube-dl/commit/796f922))
63 +* fixed downloader if user passed in a custom bin dir ([2954eed](https://github.com/przemyslawpluta/node-youtube-dl/commit/2954eed))
64 +* Fixed tests assertion, video sizes changed probably due to change in streaming technology and title ([d2f7894](https://github.com/przemyslawpluta/node-youtube-dl/commit/d2f7894))
65 +* hotfix for the electron issue ([ae7608c](https://github.com/przemyslawpluta/node-youtube-dl/commit/ae7608c))
66 +* Make properties configurable ([dab402b](https://github.com/przemyslawpluta/node-youtube-dl/commit/dab402b))
67 +* manage missing video array plus tests ([6f2840e](https://github.com/przemyslawpluta/node-youtube-dl/commit/6f2840e))
68 +* py + node test ([cf2d5e1](https://github.com/przemyslawpluta/node-youtube-dl/commit/cf2d5e1))
69 +* python test ([e6b597a](https://github.com/przemyslawpluta/node-youtube-dl/commit/e6b597a))
70 +* Quickfix for Copy Error in Usage Example ([db27e8a](https://github.com/przemyslawpluta/node-youtube-dl/commit/db27e8a))
71 +* skip error is video has been removed by the user ([5e94b13](https://github.com/przemyslawpluta/node-youtube-dl/commit/5e94b13))
72 +* skip error is video has been removed by the user ([956056b](https://github.com/przemyslawpluta/node-youtube-dl/commit/956056b))
73 +* ssl err test ([0738a25](https://github.com/przemyslawpluta/node-youtube-dl/commit/0738a25))
74 +* test ([80d924a](https://github.com/przemyslawpluta/node-youtube-dl/commit/80d924a))
75 +* travis ssl force ([6b0f0f8](https://github.com/przemyslawpluta/node-youtube-dl/commit/6b0f0f8))
76 +* update audio.js ([17c3fb1](https://github.com/przemyslawpluta/node-youtube-dl/commit/17c3fb1))
77 +* update build status ([1aa9d82](https://github.com/przemyslawpluta/node-youtube-dl/commit/1aa9d82))
78 +* update details ([653f411](https://github.com/przemyslawpluta/node-youtube-dl/commit/653f411))
79 +* update icons ([0399db6](https://github.com/przemyslawpluta/node-youtube-dl/commit/0399db6))
80 +* update mode ([e83b336](https://github.com/przemyslawpluta/node-youtube-dl/commit/e83b336))
81 +* update package ([2867fc5](https://github.com/przemyslawpluta/node-youtube-dl/commit/2867fc5))
82 +* Update README.md ([76cb708](https://github.com/przemyslawpluta/node-youtube-dl/commit/76cb708))
83 +* update tests ([d745285](https://github.com/przemyslawpluta/node-youtube-dl/commit/d745285))
84 +* update travis env ([08fd355](https://github.com/przemyslawpluta/node-youtube-dl/commit/08fd355))
85 +* update travis-ci ([339460b](https://github.com/przemyslawpluta/node-youtube-dl/commit/339460b))
86 +* update youtube-dl permissions ([621b478](https://github.com/przemyslawpluta/node-youtube-dl/commit/621b478))
87 +* updates & fixes ([8bc4839](https://github.com/przemyslawpluta/node-youtube-dl/commit/8bc4839))
88 +* version bump ([a839a5f](https://github.com/przemyslawpluta/node-youtube-dl/commit/a839a5f))
89 +
90 +
91 +
92 +<a name="1.11.1"></a>
93 +## 1.11.1 (2016-04-06)
94 +
95 +* add heroku support ([541e710](https://github.com/przemyslawpluta/node-youtube-dl/commit/541e710))
96 +* version bump ([22abe25](https://github.com/przemyslawpluta/node-youtube-dl/commit/22abe25))
97 +
98 +
99 +
100 +<a name="1.11.0"></a>
101 +# 1.11.0 (2016-03-25)
102 +
103 +* add getFormats example ([d9b2925](https://github.com/przemyslawpluta/node-youtube-dl/commit/d9b2925))
104 +* add node 4 & 5 for testing ([8683ac1](https://github.com/przemyslawpluta/node-youtube-dl/commit/8683ac1))
105 +* adding ability to continue partially downloaded files. ([e9e540a](https://github.com/przemyslawpluta/node-youtube-dl/commit/e9e540a))
106 +* allow for external bin but keep details internally ([f35daab](https://github.com/przemyslawpluta/node-youtube-dl/commit/f35daab))
107 +* As requested, I was trying to make the code as readable as possible ([38884d1](https://github.com/przemyslawpluta/node-youtube-dl/commit/38884d1))
108 +* callback err ([f49128c](https://github.com/przemyslawpluta/node-youtube-dl/commit/f49128c))
109 +* change bin permissions ([957172b](https://github.com/przemyslawpluta/node-youtube-dl/commit/957172b))
110 +* check for datadir existence ([1817160](https://github.com/przemyslawpluta/node-youtube-dl/commit/1817160))
111 +* choose bin location ([1123d33](https://github.com/przemyslawpluta/node-youtube-dl/commit/1123d33))
112 +* cleanup ([12eb585](https://github.com/przemyslawpluta/node-youtube-dl/commit/12eb585))
113 +* cleanup ([1a8b2f0](https://github.com/przemyslawpluta/node-youtube-dl/commit/1a8b2f0))
114 +* cleanup .gitignore ([bf5b974](https://github.com/przemyslawpluta/node-youtube-dl/commit/bf5b974))
115 +* dependencies bump ([f131dca](https://github.com/przemyslawpluta/node-youtube-dl/commit/f131dca))
116 +* document `ytdl.exec()` with audio example ([2b8333f](https://github.com/przemyslawpluta/node-youtube-dl/commit/2b8333f))
117 +* extract downloader ([f27c45a](https://github.com/przemyslawpluta/node-youtube-dl/commit/f27c45a))
118 +* fix bin path ([6f9ef39](https://github.com/przemyslawpluta/node-youtube-dl/commit/6f9ef39))
119 +* fix license meta in pacakge.json ([3d2f168](https://github.com/przemyslawpluta/node-youtube-dl/commit/3d2f168))
120 +* fix resolution or audio ([d2a3269](https://github.com/przemyslawpluta/node-youtube-dl/commit/d2a3269))
121 +* handle playlists ([acb1571](https://github.com/przemyslawpluta/node-youtube-dl/commit/acb1571))
122 +* install module before download ([f3e0ac7](https://github.com/przemyslawpluta/node-youtube-dl/commit/f3e0ac7))
123 +* missing dependency ([f56cb24](https://github.com/przemyslawpluta/node-youtube-dl/commit/f56cb24))
124 +* move bin path to datadir ([7ef58ef](https://github.com/przemyslawpluta/node-youtube-dl/commit/7ef58ef))
125 +* no longer maintaining ([1aa9076](https://github.com/przemyslawpluta/node-youtube-dl/commit/1aa9076))
126 +* package postinstall ([c1f052f](https://github.com/przemyslawpluta/node-youtube-dl/commit/c1f052f))
127 +* permission change on bin ([c061caa](https://github.com/przemyslawpluta/node-youtube-dl/commit/c061caa))
128 +* permission change on bin cleanup test ([6912150](https://github.com/przemyslawpluta/node-youtube-dl/commit/6912150))
129 +* preventing options being created if it doesn't exist ([894e215](https://github.com/przemyslawpluta/node-youtube-dl/commit/894e215))
130 +* remove unused module ([6fc3f02](https://github.com/przemyslawpluta/node-youtube-dl/commit/6fc3f02))
131 +* resolve to .exe on win ([2c5467e](https://github.com/przemyslawpluta/node-youtube-dl/commit/2c5467e))
132 +* skip over not available videos during playlist download ([45ee26b](https://github.com/przemyslawpluta/node-youtube-dl/commit/45ee26b))
133 +* store example videos in dir to keep things cleaner ([e7cc0d5](https://github.com/przemyslawpluta/node-youtube-dl/commit/e7cc0d5))
134 +* update ([4da180b](https://github.com/przemyslawpluta/node-youtube-dl/commit/4da180b))
135 +* update ([60a0cf4](https://github.com/przemyslawpluta/node-youtube-dl/commit/60a0cf4))
136 +* update path ([b9992cf](https://github.com/przemyslawpluta/node-youtube-dl/commit/b9992cf))
137 +* update readme ([c159427](https://github.com/przemyslawpluta/node-youtube-dl/commit/c159427))
138 +* update readme ([a41b965](https://github.com/przemyslawpluta/node-youtube-dl/commit/a41b965))
139 +* update README ([1565229](https://github.com/przemyslawpluta/node-youtube-dl/commit/1565229))
140 +* update tests ([7be149d](https://github.com/przemyslawpluta/node-youtube-dl/commit/7be149d))
141 +* Updating comment block for inline quotes, replacing double quotes with single quotes ([1646cec](https://github.com/przemyslawpluta/node-youtube-dl/commit/1646cec))
142 +
143 +
144 +
145 +<a name="1.10.5"></a>
146 +## 1.10.5 (2015-05-07)
147 +
148 +* 1.10.5 ([d2d4eba](https://github.com/przemyslawpluta/node-youtube-dl/commit/d2d4eba))
149 +* better check for `--format` ([dbaebb3](https://github.com/przemyslawpluta/node-youtube-dl/commit/dbaebb3))
150 +
151 +
152 +
153 +<a name="1.10.4"></a>
154 +## 1.10.4 (2015-05-07)
155 +
156 +* 1.10.4 ([06ec68e](https://github.com/przemyslawpluta/node-youtube-dl/commit/06ec68e))
157 +* check for `--format` too ([08ca167](https://github.com/przemyslawpluta/node-youtube-dl/commit/08ca167))
158 +* Specify download format 'best' if none supplied ([edee4d3](https://github.com/przemyslawpluta/node-youtube-dl/commit/edee4d3))
159 +* update examples ([023a502](https://github.com/przemyslawpluta/node-youtube-dl/commit/023a502))
160 +* update tests ([a85779d](https://github.com/przemyslawpluta/node-youtube-dl/commit/a85779d))
161 +
162 +
163 +
164 +<a name="1.10.3"></a>
165 +## 1.10.3 (2015-04-19)
166 +
167 +* 1.10.3 ([a70895e](https://github.com/przemyslawpluta/node-youtube-dl/commit/a70895e))
168 +* Fix the broken Host HTTP Header for Dailymotion && Fix Test ([9657b8c](https://github.com/przemyslawpluta/node-youtube-dl/commit/9657b8c))
169 +
170 +
171 +
172 +<a name="1.10.2"></a>
173 +## 1.10.2 (2015-03-24)
174 +
175 +* 1.10.2 ([484d1c3](https://github.com/przemyslawpluta/node-youtube-dl/commit/484d1c3))
176 +* a bit of docs ([c3c1b4b](https://github.com/przemyslawpluta/node-youtube-dl/commit/c3c1b4b))
177 +* print warning when getting warnings from stderr ([26bd213](https://github.com/przemyslawpluta/node-youtube-dl/commit/26bd213))
178 +
179 +
180 +
181 +<a name="1.10.1"></a>
182 +## 1.10.1 (2015-02-26)
183 +
184 +* 1.10.1 ([498e288](https://github.com/przemyslawpluta/node-youtube-dl/commit/498e288))
185 +* add io.js and 0.12 to test matrix ([17ce70b](https://github.com/przemyslawpluta/node-youtube-dl/commit/17ce70b))
186 +* call binary with python instead of directly, fixes #66 ([833d281](https://github.com/przemyslawpluta/node-youtube-dl/commit/833d281)), closes [#66](https://github.com/przemyslawpluta/node-youtube-dl/issues/66)
187 +* dont test on node v0.8 ([5c1c182](https://github.com/przemyslawpluta/node-youtube-dl/commit/5c1c182))
188 +* quote iojs ([47d1485](https://github.com/przemyslawpluta/node-youtube-dl/commit/47d1485))
189 +* update packages ([413cf53](https://github.com/przemyslawpluta/node-youtube-dl/commit/413cf53))
190 +* use container based environment ([4947618](https://github.com/przemyslawpluta/node-youtube-dl/commit/4947618))
191 +
192 +
193 +
194 +<a name="1.10.0"></a>
195 +# 1.10.0 (2015-02-19)
196 +
197 +* 1.10.0 ([d3018e5](https://github.com/przemyslawpluta/node-youtube-dl/commit/d3018e5))
198 +* Multiple URL support (array param) for getInfo() ([1afab0b](https://github.com/przemyslawpluta/node-youtube-dl/commit/1afab0b))
199 +
200 +
201 +
202 +<a name="1.9.0"></a>
203 +# 1.9.0 (2015-02-13)
204 +
205 +* 1.9.0 ([e3be488](https://github.com/przemyslawpluta/node-youtube-dl/commit/e3be488))
206 +* add warnings for using deprecated fields ([d2c53ae](https://github.com/przemyslawpluta/node-youtube-dl/commit/d2c53ae))
207 +* Call getInfo from getFormats ([4ecda89](https://github.com/przemyslawpluta/node-youtube-dl/commit/4ecda89))
208 +* document how to keep youtube-dl binary up to date. fixes #61 ([a8eface](https://github.com/przemyslawpluta/node-youtube-dl/commit/a8eface)), closes [#61](https://github.com/przemyslawpluta/node-youtube-dl/issues/61)
209 +* dont check each individual format object ([50c113f](https://github.com/przemyslawpluta/node-youtube-dl/commit/50c113f))
210 +* fix getting playlist info ([cdb37fe](https://github.com/przemyslawpluta/node-youtube-dl/commit/cdb37fe))
211 +* Move formatDuration to util.js ([c309c24](https://github.com/przemyslawpluta/node-youtube-dl/commit/c309c24))
212 +* remove unused old functions ([e4689a6](https://github.com/przemyslawpluta/node-youtube-dl/commit/e4689a6))
213 +* Return the full info provided by youtube-dl ([ace1b11](https://github.com/przemyslawpluta/node-youtube-dl/commit/ace1b11))
214 +* Use the '--dump-json' option for extracting the video information ([b3a9fcd](https://github.com/przemyslawpluta/node-youtube-dl/commit/b3a9fcd))
215 +* Use the '--dump-json' option for getFormats ([e93a8b9](https://github.com/przemyslawpluta/node-youtube-dl/commit/e93a8b9))
216 +
217 +
218 +
219 +<a name="1.8.0"></a>
220 +# 1.8.0 (2015-01-15)
221 +
222 +* 1.8.0 ([ab8b3df](https://github.com/przemyslawpluta/node-youtube-dl/commit/ab8b3df))
223 +* Added extractor API incl. tests and example code ([d2b3983](https://github.com/przemyslawpluta/node-youtube-dl/commit/d2b3983))
224 +* dont download video when downloading subtitles ([3cfa382](https://github.com/przemyslawpluta/node-youtube-dl/commit/3cfa382))
225 +* put try/catch around unlinking subtitle file ([a3f5202](https://github.com/przemyslawpluta/node-youtube-dl/commit/a3f5202))
226 +
227 +
228 +
229 +<a name="1.7.0"></a>
230 +# 1.7.0 (2015-01-08)
231 +
232 +* 1.7.0 ([777619e](https://github.com/przemyslawpluta/node-youtube-dl/commit/777619e))
233 +* added more cli args to ignore ([8edbd1e](https://github.com/przemyslawpluta/node-youtube-dl/commit/8edbd1e))
234 +* get duration. fixes #53 ([fd7d7c9](https://github.com/przemyslawpluta/node-youtube-dl/commit/fd7d7c9)), closes [#53](https://github.com/przemyslawpluta/node-youtube-dl/issues/53)
235 +* make `args` passed to youtube-dl actually optional ([413d0ab](https://github.com/przemyslawpluta/node-youtube-dl/commit/413d0ab))
236 +
237 +
238 +
239 +<a name="1.6.0"></a>
240 +# 1.6.0 (2014-11-23)
241 +
242 +* 1.6.0 ([8d548eb](https://github.com/przemyslawpluta/node-youtube-dl/commit/8d548eb))
243 +* add `getSubs()` function. fixes #48 ([6cb55af](https://github.com/przemyslawpluta/node-youtube-dl/commit/6cb55af)), closes [#48](https://github.com/przemyslawpluta/node-youtube-dl/issues/48)
244 +* better resolution detection ([cff5763](https://github.com/przemyslawpluta/node-youtube-dl/commit/cff5763))
245 +* check size is defined ([0e67ef1](https://github.com/przemyslawpluta/node-youtube-dl/commit/0e67ef1))
246 +* linting ([916e8da](https://github.com/przemyslawpluta/node-youtube-dl/commit/916e8da))
247 +* linting ([1f5e319](https://github.com/przemyslawpluta/node-youtube-dl/commit/1f5e319))
248 +* update formats returned ([d545f10](https://github.com/przemyslawpluta/node-youtube-dl/commit/d545f10))
249 +* updated getFormats regex to handle unknown & ?x formats ([7e33ace](https://github.com/przemyslawpluta/node-youtube-dl/commit/7e33ace))
250 +
251 +
252 +
253 +<a name="1.5.16"></a>
254 +## 1.5.16 (2014-10-24)
255 +
256 +* 1.5.16 ([4acfca7](https://github.com/przemyslawpluta/node-youtube-dl/commit/4acfca7))
257 +* filter out from correct args if no subs ([97346fe](https://github.com/przemyslawpluta/node-youtube-dl/commit/97346fe))
258 +* handle new warning style ([3ae2964](https://github.com/przemyslawpluta/node-youtube-dl/commit/3ae2964))
259 +* update test formats ([24f00e5](https://github.com/przemyslawpluta/node-youtube-dl/commit/24f00e5))
260 +
261 +
262 +
263 +<a name="1.5.15"></a>
264 +## 1.5.15 (2014-09-25)
265 +
266 +* 1.5.15 ([f315043](https://github.com/przemyslawpluta/node-youtube-dl/commit/f315043))
267 +* fix ([5d07020](https://github.com/przemyslawpluta/node-youtube-dl/commit/5d07020))
268 +
269 +
270 +
271 +<a name="1.5.14"></a>
272 +## 1.5.14 (2014-09-24)
273 +
274 +* 1.5.14 ([c7d7c08](https://github.com/przemyslawpluta/node-youtube-dl/commit/c7d7c08))
275 +* expose call function with empty default args as exec ([e12b538](https://github.com/przemyslawpluta/node-youtube-dl/commit/e12b538))
276 +* ignore any errors after successful download. fixes #43 ([58558d8](https://github.com/przemyslawpluta/node-youtube-dl/commit/58558d8)), closes [#43](https://github.com/przemyslawpluta/node-youtube-dl/issues/43)
277 +
278 +
279 +
280 +<a name="1.5.13"></a>
281 +## 1.5.13 (2014-09-07)
282 +
283 +* 1.5.13 ([e72b27d](https://github.com/przemyslawpluta/node-youtube-dl/commit/e72b27d))
284 +* fix for missing env variable in win ([4115b5e](https://github.com/przemyslawpluta/node-youtube-dl/commit/4115b5e))
285 +
286 +
287 +
288 +<a name="1.5.12"></a>
289 +## 1.5.12 (2014-09-04)
290 +
291 +* 1.5.12 ([8a8c681](https://github.com/przemyslawpluta/node-youtube-dl/commit/8a8c681))
292 +* fix youtube id filtering ([3cb82a9](https://github.com/przemyslawpluta/node-youtube-dl/commit/3cb82a9))
293 +
294 +
295 +
296 +<a name="1.5.11"></a>
297 +## 1.5.11 (2014-08-24)
298 +
299 +* 1.5.11 ([09d2951](https://github.com/przemyslawpluta/node-youtube-dl/commit/09d2951))
300 +* support non-youtube (speificially vimeo) videos. fixes #39 ([cd6938b](https://github.com/przemyslawpluta/node-youtube-dl/commit/cd6938b)), closes [#39](https://github.com/przemyslawpluta/node-youtube-dl/issues/39)
301 +
302 +
303 +
304 +<a name="1.5.10"></a>
305 +## 1.5.10 (2014-08-05)
306 +
307 +* 1.5.10 ([f9c0c8f](https://github.com/przemyslawpluta/node-youtube-dl/commit/f9c0c8f))
308 +* fix not passing options ([02fa0df](https://github.com/przemyslawpluta/node-youtube-dl/commit/02fa0df))
309 +
310 +
311 +
312 +<a name="1.5.9"></a>
313 +## 1.5.9 (2014-08-02)
314 +
315 +* 1.5.9 ([303fb12](https://github.com/przemyslawpluta/node-youtube-dl/commit/303fb12))
316 +* Add more entries to badArgs ([a6821b5](https://github.com/przemyslawpluta/node-youtube-dl/commit/a6821b5))
317 +* fix for failed download with no subtitles ([36fd75a](https://github.com/przemyslawpluta/node-youtube-dl/commit/36fd75a))
318 +* fix for failed download with no subtitles when requested ([69166bf](https://github.com/przemyslawpluta/node-youtube-dl/commit/69166bf))
319 +* fix for failed download with no subtitles when requested ([aeab2dd](https://github.com/przemyslawpluta/node-youtube-dl/commit/aeab2dd))
320 +* fix for failed download with no subtitles when requested ([038b1fd](https://github.com/przemyslawpluta/node-youtube-dl/commit/038b1fd))
321 +* fix for failed download with no subtitles when requested ([19c13af](https://github.com/przemyslawpluta/node-youtube-dl/commit/19c13af))
322 +* fix for failed download with no subtitles when requested ([82a48a4](https://github.com/przemyslawpluta/node-youtube-dl/commit/82a48a4))
323 +* only notify on build changes ([3cf3363](https://github.com/przemyslawpluta/node-youtube-dl/commit/3cf3363))
324 +* update request to v2.37.0 ([11757f3](https://github.com/przemyslawpluta/node-youtube-dl/commit/11757f3))
325 +
326 +
327 +
328 +<a name="1.5.8"></a>
329 +## 1.5.8 (2014-07-04)
330 +
331 +* Fix ReferenceError: onerror is not defined ([acb3512](https://github.com/przemyslawpluta/node-youtube-dl/commit/acb3512))
332 +* Fix var name: from er to err ([21bdbee](https://github.com/przemyslawpluta/node-youtube-dl/commit/21bdbee))
333 +* update request ([f97f90b](https://github.com/przemyslawpluta/node-youtube-dl/commit/f97f90b))
334 +* v1.5.7 ([f19215a](https://github.com/przemyslawpluta/node-youtube-dl/commit/f19215a))
335 +* v1.5.8 ([96083ba](https://github.com/przemyslawpluta/node-youtube-dl/commit/96083ba))
336 +
337 +
338 +
339 +<a name="1.5.6"></a>
340 +## 1.5.6 (2014-06-14)
341 +
342 +* comment consistency ([7acea1e](https://github.com/przemyslawpluta/node-youtube-dl/commit/7acea1e))
343 +* fix parsing resolutions ([ac48c37](https://github.com/przemyslawpluta/node-youtube-dl/commit/ac48c37))
344 +* fix when not giving `args` to `getInfo()` ([794617d](https://github.com/przemyslawpluta/node-youtube-dl/commit/794617d))
345 +* v1.5.6 ([80999a5](https://github.com/przemyslawpluta/node-youtube-dl/commit/80999a5))
346 +
347 +
348 +
349 +<a name="1.5.5"></a>
350 +## 1.5.5 (2014-05-02)
351 +
352 +* can pass execFile options to download ([2986447](https://github.com/przemyslawpluta/node-youtube-dl/commit/2986447))
353 +* dont parse options twice on download ([67eb88d](https://github.com/przemyslawpluta/node-youtube-dl/commit/67eb88d))
354 +* v1.5.5 ([20c3cd2](https://github.com/przemyslawpluta/node-youtube-dl/commit/20c3cd2))
355 +
356 +
357 +
358 +<a name="1.5.4"></a>
359 +## 1.5.4 (2014-05-01)
360 +
361 +* chmod bin directory too ([3d1e88f](https://github.com/przemyslawpluta/node-youtube-dl/commit/3d1e88f))
362 +* run download script on preinstall ([c377b4e](https://github.com/przemyslawpluta/node-youtube-dl/commit/c377b4e))
363 +* update vows ([a3be7a9](https://github.com/przemyslawpluta/node-youtube-dl/commit/a3be7a9))
364 +* v1.5.4 ([a0709a4](https://github.com/przemyslawpluta/node-youtube-dl/commit/a0709a4))
365 +* package: add binary ([2050667](https://github.com/przemyslawpluta/node-youtube-dl/commit/2050667))
366 +
367 +
368 +
369 +<a name="1.5.3"></a>
370 +## 1.5.3 (2014-04-26)
371 +
372 +* dont global link youtube-dl binary. too much confusion. ([b74ed8f](https://github.com/przemyslawpluta/node-youtube-dl/commit/b74ed8f))
373 +* Remove /v/ from the id to accept url like http://www.youtube.com/v/6tC1yOUvvMo provided by the youtu ([b4a3350](https://github.com/przemyslawpluta/node-youtube-dl/commit/b4a3350))
374 +* Remove useless g flag from Regex ([1239606](https://github.com/przemyslawpluta/node-youtube-dl/commit/1239606))
375 +* some code organization ([085b9f7](https://github.com/przemyslawpluta/node-youtube-dl/commit/085b9f7))
376 +* update ignore rules ([0acf105](https://github.com/przemyslawpluta/node-youtube-dl/commit/0acf105))
377 +* v1.5.3 ([3175bd0](https://github.com/przemyslawpluta/node-youtube-dl/commit/3175bd0))
378 +
379 +
380 +
381 +<a name="1.5.2"></a>
382 +## 1.5.2 (2014-04-25)
383 +
384 +* Add a second var ([76d3468](https://github.com/przemyslawpluta/node-youtube-dl/commit/76d3468))
385 +* Fix "Cannot call method 'split' of undefined" bug with last version of youtube-dl (2014.04.21.6) ([864a526](https://github.com/przemyslawpluta/node-youtube-dl/commit/864a526))
386 +* Remove commented old code ([9804155](https://github.com/przemyslawpluta/node-youtube-dl/commit/9804155))
387 +* Remove the extra space ([11aabf9](https://github.com/przemyslawpluta/node-youtube-dl/commit/11aabf9))
388 +* Save the regexp in the outer scope so it's not compiled every time this function runs ([585c526](https://github.com/przemyslawpluta/node-youtube-dl/commit/585c526))
389 +* v1.5.2 ([88be6d7](https://github.com/przemyslawpluta/node-youtube-dl/commit/88be6d7))
390 +
391 +
392 +
393 +<a name="1.5.1"></a>
394 +## 1.5.1 (2014-04-08)
395 +
396 +* add Przemyslaw to contributors ([afc4cc9](https://github.com/przemyslawpluta/node-youtube-dl/commit/afc4cc9))
397 +* fix for win py2.x / py3.x ([472a8db](https://github.com/przemyslawpluta/node-youtube-dl/commit/472a8db))
398 +* v1.5.1 ([7a2620d](https://github.com/przemyslawpluta/node-youtube-dl/commit/7a2620d))
399 +
400 +
401 +
402 +<a name="1.5.0"></a>
403 +# 1.5.0 (2014-04-08)
404 +
405 +* download first if array of clips ([28ed6bb](https://github.com/przemyslawpluta/node-youtube-dl/commit/28ed6bb))
406 +* handle videos download from youtube playlist ([b7434da](https://github.com/przemyslawpluta/node-youtube-dl/commit/b7434da))
407 +* refactor ([6c5187e](https://github.com/przemyslawpluta/node-youtube-dl/commit/6c5187e))
408 +* test update ([8704b8e](https://github.com/przemyslawpluta/node-youtube-dl/commit/8704b8e))
409 +* typo ([540ee03](https://github.com/przemyslawpluta/node-youtube-dl/commit/540ee03))
410 +* typo ([2647ed5](https://github.com/przemyslawpluta/node-youtube-dl/commit/2647ed5))
411 +* v1.5.0 ([b27d373](https://github.com/przemyslawpluta/node-youtube-dl/commit/b27d373))
412 +
413 +
414 +
415 +<a name="1.4.0"></a>
416 +# 1.4.0 (2014-03-14)
417 +
418 +* not needed ([7dcd88f](https://github.com/przemyslawpluta/node-youtube-dl/commit/7dcd88f))
419 +* reflect api changes ([82aeb41](https://github.com/przemyslawpluta/node-youtube-dl/commit/82aeb41))
420 +* update example videos ([3bd98d7](https://github.com/przemyslawpluta/node-youtube-dl/commit/3bd98d7))
421 +* update tests ([c4ab33d](https://github.com/przemyslawpluta/node-youtube-dl/commit/c4ab33d))
422 +* use youtube-dl to get download url, return stream ([3479e52](https://github.com/przemyslawpluta/node-youtube-dl/commit/3479e52))
423 +* v1.4.0 ([e23e5f3](https://github.com/przemyslawpluta/node-youtube-dl/commit/e23e5f3))
424 +
425 +
426 +
427 +<a name="1.3.6"></a>
428 +## 1.3.6 (2014-02-15)
429 +
430 +* fix - youtube-dl incorrect download ([8c439b1](https://github.com/przemyslawpluta/node-youtube-dl/commit/8c439b1))
431 +* v1.3.6 ([be7c22f](https://github.com/przemyslawpluta/node-youtube-dl/commit/be7c22f))
432 +
433 +
434 +
435 +<a name="1.3.5"></a>
436 +## 1.3.5 (2014-02-15)
437 +
438 +* Fix - win handling getInfo & getFormats ([19ccc54](https://github.com/przemyslawpluta/node-youtube-dl/commit/19ccc54))
439 +* Fix - win handling getInfo & getFormats ([7655ea1](https://github.com/przemyslawpluta/node-youtube-dl/commit/7655ea1))
440 +* v1.3.5 ([6f4eb9c](https://github.com/przemyslawpluta/node-youtube-dl/commit/6f4eb9c))
441 +
442 +
443 +
444 +<a name="1.3.4"></a>
445 +## 1.3.4 (2014-02-14)
446 +
447 +* Fix - Incorrect youtube video URL ([954df15](https://github.com/przemyslawpluta/node-youtube-dl/commit/954df15))
448 +* Fix - Incorrect youtube video URL ([17c4214](https://github.com/przemyslawpluta/node-youtube-dl/commit/17c4214))
449 +* Fix - Incorrect youtube video URL ([12dea04](https://github.com/przemyslawpluta/node-youtube-dl/commit/12dea04))
450 +* Fix - Incorrect youtube video URL ([1b10dff](https://github.com/przemyslawpluta/node-youtube-dl/commit/1b10dff))
451 +* Fix - Incorrect youtube video URL ([408e2b1](https://github.com/przemyslawpluta/node-youtube-dl/commit/408e2b1))
452 +* Fix - Incorrect youtube video URL ([c161fa6](https://github.com/przemyslawpluta/node-youtube-dl/commit/c161fa6))
453 +* Fix - Incorrect youtube video URL ([753ae6b](https://github.com/przemyslawpluta/node-youtube-dl/commit/753ae6b))
454 +* Fix - Incorrect youtube video URL ([04f4aaa](https://github.com/przemyslawpluta/node-youtube-dl/commit/04f4aaa))
455 +* Fix - Incorrect youtube video URL ([a5eeb09](https://github.com/przemyslawpluta/node-youtube-dl/commit/a5eeb09))
456 +* Fix - Incorrect youtube video URL ([28dd461](https://github.com/przemyslawpluta/node-youtube-dl/commit/28dd461))
457 +* only write version to file if downloaded successfully ([091f425](https://github.com/przemyslawpluta/node-youtube-dl/commit/091f425))
458 +* v1.3.4 ([6825c7b](https://github.com/przemyslawpluta/node-youtube-dl/commit/6825c7b))
459 +
460 +
461 +
462 +<a name="1.3.3"></a>
463 +## 1.3.3 (2014-02-12)
464 +
465 +* spawn ENOENT in win ([48a309d](https://github.com/przemyslawpluta/node-youtube-dl/commit/48a309d))
466 +* spawn ENOENT in win ([b6191c8](https://github.com/przemyslawpluta/node-youtube-dl/commit/b6191c8))
467 +* spawn ENOENT in win ([a816720](https://github.com/przemyslawpluta/node-youtube-dl/commit/a816720))
468 +* spawn ENOENT in win ([b6178e6](https://github.com/przemyslawpluta/node-youtube-dl/commit/b6178e6))
469 +* tiny cleanup ([19a0059](https://github.com/przemyslawpluta/node-youtube-dl/commit/19a0059))
470 +* update get formats regexp ([9df37f0](https://github.com/przemyslawpluta/node-youtube-dl/commit/9df37f0))
471 +* update ugh tests ([db2388c](https://github.com/przemyslawpluta/node-youtube-dl/commit/db2388c))
472 +* v1.3.3 ([f4498fa](https://github.com/przemyslawpluta/node-youtube-dl/commit/f4498fa))
473 +
474 +
475 +
476 +<a name="1.3.2"></a>
477 +## 1.3.2 (2013-10-22)
478 +
479 +* improve regexp to download latest version ([9040f81](https://github.com/przemyslawpluta/node-youtube-dl/commit/9040f81))
480 +* removed check for query.v that breaks soundcloud functionality ([11da4f7](https://github.com/przemyslawpluta/node-youtube-dl/commit/11da4f7))
481 +* version bump ([60cce67](https://github.com/przemyslawpluta/node-youtube-dl/commit/60cce67))
482 +
483 +
484 +
485 +<a name="1.3.1"></a>
486 +## 1.3.1 (2013-10-15)
487 +
488 +* always download latest version of youtube-dl ([c7de217](https://github.com/przemyslawpluta/node-youtube-dl/commit/c7de217))
489 +* fix reading download state ([174743a](https://github.com/przemyslawpluta/node-youtube-dl/commit/174743a))
490 +* formats change :/ ([e6f172d](https://github.com/przemyslawpluta/node-youtube-dl/commit/e6f172d))
491 +* make sure to delete downloaded file ([be74d80](https://github.com/przemyslawpluta/node-youtube-dl/commit/be74d80))
492 +* only download if new version ([1c8211c](https://github.com/przemyslawpluta/node-youtube-dl/commit/1c8211c))
493 +* specify format to download ([429687c](https://github.com/przemyslawpluta/node-youtube-dl/commit/429687c))
494 +* v1.3.1 ([23128d7](https://github.com/przemyslawpluta/node-youtube-dl/commit/23128d7))
495 +
496 +
497 +
498 +<a name="1.3.0"></a>
499 +# 1.3.0 (2013-09-13)
500 +
501 +* add getFormats() ([604fa7b](https://github.com/przemyslawpluta/node-youtube-dl/commit/604fa7b))
502 +* some style changes ([08a2ba5](https://github.com/przemyslawpluta/node-youtube-dl/commit/08a2ba5))
503 +* version bump ([1735865](https://github.com/przemyslawpluta/node-youtube-dl/commit/1735865))
504 +
505 +
506 +
507 +<a name="1.2.12"></a>
508 +## 1.2.12 (2013-08-27)
509 +
510 +* add id to download info ([eb92288](https://github.com/przemyslawpluta/node-youtube-dl/commit/eb92288))
511 +* better info test ([e4a1b2f](https://github.com/przemyslawpluta/node-youtube-dl/commit/e4a1b2f))
512 +* take into account multi line descriptions ([63ad7c2](https://github.com/przemyslawpluta/node-youtube-dl/commit/63ad7c2))
513 +* version bump ([8625ff4](https://github.com/przemyslawpluta/node-youtube-dl/commit/8625ff4))
514 +
515 +
516 +
517 +<a name="1.2.11"></a>
518 +## 1.2.11 (2013-08-23)
519 +
520 +* add id, itag, and resolution to `info()` ([11c7f68](https://github.com/przemyslawpluta/node-youtube-dl/commit/11c7f68))
521 +* version bump ([c5fc896](https://github.com/przemyslawpluta/node-youtube-dl/commit/c5fc896))
522 +
523 +
524 +
525 +<a name="1.2.10"></a>
526 +## 1.2.10 (2013-08-04)
527 +
528 +* cleaner example output ([7fcdf8f](https://github.com/przemyslawpluta/node-youtube-dl/commit/7fcdf8f))
529 +* correctly split lines ([13368d1](https://github.com/przemyslawpluta/node-youtube-dl/commit/13368d1))
530 +* update event-stream ([87983c1](https://github.com/przemyslawpluta/node-youtube-dl/commit/87983c1))
531 +* version bump ([b605c93](https://github.com/przemyslawpluta/node-youtube-dl/commit/b605c93))
532 +
533 +
534 +
535 +<a name="1.2.9"></a>
536 +## 1.2.9 (2013-08-04)
537 +
538 +* error checking ([524416b](https://github.com/przemyslawpluta/node-youtube-dl/commit/524416b))
539 +* update youtube-dl version ([f4d21ec](https://github.com/przemyslawpluta/node-youtube-dl/commit/f4d21ec))
540 +* version bump ([4fc9e1c](https://github.com/przemyslawpluta/node-youtube-dl/commit/4fc9e1c))
541 +
542 +
543 +
544 +<a name="1.2.8"></a>
545 +## 1.2.8 (2013-05-17)
546 +
547 +* [ci skip] ([8af4a1f](https://github.com/przemyslawpluta/node-youtube-dl/commit/8af4a1f))
548 +* check if progress is printed at least once ([189834d](https://github.com/przemyslawpluta/node-youtube-dl/commit/189834d))
549 +* fix tests ([e0895a4](https://github.com/przemyslawpluta/node-youtube-dl/commit/e0895a4))
550 +* minor cosmetics ([af3a82c](https://github.com/przemyslawpluta/node-youtube-dl/commit/af3a82c))
551 +* more thorough tests ([1d96ad2](https://github.com/przemyslawpluta/node-youtube-dl/commit/1d96ad2))
552 +* Release v1.2.8 ([85ca0da](https://github.com/przemyslawpluta/node-youtube-dl/commit/85ca0da))
553 +* update exists method ([1fbfb00](https://github.com/przemyslawpluta/node-youtube-dl/commit/1fbfb00))
554 +* update node versions ([73e93d1](https://github.com/przemyslawpluta/node-youtube-dl/commit/73e93d1))
555 +* update regexp for download progress ([f64ff44](https://github.com/przemyslawpluta/node-youtube-dl/commit/f64ff44))
556 +* update where youtube-dl is downloaded from ([dfe6234](https://github.com/przemyslawpluta/node-youtube-dl/commit/dfe6234))
557 +
558 +
559 +
560 +<a name="1.2.7"></a>
561 +## 1.2.7 (2012-08-19)
562 +
563 +* cleanup ([36e8741](https://github.com/przemyslawpluta/node-youtube-dl/commit/36e8741))
564 +* link to ytdl ([fc09348](https://github.com/przemyslawpluta/node-youtube-dl/commit/fc09348))
565 +* Release v1.2.7 ([dafa422](https://github.com/przemyslawpluta/node-youtube-dl/commit/dafa422))
566 +* version bump ([236a4a7](https://github.com/przemyslawpluta/node-youtube-dl/commit/236a4a7))
567 +
568 +
569 +
570 +<a name="1.2.6"></a>
571 +## 1.2.6 (2012-08-01)
572 +
573 +* buffer info call ([c46a993](https://github.com/przemyslawpluta/node-youtube-dl/commit/c46a993))
574 +* make sure to delete downloaded file ([5247bdb](https://github.com/przemyslawpluta/node-youtube-dl/commit/5247bdb))
575 +* separate youtubedl stdout by line ([a1b7294](https://github.com/przemyslawpluta/node-youtube-dl/commit/a1b7294))
576 +* version bump ([4f30db8](https://github.com/przemyslawpluta/node-youtube-dl/commit/4f30db8))
577 +
578 +
579 +
580 +<a name="1.2.5"></a>
581 +## 1.2.5 (2012-07-07)
582 +
583 +* [fix] path.existsSync was moved to fs.existsSync ([aadc85a](https://github.com/przemyslawpluta/node-youtube-dl/commit/aadc85a))
584 +* added node v0.8 ([a0dc4d8](https://github.com/przemyslawpluta/node-youtube-dl/commit/a0dc4d8))
585 +* existsSync ([876d969](https://github.com/przemyslawpluta/node-youtube-dl/commit/876d969))
586 +* fix existsSync ([24b7db7](https://github.com/przemyslawpluta/node-youtube-dl/commit/24b7db7))
587 +* removed engines ([1e3c85e](https://github.com/przemyslawpluta/node-youtube-dl/commit/1e3c85e))
588 +* use `fs.exists` ([658c651](https://github.com/przemyslawpluta/node-youtube-dl/commit/658c651))
589 +* version bump ([6d678d8](https://github.com/przemyslawpluta/node-youtube-dl/commit/6d678d8))
590 +
591 +
592 +
593 +<a name="1.2.4"></a>
594 +## 1.2.4 (2012-03-10)
595 +
596 +* more efficient youtube-dl download ([574cd7f](https://github.com/przemyslawpluta/node-youtube-dl/commit/574cd7f))
597 +* ver bump ([fe10efb](https://github.com/przemyslawpluta/node-youtube-dl/commit/fe10efb))
598 +* ver bump ([3fb0f0e](https://github.com/przemyslawpluta/node-youtube-dl/commit/3fb0f0e))
599 +
600 +
601 +
602 +<a name="1.2.3"></a>
603 +## 1.2.3 (2012-03-04)
604 +
605 +* used `__dirname` instead of `./` to save download ([b5fb4bf](https://github.com/przemyslawpluta/node-youtube-dl/commit/b5fb4bf))
606 +* used `path.join` to make it more cross-platform ([05c2ba3](https://github.com/przemyslawpluta/node-youtube-dl/commit/05c2ba3))
607 +
608 +
609 +
610 +<a name="1.2.2"></a>
611 +## 1.2.2 (2012-02-06)
612 +
613 +* Better error reporting ([e853b64](https://github.com/przemyslawpluta/node-youtube-dl/commit/e853b64))
614 +
615 +
616 +
617 +<a name="1.2.1"></a>
618 +## 1.2.1 (2012-01-04)
619 +
620 +* added test dir ([1695d60](https://github.com/przemyslawpluta/node-youtube-dl/commit/1695d60))
621 +* added test script ([39ecfd6](https://github.com/przemyslawpluta/node-youtube-dl/commit/39ecfd6))
622 +* better formatting ([16ad412](https://github.com/przemyslawpluta/node-youtube-dl/commit/16ad412))
623 +* better versioning ([40d175e](https://github.com/przemyslawpluta/node-youtube-dl/commit/40d175e))
624 +* cleared file ([c30ae25](https://github.com/przemyslawpluta/node-youtube-dl/commit/c30ae25))
625 +* javascript syntax ([42c9fd9](https://github.com/przemyslawpluta/node-youtube-dl/commit/42c9fd9))
626 +* organized readme ([c6069fd](https://github.com/przemyslawpluta/node-youtube-dl/commit/c6069fd))
627 +* removed v0.5 ([ef5e15c](https://github.com/przemyslawpluta/node-youtube-dl/commit/ef5e15c))
628 +* restored ([2ab9779](https://github.com/przemyslawpluta/node-youtube-dl/commit/2ab9779))
629 +* travis ci ([548d808](https://github.com/przemyslawpluta/node-youtube-dl/commit/548d808))
630 +* Written back to Javascript ([0063944](https://github.com/przemyslawpluta/node-youtube-dl/commit/0063944))
631 +
632 +
633 +
634 +<a name="1.2.0"></a>
635 +# 1.2.0 (2011-09-16)
636 +
637 +* added filename to data returned ([49909ca](https://github.com/przemyslawpluta/node-youtube-dl/commit/49909ca))
638 +* added tests ([1377915](https://github.com/przemyslawpluta/node-youtube-dl/commit/1377915))
639 +* fixed installation issue ([d05b14c](https://github.com/przemyslawpluta/node-youtube-dl/commit/d05b14c))
640 +* fixed symlink installation issue ([68199c0](https://github.com/przemyslawpluta/node-youtube-dl/commit/68199c0))
641 +
642 +
643 +
644 +<a name="1.1.0"></a>
645 +# 1.1.0 (2011-08-27)
646 +
647 +* now uses emitter ([7063855](https://github.com/przemyslawpluta/node-youtube-dl/commit/7063855))
648 +* update ([5c6ff08](https://github.com/przemyslawpluta/node-youtube-dl/commit/5c6ff08))
649 +
650 +
651 +
652 +<a name="1.0.4"></a>
653 +## 1.0.4 (2011-08-07)
654 +
655 +* added *.mp4 ([6b7a1dc](https://github.com/przemyslawpluta/node-youtube-dl/commit/6b7a1dc))
656 +* added scripts folder to tasks ([bfa584b](https://github.com/przemyslawpluta/node-youtube-dl/commit/bfa584b))
657 +* added scripts to watch task ([0afc347](https://github.com/przemyslawpluta/node-youtube-dl/commit/0afc347))
658 +* better organized ([dfd57c6](https://github.com/przemyslawpluta/node-youtube-dl/commit/dfd57c6))
659 +* commit ([059d81b](https://github.com/przemyslawpluta/node-youtube-dl/commit/059d81b))
660 +* convenience ([2cb471e](https://github.com/przemyslawpluta/node-youtube-dl/commit/2cb471e))
661 +* fixed error in info function ([ea6ceda](https://github.com/przemyslawpluta/node-youtube-dl/commit/ea6ceda))
662 +* fixed main ([572509b](https://github.com/przemyslawpluta/node-youtube-dl/commit/572509b))
663 +* minimalist ([bb5c5fb](https://github.com/przemyslawpluta/node-youtube-dl/commit/bb5c5fb))
664 +* now requires coffee-script to run ([8be7f53](https://github.com/przemyslawpluta/node-youtube-dl/commit/8be7f53))
665 +* organized ([aeaf9c8](https://github.com/przemyslawpluta/node-youtube-dl/commit/aeaf9c8))
666 +* organized ([2544054](https://github.com/przemyslawpluta/node-youtube-dl/commit/2544054))
667 +* organized ([cbea725](https://github.com/przemyslawpluta/node-youtube-dl/commit/cbea725))
668 +* removed coffeescript from installation ([b5bc9d8](https://github.com/przemyslawpluta/node-youtube-dl/commit/b5bc9d8))
669 +* updated version number ([df8861a](https://github.com/przemyslawpluta/node-youtube-dl/commit/df8861a))
670 +* when finished downloading, statistics data will be passed ([77a99e5](https://github.com/przemyslawpluta/node-youtube-dl/commit/77a99e5))
671 +
672 +
673 +
1 +Copyright (C) 2011 by Roly Fentanes
2 +
3 +Permission is hereby granted, free of charge, to any person obtaining a copy
4 +of this software and associated documentation files (the "Software"), to deal
5 +in the Software without restriction, including without limitation the rights
6 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 +copies of the Software, and to permit persons to whom the Software is
8 +furnished to do so, subject to the following conditions:
9 +
10 +The above copyright notice and this permission notice shall be included in
11 +all copies or substantial portions of the Software.
12 +
13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 +THE SOFTWARE.
1 +# youtube-dl
2 +
3 +[![Build Status](https://travis-ci.org/przemyslawpluta/node-youtube-dl.svg?branch=master)](https://travis-ci.org/przemyslawpluta/node-youtube-dl) [![npm version](https://badge.fury.io/js/youtube-dl.svg)](https://badge.fury.io/js/youtube-dl)
4 +
5 +Download videos from youtube in node.js using [youtube-dl](http://rg3.github.com/youtube-dl/).
6 +
7 +If you're only interested in downloading only from youtube, you should consider using [pure Javascript youtube downloading module](https://github.com/fent/node-ytdl).
8 +
9 +## Installation
10 +
11 +With [npm](https://www.npmjs.com/) do:
12 +
13 +``` sh
14 +npm install @microlink/youtube-dl
15 +```
16 +
17 +## Usage
18 +
19 +### Downloading videos
20 +
21 +``` js
22 +var fs = require('fs');
23 +var youtubedl = require('youtube-dl');
24 +var video = youtubedl('http://www.youtube.com/watch?v=90AiXO1pAiA',
25 + // Optional arguments passed to youtube-dl.
26 + ['--format=18'],
27 + // Additional options can be given for calling `child_process.execFile()`.
28 + { cwd: __dirname });
29 +
30 +// Will be called when the download starts.
31 +video.on('info', function(info) {
32 + console.log('Download started');
33 + console.log('filename: ' + info._filename);
34 + console.log('size: ' + info.size);
35 +});
36 +
37 +video.pipe(fs.createWriteStream('myvideo.mp4'));
38 +```
39 +
40 +It will produce an output that looks like the following when ran.
41 +
42 +```bash
43 +Got video info
44 +saving to T-ara - Number Nine - MV - 티아라-Seku9G1kT0c.mp4
45 +100.00%
46 +```
47 +
48 +### Resuming partially downloaded videos
49 +
50 +``` js
51 +var youtubedl = require('./');
52 +var fs = require('fs');
53 +var output = 'myvideo.mp4';
54 +
55 +var downloaded = 0;
56 +if (fs.existsSync(output)) {
57 + downloaded = fs.statSync(output).size;
58 +}
59 +
60 +var video = youtubedl('https://www.youtube.com/watch?v=179MiZSibco',
61 +
62 + // Optional arguments passed to youtube-dl.
63 + ['--format=18'],
64 +
65 + // start will be sent as a range header
66 + { start: downloaded, cwd: __dirname });
67 +
68 +// Will be called when the download starts.
69 +video.on('info', function(info) {
70 + console.log('Download started');
71 + console.log('filename: ' + info._filename);
72 +
73 + // info.size will be the amount to download, add
74 + var total = info.size + downloaded;
75 + console.log('size: ' + total);
76 +
77 + if (downloaded > 0) {
78 + // size will be the amount already downloaded
79 + console.log('resuming from: ' + downloaded);
80 +
81 + // display the remaining bytes to download
82 + console.log('remaining bytes: ' + info.size);
83 + }
84 +});
85 +
86 +video.pipe(fs.createWriteStream('myvideo.mp4', { flags: 'a' }));
87 +
88 +// Will be called if download was already completed and there is nothing more to download.
89 +video.on('complete', function complete(info) {
90 + 'use strict';
91 + console.log('filename: ' + info._filename + ' already downloaded.');
92 +});
93 +
94 +video.on('end', function() {
95 + console.log('finished downloading!');
96 +});
97 +```
98 +
99 +It will produce an output that looks like the following when ran.
100 +
101 +**Output:**
102 +
103 +``` sh
104 +[~/nodejs/node-youtube-dl/example]$ node resume.js
105 +Download started
106 +filename: 1 1 1-179MiZSibco.mp4
107 +size: 5109213
108 +^C
109 +```
110 +
111 +``` sh
112 +[~/nodejs/node-youtube-dl/example]$ node resume.js
113 +Download started
114 +filename: 1 1 1-179MiZSibco.mp4
115 +size: 5109213
116 +resuming from: 917504
117 +remaining bytes: 4191709
118 +finished downloading
119 +```
120 +
121 +### Getting video information
122 +
123 +``` js
124 +var youtubedl = require('youtube-dl');
125 +var url = 'http://www.youtube.com/watch?v=WKsjaOqDXgg';
126 +// Optional arguments passed to youtube-dl.
127 +var options = ['--username=user', '--password=hunter2'];
128 +youtubedl.getInfo(url, options, function(err, info) {
129 + if (err) throw err;
130 +
131 + console.log('id:', info.id);
132 + console.log('title:', info.title);
133 + console.log('url:', info.url);
134 + console.log('thumbnail:', info.thumbnail);
135 + console.log('description:', info.description);
136 + console.log('filename:', info._filename);
137 + console.log('format id:', info.format_id);
138 +});
139 +```
140 +
141 +Running that will produce something like
142 +
143 +``` sh
144 +id: WKsjaOqDXgg
145 +title: Ace Rimmer to the Rescue
146 +url: http://r5---sn-p5qlsn7e.c.youtube.com/videoplayback?ms=au&ip=160.79.125.18&cp=U0hWTFVQVl9FTENONl9NSlpDOjgtU1VsODlkVmRH&id=58ab2368ea835e08&source=youtube&expire=1377558202&factor=1.25&key=yt1&ipbits=8&mt=1377534150&itag=34&sver=3&upn=-rGWz2vYpN4&fexp=912306%2C927900%2C919395%2C926518%2C936203%2C913819%2C929117%2C929121%2C929906%2C929907%2C929922%2C929127%2C929129%2C929131%2C929930%2C925726%2C925720%2C925722%2C925718%2C929917%2C906945%2C929919%2C929933%2C912521%2C932306%2C913428%2C904830%2C919373%2C930803%2C908536%2C904122%2C938701%2C936308%2C909549%2C900816%2C912711%2C904494%2C904497%2C900375%2C906001&sparams=algorithm%2Cburst%2Ccp%2Cfactor%2Cid%2Cip%2Cipbits%2Citag%2Csource%2Cupn%2Cexpire&mv=m&burst=40&algorithm=throttle-factor&signature=ABD3A847684AD9B39331E567568D3FA0DCFA4776.7895521E130A042FB3625A17242CE3C02A4460B7&ratebypass=yes
147 +thumbnail: https://i1.ytimg.com/vi/WKsjaOqDXgg/hqdefault.jpg
148 +description: An old Red Dwarf eposide where Ace Rimmer saves the Princess Bonjella.
149 +filename: Ace Rimmer to the Rescue-WKsjaOqDXgg.flv
150 +format id: 34
151 +```
152 +
153 +You can use an array of urls to produce an array of response objects with matching array index (e.g. the 1st response object will match the first url etc...)
154 +
155 +``` js
156 +var youtubedl = require('youtube-dl');
157 +var url1 = 'http://www.youtube.com/watch?v=WKsjaOqDXgg';
158 +var url2 = 'https://vimeo.com/6586873';
159 +youtubedl.getInfo([url1, url2], function(err, info) {
160 + if (err) throw err;
161 +
162 + console.log('title for the url1:', info[0].title);
163 + console.log('title for the url2:', info[1].title);
164 +});
165 +```
166 +
167 +### Downloading subtitles
168 +
169 +``` js
170 +var youtubedl = require('youtube-dl');
171 +var url = 'https://youtu.be/PizwcirYuGY';
172 +
173 +var options = {
174 + // Write automatic subtitle file (youtube only)
175 + auto: false,
176 + // Downloads all the available subtitles.
177 + all: false,
178 + // Languages of subtitles to download, separated by commas.
179 + lang: 'en',
180 + // The directory to save the downloaded files in.
181 + cwd: __dirname,
182 +};
183 +youtubedl.getSubs(url, options, function(err, files) {
184 + if (err) throw err;
185 +
186 + console.log('subtitle files downloaded:', files);
187 +});
188 +```
189 +
190 +### Downloading thumbnails
191 +
192 +``` js
193 +var youtubedl = require('youtube-dl');
194 +var url = 'https://youtu.be/PizwcirYuGY';
195 +
196 +var options = {
197 + // Downloads available thumbnail.
198 + all: false,
199 + // The directory to save the downloaded files in.
200 + cwd: __dirname,
201 +};
202 +youtubedl.getThumbs(url, options, function(err, files) {
203 + if (err) throw err;
204 + console.log('thumbnail file downloaded:', files);
205 +});
206 +```
207 +
208 +For more usage info on youtube-dl and the arguments you can pass to it, do `youtube-dl -h` or go to the [youtube-dl documentation][].
209 +
210 +### Downloading playlists
211 +
212 +``` js
213 +
214 +var path = require('path');
215 +var fs = require('fs');
216 +var ytdl = require('youtube-dl');
217 +
218 +function playlist(url) {
219 +
220 + 'use strict';
221 + var video = ytdl(url);
222 +
223 + video.on('error', function error(err) {
224 + console.log('error 2:', err);
225 + });
226 +
227 + var size = 0;
228 + video.on('info', function(info) {
229 + size = info.size;
230 + var output = path.join(__dirname + '/', size + '.mp4');
231 + video.pipe(fs.createWriteStream(output));
232 + });
233 +
234 + var pos = 0;
235 + video.on('data', function data(chunk) {
236 + pos += chunk.length;
237 + // `size` should not be 0 here.
238 + if (size) {
239 + var percent = (pos / size * 100).toFixed(2);
240 + process.stdout.cursorTo(0);
241 + process.stdout.clearLine(1);
242 + process.stdout.write(percent + '%');
243 + }
244 + });
245 +
246 + video.on('next', playlist);
247 +
248 +}
249 +
250 +playlist('https://www.youtube.com/playlist?list=PLEFA9E9D96CB7F807');
251 +
252 +```
253 +
254 +### Getting the list of extractors
255 +
256 +``` js
257 +var youtubedl = require('youtube-dl');
258 +youtubedl.getExtractors(true, function(err, list) {
259 + console.log('Found ' + list.length + ' extractors');
260 + for (var i = 0; i < list.length; i++) {
261 + console.log(list[i]);
262 + }
263 +});
264 +```
265 +
266 +Will print something like
267 +
268 +``` sh
269 +Found 521 extractors
270 +1up.com
271 +220.ro
272 +24video
273 +3sat
274 +```
275 +
276 +### Call the `youtube-dl` binary directly
277 +
278 +This module doesn't have `youtube-dl` download the video. Instead, it uses the `url` key from the `--dump-json` CLI option to create a node stream. That way, it can be used like any other node stream.
279 +
280 +If that, or none of the above support your use case, you can use `ytdl.exec()` to call `youtube-dl` however you like.
281 +
282 +``` js
283 +ytdl.exec(url, ['-x', '--audio-format', 'mp3'], {}, function(err, output) {
284 + if (err) throw err;
285 + console.log(output.join('\n'));
286 +});
287 +```
288 +
289 +### Update
290 +
291 +Since the youtube-dl binary is updated regularly, you can run `npm run update` to check for and download any updates for it. You can also require `../lib/downloader` in your app if you'd like to place `youtube-dl` binary in a specific directory and control when it gets updates.
292 +
293 +``` js
294 +var downloader = require('../lib/downloader');
295 +
296 +downloader('path/to-binary', function error(err, done) {
297 + 'use strict';
298 + if (err) { return console.log(err.stack); }
299 + console.log(done);
300 +});
301 +```
302 +
303 +### Tests
304 +
305 +Tests are written with [vows](http://vowsjs.org/)
306 +
307 +``` sh
308 +npm test
309 +```
310 +
311 +## License
312 +
313 +MIT
314 +
315 +[youtube-dl]: http://rg3.github.com/youtube-dl/
316 +[youtube-dl documentation]: http://rg3.github.com/youtube-dl/documentation.html
1 +{"version":"2019.05.20","path":null,"exec":"youtube-dl.exe"}
...\ No newline at end of file ...\ No newline at end of file
No preview for this file type
1 +var fs = require('fs');
2 +var path = require('path');
3 +var mkdirp = require('mkdirp');
4 +var request = require('request');
5 +
6 +// First, look for the download link.
7 +/*jshint maxlen:false */
8 +var dir, filePath;
9 +var isWin = (process.platform === 'win32' || process.env.NODE_PLATFORM === 'windows') ? true : false;
10 +var defaultBin = path.join(__dirname, '..', 'bin');
11 +var defaultPath = path.join(defaultBin, 'details');
12 +var url = 'https://yt-dl.org/downloads/latest/youtube-dl';
13 +
14 +function download(url, callback) {
15 + 'use strict';
16 +
17 + var status = null;
18 +
19 + // download the correct version of the binary based on the platform
20 + url = exec(url);
21 +
22 + request.get(url, { followRedirect: false }, function (err, res) {
23 + if (res.statusCode !== 302) {
24 + return callback(new Error('Did not get redirect for the latest version link. Status: ' + res.statusCode));
25 + }
26 +
27 + var url = res.headers.location;
28 + var downloadFile = request.get(url);
29 + var newVersion = /yt-dl\.org\/downloads\/(\d{4}\.\d\d\.\d\d(\.\d)?)\/youtube-dl/.exec(url)[1];
30 +
31 + downloadFile.on('response', function response(res) {
32 + if (res.statusCode !== 200) {
33 + status = new Error('Response Error: ' + res.statusCode);
34 + return;
35 + }
36 + downloadFile.pipe(fs.createWriteStream(filePath, { mode: 493 }));
37 + });
38 +
39 + downloadFile.on('error', function error(err) { callback(err); });
40 +
41 + downloadFile.on('end', function end() { callback(status, newVersion); });
42 +
43 + });
44 +}
45 +
46 +function exec(path) {
47 + 'use strict';
48 + return (isWin) ? path + '.exe' : path;
49 +}
50 +
51 +function createBase(binDir) {
52 + 'use strict';
53 + dir = (binDir) ? binDir : defaultBin;
54 + mkdirp.sync(dir);
55 + if (binDir) { mkdirp.sync(defaultBin); }
56 + filePath = path.join(dir, exec('youtube-dl'));
57 +}
58 +
59 +function downloader(binDir, callback) {
60 +
61 + 'use strict';
62 + if (typeof binDir === 'function') {
63 + callback = binDir;
64 + binDir = null;
65 + }
66 +
67 + createBase(binDir);
68 +
69 + download(url, function error(err, newVersion) {
70 + if (err) { return callback(err); }
71 + fs.writeFileSync(defaultPath, JSON.stringify({ version: newVersion, path: ((binDir) ? filePath : binDir), exec: exec('youtube-dl') }), 'utf8');
72 + callback(null, 'Downloaded youtube-dl ' + newVersion);
73 + });
74 +}
75 +
76 +module.exports = downloader;
1 +// Arguments we dont want users to use with youtube-dl
2 +// because they will break the module.
3 +var badArgs = [
4 + '-h', '--help',
5 + '-v', '--version',
6 + '-U', '--update',
7 + '-q', '--quiet',
8 + '-s', '--simulate',
9 + '-g', '--get-url',
10 + '-e', '--get-title',
11 + '--get-id',
12 + '--get-thumbnail',
13 + '--get-description',
14 + '--get-duration',
15 + '--get-filename',
16 + '--get-format',
17 + '-j', '--dump-json',
18 + '--newline',
19 + '--no-progress',
20 + '--console-title',
21 + '-v', '--verbose',
22 + '--dump-intermediate-pages',
23 + '--write-pages',
24 + '--print-traffic',
25 +];
26 +
27 +/**
28 + * Helps parse options used in youtube-dl command.
29 + *
30 + * @param {Array.<String>}
31 + * @return {Array.<String>}
32 + */
33 +exports.parseOpts = function (args) {
34 + var pos;
35 + for (var i = 0, len = badArgs.length; i < len; i++) {
36 + if ((pos = args.indexOf(badArgs[i])) !== -1) {
37 + args.splice(pos, 1);
38 + }
39 + }
40 + return args;
41 +};
42 +
43 +
44 +/**
45 + * Converts seconds to format hh:mm:ss
46 + *
47 + * @param {Number} seconds
48 + * @return {String}
49 + */
50 +exports.formatDuration = function (seconds) {
51 + var parts = [];
52 + parts.push(seconds % 60);
53 + var minutes = Math.floor(seconds / 60);
54 + if (minutes > 0) {
55 + parts.push(minutes % 60);
56 + var hours = Math.floor(minutes / 60);
57 + if (hours > 0) {
58 + parts.push(hours);
59 + }
60 + }
61 + return parts.reverse().join(':');
62 +};
1 +'use strict';
2 +
3 +const execFile = require('child_process').execFile;
4 +const streamify = require('streamify');
5 +const request = require('request');
6 +const hms = require('hh-mm-ss');
7 +const path = require('path');
8 +const http = require('http');
9 +const url = require('url');
10 +const fs = require('fs');
11 +
12 +const util = require('./util');
13 +
14 +const TEN_MEGABYTES = 1000 * 1000 * 10;
15 +
16 +const execFileOpts = { maxBuffer: TEN_MEGABYTES }
17 +
18 +const detailsPath = path.join(__dirname, '..', 'bin/details')
19 +
20 +const ytdlBinary = (() => {
21 + if (fs.existsSync(detailsPath)) {
22 + const details = JSON.parse(fs.readFileSync(detailsPath));
23 + return details.path ? details.path : path.resolve(__dirname, '..', 'bin', details.exec);
24 + }
25 +
26 + if (!fs.existsSync(ytdlBinary)) {
27 + console.error('ERROR: unable to locate youtube-dl details in ' + path.dirname(ytdlBinary));
28 + process.exit(1);
29 + }
30 +})()
31 +
32 +const isWin = (process.platform === 'win32' || process.env.NODE_PLATFORM === 'windows') ? true : false;
33 +
34 +const isDebug = /^\[debug\] /;
35 +const isWarning = /^WARNING: /;
36 +const isYouTubeRegex = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\//;
37 +const isNoSubsRegex = /WARNING: video doesn't have subtitles|no closed captions found/;
38 +const videoNotAvailable = new RegExp(
39 + 'This video is not available|' +
40 + 'This video has been removed by the user|' +
41 + 'Please sign in to view this video|' +
42 + 'This video is no longer available|' +
43 + 'The uploader has not made this video available|' +
44 + 'This video contains content from'
45 +);
46 +
47 +const subsRegex = /--write-sub|--write-srt|--srt-lang|--all-subs/;
48 +
49 +function youtubeDl(args, options, callback) {
50 + let passOver = false;
51 +
52 + execFile(ytdlBinary, args, { ...execFileOpts, ...options }, function done(err, stdout, stderr) {
53 + if (err) {
54 + if (videoNotAvailable.test(err.message)) passOver = true;
55 + if (!passOver) return callback(err);
56 + }
57 +
58 + if (stderr && !passOver) {
59 + // Try once to download video if no subtitles available
60 + if (!options.nosubs && isNoSubsRegex.test(stderr)) {
61 + let i;
62 + let cleanupOpt = args2;
63 +
64 + for (i = cleanupOpt.length - 1; i >= 0; i--) {
65 + if (subsRegex.test(cleanupOpt[i])) { cleanupOpt.splice(i, 1); }
66 + }
67 +
68 + options.nosubs = true;
69 +
70 + return call(video, args1, cleanupOpt, options, callback);
71 + }
72 +
73 + if (isDebug.test(stderr) && args.indexOf('--verbose') > -1) {
74 + console.log('\n' + stderr);
75 + } else if (isWarning.test(stderr)) {
76 + console.warn(stderr);
77 + } else {
78 + return callback(new Error(stderr.slice(7)));
79 + }
80 + }
81 +
82 + if (passOver && stdout === '' && urls.length > 1) {
83 + urls.shift();
84 + return call(urls, args1, args2, options, callback);
85 + }
86 +
87 + return callback(null, stdout.trim().split(/\r?\n/));
88 + })
89 +}
90 +
91 +
92 +/**
93 + * Processes data
94 + *
95 + * @param {Object} data
96 + * @param {Object} options
97 + * @param {Object} stream
98 + */
99 +
100 +function processData(data, options, stream) {
101 + const item = !data.length ? data : data.shift();
102 +
103 + // fix for pause/resume downloads
104 + const headers = { 'Host': url.parse(item.url).hostname };
105 +
106 + if (options && options.start > 0) headers.Range = 'bytes=' + options.start + '-';
107 +
108 + const req = request({ url: item.url, headers: headers });
109 +
110 + req.on('response', function response(res) {
111 +
112 + const size = parseInt(res.headers['content-length'], 10);
113 + if (size) item.size = size;
114 +
115 + if (options && options.start > 0 && res.statusCode === 416) {
116 + // the file that is being resumed is complete.
117 + return stream.emit('complete', item);
118 + }
119 +
120 + if (res.statusCode !== 200 && res.statusCode !== 206) {
121 + return stream.emit('error', new Error('status code ' + res.statusCode));
122 + }
123 +
124 + stream.emit('info', item);
125 +
126 + stream.on('end', function end() {
127 + if (data.length) stream.emit('next', data);
128 + });
129 +
130 + });
131 +
132 + return stream.resolve(req);
133 +}
134 +
135 +/**
136 + * Downloads a video.
137 + *
138 + * @param {String} videoUrl
139 + * @param {!Array.<String>} args
140 + * @param {!Object} options
141 + */
142 +const ytdl = module.exports = function (videoUrl, args, options) {
143 + const stream = streamify({ superCtor: http.ClientResponse, readable: true, writable: false });
144 +
145 + if (typeof videoUrl !== 'string') {
146 + processData(videoUrl, options, stream);
147 + return stream;
148 + }
149 +
150 + ytdl.getInfo(videoUrl, args, options, function getInfo(err, data) {
151 + return err ? stream.emit('error', err) : processData(data, options, stream);
152 + });
153 +
154 + return stream;
155 +};
156 +
157 +/**
158 + * Calls youtube-dl with some arguments and the `callback`
159 + * gets called with the output.
160 + *
161 + * @param {String|Array.<String>}
162 + * @param {Array.<String>} args
163 + * @param {Array.<String>} args2
164 + * @param {Object} options
165 + * @param {Function(!Error, String)} callback
166 + */
167 +function call(urls, args1, args2, options = {}, callback) {
168 + let args = args1;
169 + if (args2) args = args.concat(args2);
170 +
171 + // set encoding on windows to support unicode titles
172 + if (isWin) {
173 + // check if encoding is already set
174 + let hasEncoding = false;
175 + for (let i = 0; i < args.length; i++) {
176 + if (args[i] === '--encoding') {
177 + hasEncoding = true;
178 + break;
179 + }
180 + }
181 + if (!hasEncoding) {
182 + args.push('--encoding');
183 + args.push('utf8');
184 + }
185 + }
186 +
187 +
188 + if (urls !== null) {
189 + if (typeof urls === 'string') {
190 + urls = [urls];
191 + }
192 +
193 + for (let i = 0; i < urls.length; i++) {
194 + const video = urls[i];
195 + if (isYouTubeRegex.test(video)) {
196 + // Get possible IDs.
197 + const details = url.parse(video, true);
198 + let id = details.query.v || '';
199 + if (id) {
200 + args.push('http://www.youtube.com/watch?v=' + id);
201 + } else {
202 + // Get possible IDs for youtu.be from urladdr.
203 + id = details.pathname.slice(1).replace(/^v\//, '');
204 + if (id) {
205 + args.push(video);
206 + args.unshift('-i');
207 + }
208 + }
209 + } else {
210 + if (i === 0)
211 + args.push('--');
212 + args.push(video);
213 + }
214 + }
215 + }
216 +
217 + return youtubeDl(args, options, callback)
218 +}
219 +
220 +/**
221 + * Calls youtube-dl with some arguments and the `callback`
222 + * gets called with the output.
223 + *
224 + * @param {String} url
225 + * @param {Array.<String>} args
226 + * @param {Object} options
227 + * @param {Function(!Error, String)} callback
228 + */
229 +ytdl.exec = function exec(url, args, options, callback) {
230 + return call(url, [], args, options, callback);
231 +};
232 +
233 +
234 +/**
235 + * @param {Object} data
236 + * @returns {Object}
237 + */
238 +function parseInfo(data) {
239 + const info = JSON.parse(data);
240 +
241 + // Add and process some entries to keep backwards compatibility
242 + Object.defineProperty(info, 'filename', {
243 + get: function get() {
244 + console.warn('`info.filename` is deprecated, use `info._filename`');
245 + return info._filename;
246 + }
247 + });
248 + Object.defineProperty(info, 'itag', {
249 + get: function get() {
250 + console.warn('`info.itag` is deprecated, use `info.format_id`');
251 + return info.format_id;
252 + }
253 + });
254 + Object.defineProperty(info, 'resolution', {
255 + get: function get() {
256 + console.warn('`info.resolution` is deprecated, use `info.format`');
257 + return info.format.split(' - ')[1];
258 + }
259 + });
260 +
261 + info._duration_raw = info.duration;
262 + info._duration_hms = (info.duration) ? hms.fromS(info.duration, 'hh:mm:ss') : info.duration;
263 + info.duration = (info.duration) ? util.formatDuration(info.duration) : info.duration;
264 +
265 + return info;
266 +}
267 +
268 +/**
269 + * Set path from youtube-dl.
270 + *
271 + * @param {String} path
272 + */
273 +ytdl.setYtdlBinary = function setYtdlBinary(path) {
274 + ytdlBinary = path;
275 +};
276 +
277 +/**
278 + * Get path from youtube-dl.
279 + *
280 + * @param {String} path
281 + */
282 +ytdl.getYtdlBinary = function getYtdlBinary() {
283 + return ytdlBinary;
284 +};
285 +
286 +
287 +/**
288 + * Gets info from a video.
289 + *
290 + * @param {String} url
291 + * @param {Array.<String>} args
292 + * @param {Object} options
293 + * @param {Function(!Error, Object)} callback
294 + */
295 +ytdl.getInfo = function getInfo(url, args, options, callback) {
296 + if (typeof options === 'function') {
297 + callback = options;
298 + options = {};
299 + } else if (typeof args === 'function') {
300 + callback = args;
301 + options = {};
302 + args = [];
303 + }
304 + const defaultArgs = ['--dump-json'];
305 + if (!args || args.indexOf('-f') < 0 && args.indexOf('--format') < 0 &&
306 + args.every(function (a) {
307 + return a.indexOf('--format=') !== 0;
308 + })) {
309 + defaultArgs.push('-f');
310 + defaultArgs.push('best');
311 + }
312 +
313 + call(url, defaultArgs, args, options, function done(err, data) {
314 + if (err) return callback(err);
315 + let info;
316 +
317 + try {
318 + info = data.map(parseInfo);
319 + } catch (err) {
320 + return callback(err);
321 + }
322 +
323 + return callback(null, info.length === 1 ? info[0] : info);
324 + });
325 +};
326 +
327 +/**
328 + * @param {String} url
329 + * @param {Object} options
330 + * {Boolean} auto
331 + * {Boolean} all
332 + * {String} lang
333 + * {String} cwd
334 + * @param {Function(!Error, Object)} callback
335 + */
336 +ytdl.getSubs = function getSubs(url, options, callback) {
337 + if (typeof options === 'function') {
338 + callback = options;
339 + options = {};
340 + }
341 +
342 + const args = ['--skip-download'];
343 + args.push('--write' + (options.auto ? '-auto' : '') + '-sub');
344 + if (options.all) {
345 + args.push('--all-subs');
346 + }
347 + if (options.lang) {
348 + args.push('--sub-lang=' + options.lang);
349 + }
350 + if (!options.warrning) {
351 + args.push('--no-warnings');
352 + }
353 +
354 + call(url, args, [], { cwd: options.cwd }, function (err, data) {
355 + if (err) return callback(err);
356 +
357 + const files = [];
358 + for (let i = 0, len = data.length; i < len; i++) {
359 + const line = data[i];
360 + if (line.indexOf('[info] Writing video subtitles to: ') === 0) {
361 + files.push(line.slice(35));
362 + }
363 + }
364 +
365 + return callback(null, files);
366 + });
367 +};
368 +
369 +/**
370 + * @param {String} url
371 + * @param {Object} options
372 + * {Boolean} all
373 + * {String} cwd
374 + * @param {Function(!Error, Object)} callback
375 + */
376 +ytdl.getThumbs = function getThumbs(url, options, callback) {
377 + if (typeof options === 'function') {
378 + callback = options;
379 + options = {};
380 + }
381 +
382 + const args = ['--skip-download'];
383 +
384 + if (options.all) {
385 + args.push('--write-all-thumbnails');
386 + } else {
387 + args.push('--write-thumbnail');
388 + }
389 +
390 + if (!options.warrning) {
391 + args.push('--no-warnings');
392 + }
393 +
394 + call(url, args, [], { cwd: options.cwd }, function (err, data) {
395 + if (err) return callback(err);
396 +
397 + const files = [];
398 + for (let i = 0, len = data.length; i < len; i++) {
399 + const line = data[i];
400 + const info = 'Writing thumbnail to: ';
401 + if (line.indexOf(info) !== -1) {
402 + files.push(line.slice(line.indexOf(info) + info.length));
403 + }
404 + }
405 + return callback(null, files);
406 + });
407 +};
408 +
409 +/**
410 + * @param {!Boolean} descriptions
411 + * @param {!Object} options
412 + * @param {Function(!Error, Object)} callback
413 + */
414 +ytdl.getExtractors = function getExtractors(descriptions, options, callback) {
415 + if (typeof options === 'function') {
416 + callback = options;
417 + options = {};
418 + } else if (typeof descriptions === 'function') {
419 + callback = descriptions;
420 + options = {};
421 + descriptions = false;
422 + }
423 +
424 + const args = descriptions ? ['--extractor-descriptions'] : ['--list-extractors'];
425 + return call(null, args, null, options, callback);
426 +};
1 +{
2 + "_from": "youtube-dl",
3 + "_id": "youtube-dl@1.13.1",
4 + "_inBundle": false,
5 + "_integrity": "sha512-89mUKwOavaojNKQlyzW+A7Dph5G/oPYs6T/PTMcvgdRQ5E2+uDQgYPxWHQDMBhHOkxQaxvxQTiTPKQLdg0OI4w==",
6 + "_location": "/youtube-dl",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "tag",
10 + "registry": true,
11 + "raw": "youtube-dl",
12 + "name": "youtube-dl",
13 + "escapedName": "youtube-dl",
14 + "rawSpec": "",
15 + "saveSpec": null,
16 + "fetchSpec": "latest"
17 + },
18 + "_requiredBy": [
19 + "#USER",
20 + "/"
21 + ],
22 + "_resolved": "https://registry.npmjs.org/youtube-dl/-/youtube-dl-1.13.1.tgz",
23 + "_shasum": "2da47c0dad3c5391e2172b7811da46501b82edc4",
24 + "_spec": "youtube-dl",
25 + "_where": "C:\\Users\\user\\Desktop\\오소git\\오소플젝\\Youtube_MPL",
26 + "author": {
27 + "name": "Roly Fentanes",
28 + "url": "https://github.com/fent"
29 + },
30 + "bugs": {
31 + "url": "https://github.com/przemyslawpluta/node-youtube-dl/issues"
32 + },
33 + "bundleDependencies": false,
34 + "contributors": [
35 + {
36 + "name": "Roly Fentanes",
37 + "email": "roly426@gmail.com"
38 + },
39 + {
40 + "name": "przemyslawpluta",
41 + "email": "przemekpluta@hotmail.com"
42 + },
43 + {
44 + "name": "Jay Salvat",
45 + "email": "jay@jaysalvat.com"
46 + },
47 + {
48 + "name": "Kiko Beats",
49 + "email": "josefrancisco.verdu@gmail.com"
50 + },
51 + {
52 + "name": "Jaime Marquínez Ferrándiz",
53 + "email": "jaime.marquinez.ferrandiz@gmail.com"
54 + },
55 + {
56 + "name": "Jay Baker",
57 + "email": "logikal@gmail.com"
58 + },
59 + {
60 + "name": "Jack Li",
61 + "email": "jack.lee2980@gmail.com"
62 + },
63 + {
64 + "name": "Sergey M․",
65 + "email": "dstftw@gmail.com"
66 + },
67 + {
68 + "name": "optikfluffel",
69 + "email": "optik@fluffel.io"
70 + },
71 + {
72 + "name": "EragonJ",
73 + "email": "eragonj@eragonj.me"
74 + },
75 + {
76 + "name": "t3rr0r",
77 + "email": "mail@t3rr0r.com"
78 + },
79 + {
80 + "name": "tifroz",
81 + "email": "hhardel@gmail.com"
82 + },
83 + {
84 + "name": "Jeremy Louie",
85 + "email": "jeremy@jeremylouie.com"
86 + },
87 + {
88 + "name": "Calvin",
89 + "email": "calvin@sealtelecom.com.br"
90 + },
91 + {
92 + "name": "walheresq",
93 + "email": "walheresq@hotmail.com"
94 + },
95 + {
96 + "name": "▟ ▖▟ ▖",
97 + "email": "dodo.the.last@gmail.com"
98 + },
99 + {
100 + "name": "Davide Pastore",
101 + "email": "pasdavide@gmail.com"
102 + },
103 + {
104 + "name": "Farrin Reid",
105 + "email": "blakmatrix@gmail.com"
106 + },
107 + {
108 + "name": "Jason Penny",
109 + "email": "jason@jooraccess.com"
110 + },
111 + {
112 + "name": "Juan C. Olivares",
113 + "email": "cristobal@cxsoftware.com"
114 + },
115 + {
116 + "name": "Lopez Hugo",
117 + "email": "hugo.lpz@gmail.com"
118 + },
119 + {
120 + "name": "Meral",
121 + "email": "meral.harbes@gmail.com"
122 + },
123 + {
124 + "name": "Michael Nguyen",
125 + "email": "tehtotalpwnage@gmail.com"
126 + },
127 + {
128 + "name": "Nicolas Gotchac",
129 + "email": "ngotchac@gmail.com"
130 + },
131 + {
132 + "name": "Parikshit Hooda",
133 + "email": "phooda804@live.com"
134 + },
135 + {
136 + "name": "Pietro",
137 + "email": "pietro.passarelli@gmail.com"
138 + },
139 + {
140 + "name": "Sagi Nadir",
141 + "email": "saginadir@gmail.com"
142 + },
143 + {
144 + "name": "btmdave",
145 + "email": "dave@bluetopmedia.com"
146 + },
147 + {
148 + "name": "coderaiser",
149 + "email": "mnemonic.enemy@gmail.com"
150 + }
151 + ],
152 + "dependencies": {
153 + "hh-mm-ss": "~1.2.0",
154 + "mkdirp": "~0.5.1",
155 + "request": "~2.88.0",
156 + "streamify": "~0.2.9"
157 + },
158 + "deprecated": false,
159 + "description": "youtube-dl driver for node",
160 + "devDependencies": {
161 + "vows": "latest"
162 + },
163 + "files": [
164 + "lib",
165 + "scripts"
166 + ],
167 + "homepage": "https://github.com/przemyslawpluta/node-youtube-dl#readme",
168 + "keywords": [
169 + "download",
170 + "video",
171 + "youtube"
172 + ],
173 + "license": "MIT",
174 + "main": "./lib/youtube-dl.js",
175 + "name": "youtube-dl",
176 + "repository": {
177 + "type": "git",
178 + "url": "git://github.com/przemyslawpluta/node-youtube-dl.git"
179 + },
180 + "scripts": {
181 + "postinstall": "node ./scripts/download.js",
182 + "test": "vows ./test/*.js --spec",
183 + "update": "node ./scripts/download.js"
184 + },
185 + "version": "1.13.1"
186 +}
1 +var downloader = require('../lib/downloader');
2 +
3 +downloader(function error(err, done) {
4 + 'use strict';
5 + if (err) { return console.log(err.stack); }
6 + console.log(done);
7 +});
1 +language: node_js
2 +node_js:
3 + - node
1 +The MIT License (MIT)
2 +
3 +Copyright (c) Feross Aboukhadijeh
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy of
6 +this software and associated documentation files (the "Software"), to deal in
7 +the Software without restriction, including without limitation the rights to
8 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 +the Software, and to permit persons to whom the Software is furnished to do so,
10 +subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in all
13 +copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1 +# zero-fill [![build](https://img.shields.io/travis/feross/zero-fill/master.svg)](https://travis-ci.org/feross/zero-fill) [![version](https://img.shields.io/npm/v/zero-fill.svg)](https://npmjs.org/package/zero-fill)
2 +
3 +### Zero-fill a number to the given size.
4 +
5 +![zero](https://raw.githubusercontent.com/feross/zero-fill/master/img.png)
6 +
7 +[![browser support](https://ci.testling.com/feross/zero-fill.png)](https://ci.testling.com/feross/zero-fill)
8 +
9 +## install
10 +
11 +```
12 +npm install zero-fill
13 +```
14 +
15 +## usage
16 +
17 +```js
18 +var zeroFill = require('zero-fill')
19 +
20 +zeroFill(4, 1) // '0001'
21 +zeroFill(10, 55) // '0000000055'
22 +zeroFill(1, 1) // '1'
23 +```
24 +
25 +Partial application:
26 +
27 +```js
28 +zeroFill(4)(1) // '0001'
29 +```
30 +
31 +Custom padding character:
32 +
33 +```js
34 +zeroFill(4, 55, ' ') // ' 55'
35 +zeroFill(4, 500, ' ') // ' 500'
36 +```
37 +
38 +## license
39 +
40 +MIT. Copyright (c) [Feross Aboukhadijeh](http://feross.org).
1 +/**
2 + * Given a number, return a zero-filled string.
3 + * From http://stackoverflow.com/questions/1267283/
4 + * @param {number} width
5 + * @param {number} number
6 + * @return {string}
7 + */
8 +module.exports = function zeroFill (width, number, pad) {
9 + if (number === undefined) {
10 + return function (number, pad) {
11 + return zeroFill(width, number, pad)
12 + }
13 + }
14 + if (pad === undefined) pad = '0'
15 + width -= number.toString().length
16 + if (width > 0) return new Array(width + (/\./.test(number) ? 2 : 1)).join(pad) + number
17 + return number + ''
18 +}
1 +{
2 + "_from": "zero-fill@^2.2.3",
3 + "_id": "zero-fill@2.2.3",
4 + "_inBundle": false,
5 + "_integrity": "sha1-o97wa6XjmuZEhQu0yirUEStIVek=",
6 + "_location": "/zero-fill",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "range",
10 + "registry": true,
11 + "raw": "zero-fill@^2.2.3",
12 + "name": "zero-fill",
13 + "escapedName": "zero-fill",
14 + "rawSpec": "^2.2.3",
15 + "saveSpec": null,
16 + "fetchSpec": "^2.2.3"
17 + },
18 + "_requiredBy": [
19 + "/hh-mm-ss"
20 + ],
21 + "_resolved": "https://registry.npmjs.org/zero-fill/-/zero-fill-2.2.3.tgz",
22 + "_shasum": "a3def06ba5e39ae644850bb4ca2ad4112b4855e9",
23 + "_spec": "zero-fill@^2.2.3",
24 + "_where": "C:\\Users\\user\\Desktop\\오소git\\오소플젝\\Youtube_MPL\\node_modules\\hh-mm-ss",
25 + "author": {
26 + "name": "Feross Aboukhadijeh",
27 + "email": "feross@feross.org",
28 + "url": "http://feross.org/"
29 + },
30 + "bugs": {
31 + "url": "https://github.com/feross/zero-fill/issues"
32 + },
33 + "bundleDependencies": false,
34 + "dependencies": {},
35 + "deprecated": false,
36 + "description": "Zero-fill a number to the given size.",
37 + "devDependencies": {
38 + "standard": "^6.0.4",
39 + "tape": "^4.4.0"
40 + },
41 + "homepage": "https://github.com/feross/zero-fill#readme",
42 + "keywords": [
43 + "zero",
44 + "zero fill",
45 + "fill",
46 + "zerofill",
47 + "pad",
48 + "0",
49 + "zero pad",
50 + "zeropad",
51 + "string",
52 + "number"
53 + ],
54 + "license": "MIT",
55 + "main": "index.js",
56 + "name": "zero-fill",
57 + "repository": {
58 + "type": "git",
59 + "url": "git://github.com/feross/zero-fill.git"
60 + },
61 + "scripts": {
62 + "test": "standard && tape test/*.js"
63 + },
64 + "version": "2.2.3"
65 +}
1 +var zeroFill = require('../')
2 +var test = require('tape')
3 +
4 +test('basic use', function (t) {
5 + t.equal(zeroFill(4, 1), '0001')
6 + t.equal(zeroFill(10, 1), '0000000001')
7 + t.equal(zeroFill(10, 55), '0000000055')
8 + t.equal(zeroFill(1, 1), '1')
9 + t.end()
10 +})
11 +
12 +test('width edge cases', function (t) {
13 + t.equal(zeroFill(1, 20), '20', 'do not trim string if width is too small')
14 + t.equal(zeroFill(0, 20), '20', 'zero width')
15 + t.equal(zeroFill(0, 1), '1', 'zero width')
16 + t.end()
17 +})
18 +
19 +test('partial application', function (t) {
20 + t.equal(zeroFill(4)(1), '0001')
21 + t.equal(zeroFill(10)(1), '0000000001')
22 + t.equal(zeroFill(10)(55), '0000000055')
23 + t.equal(zeroFill(1)(1), '1')
24 + t.equal(zeroFill(3)(1, ' '), ' 1') // custom pad character
25 + t.end()
26 +})
27 +
28 +test('custom pad character', function (t) {
29 + t.equal(zeroFill(4, 1, ' '), ' 1')
30 + t.equal(zeroFill(10, 1, 'x'), 'xxxxxxxxx1')
31 + t.equal(zeroFill(10, 55, 'x'), 'xxxxxxxx55')
32 + t.equal(zeroFill(1, 1, 'x'), '1')
33 + t.end()
34 +})
...@@ -2,6 +2,17 @@ ...@@ -2,6 +2,17 @@
2 "requires": true, 2 "requires": true,
3 "lockfileVersion": 1, 3 "lockfileVersion": 1,
4 "dependencies": { 4 "dependencies": {
5 + "@microlink/youtube-dl": {
6 + "version": "2.0.0",
7 + "resolved": "https://registry.npmjs.org/@microlink/youtube-dl/-/youtube-dl-2.0.0.tgz",
8 + "integrity": "sha512-B2DqRrDHFMu1MsBTq6ZAKR4BtKgvOK91Ci9EQiMVbSGC1/3UIPxpIYP4Py4kzcS94B++zVSMirhnCgX//5Qs4w==",
9 + "requires": {
10 + "hh-mm-ss": "~1.2.0",
11 + "mkdirp": "~0.5.1",
12 + "request": "~2.88.0",
13 + "streamify": "~0.2.9"
14 + }
15 + },
5 "ajv": { 16 "ajv": {
6 "version": "6.10.0", 17 "version": "6.10.0",
7 "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", 18 "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz",
...@@ -146,6 +157,22 @@ ...@@ -146,6 +157,22 @@
146 "har-schema": "^2.0.0" 157 "har-schema": "^2.0.0"
147 } 158 }
148 }, 159 },
160 + "hashish": {
161 + "version": "0.0.4",
162 + "resolved": "https://registry.npmjs.org/hashish/-/hashish-0.0.4.tgz",
163 + "integrity": "sha1-bWC8b/r3Ebav1g5CbQd5iAFOZVQ=",
164 + "requires": {
165 + "traverse": ">=0.2.4"
166 + }
167 + },
168 + "hh-mm-ss": {
169 + "version": "1.2.0",
170 + "resolved": "https://registry.npmjs.org/hh-mm-ss/-/hh-mm-ss-1.2.0.tgz",
171 + "integrity": "sha512-f4I9Hz1dLpX/3mrEs7yq30+FiuO3tt5NWAqAGeBTaoeoBfB8vhcQ3BphuDc5DjZb/K809agqrAaFlP0jhEU/8w==",
172 + "requires": {
173 + "zero-fill": "^2.2.3"
174 + }
175 + },
149 "http-signature": { 176 "http-signature": {
150 "version": "1.2.0", 177 "version": "1.2.0",
151 "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 178 "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
...@@ -210,6 +237,19 @@ ...@@ -210,6 +237,19 @@
210 "mime-db": "1.40.0" 237 "mime-db": "1.40.0"
211 } 238 }
212 }, 239 },
240 + "minimist": {
241 + "version": "0.0.8",
242 + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
243 + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
244 + },
245 + "mkdirp": {
246 + "version": "0.5.1",
247 + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
248 + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
249 + "requires": {
250 + "minimist": "0.0.8"
251 + }
252 + },
213 "oauth-sign": { 253 "oauth-sign": {
214 "version": "0.9.0", 254 "version": "0.9.0",
215 "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 255 "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
...@@ -288,6 +328,14 @@ ...@@ -288,6 +328,14 @@
288 "tweetnacl": "~0.14.0" 328 "tweetnacl": "~0.14.0"
289 } 329 }
290 }, 330 },
331 + "streamify": {
332 + "version": "0.2.9",
333 + "resolved": "https://registry.npmjs.org/streamify/-/streamify-0.2.9.tgz",
334 + "integrity": "sha512-8pUxeLEef9UO1FxtTt5iikAiyzGI4SZRnGuJ3sz8axZ5Xk+/7ezEV5kuJQsMEFxw7AKYw3xp0Ow+20mmSaJbQQ==",
335 + "requires": {
336 + "hashish": "~0.0.4"
337 + }
338 + },
291 "tough-cookie": { 339 "tough-cookie": {
292 "version": "2.4.3", 340 "version": "2.4.3",
293 "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", 341 "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
...@@ -304,6 +352,11 @@ ...@@ -304,6 +352,11 @@
304 } 352 }
305 } 353 }
306 }, 354 },
355 + "traverse": {
356 + "version": "0.6.6",
357 + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz",
358 + "integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc="
359 + },
307 "tunnel-agent": { 360 "tunnel-agent": {
308 "version": "0.6.0", 361 "version": "0.6.0",
309 "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 362 "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
...@@ -339,6 +392,22 @@ ...@@ -339,6 +392,22 @@
339 "core-util-is": "1.0.2", 392 "core-util-is": "1.0.2",
340 "extsprintf": "^1.2.0" 393 "extsprintf": "^1.2.0"
341 } 394 }
395 + },
396 + "youtube-dl": {
397 + "version": "1.13.1",
398 + "resolved": "https://registry.npmjs.org/youtube-dl/-/youtube-dl-1.13.1.tgz",
399 + "integrity": "sha512-89mUKwOavaojNKQlyzW+A7Dph5G/oPYs6T/PTMcvgdRQ5E2+uDQgYPxWHQDMBhHOkxQaxvxQTiTPKQLdg0OI4w==",
400 + "requires": {
401 + "hh-mm-ss": "~1.2.0",
402 + "mkdirp": "~0.5.1",
403 + "request": "~2.88.0",
404 + "streamify": "~0.2.9"
405 + }
406 + },
407 + "zero-fill": {
408 + "version": "2.2.3",
409 + "resolved": "https://registry.npmjs.org/zero-fill/-/zero-fill-2.2.3.tgz",
410 + "integrity": "sha1-o97wa6XjmuZEhQu0yirUEStIVek="
342 } 411 }
343 } 412 }
344 } 413 }
......