조인천

ver3

Showing 121 changed files with 5022 additions and 3 deletions
var request = require('request');
var optionParams = {
q:"kakao",
q:"저라뎃",
part:"snippet",
key:"AIzaSyCgGa6aM7taXs4bajtYukbc_EQAKTLVTNc",
maxResult2:5
type:"video",
maxResult2:5,
regionCode:"KR",
videoDuration:"short"
};
optionParams.q = encodeURI(optionParams.q);
var url = "https://www.googleapis.com/youtube/v3/search?";
for (var option in optionParams)
{
......@@ -14,6 +19,33 @@ for (var option in optionParams)
url = url.substr(0,url.length-1);
var VideoIds = new Array();
var idx = 0;
request(url, function(err,res,body){
console.log(body)
//console.log(body)
var data = JSON.parse(body).items;
for(var content in data)
{
VideoIds[idx]=(data[content].id.videoId);
idx++;
}
console.log(VideoIds.length);
console.log(VideoIds[0]);
console.log(typeof(VideoIds[1]));
//다운로드 부분
var fs = require('fs');
var youtubedl = require('youtube-dl');
var video = youtubedl('http://www.youtube.com/watch?v='.concat(VideoIds[1]));
video.on('info',function(info)
{
console.log('Download started');
console.log('filename : '+ info.filename);
console.log('size : '+info.size);
});
video.pipe(fs.createWriteStream('justlikethat.mp4'));
});
......
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.
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*) basedir=`cygpath -w "$basedir"`;;
esac
if [ -x "$basedir/node" ]; then
"$basedir/node" "$basedir/../mkdirp/bin/cmd.js" "$@"
ret=$?
else
node "$basedir/../mkdirp/bin/cmd.js" "$@"
ret=$?
fi
exit $ret
@IF EXIST "%~dp0\node.exe" (
"%~dp0\node.exe" "%~dp0\..\mkdirp\bin\cmd.js" %*
) ELSE (
@SETLOCAL
@SET PATHEXT=%PATHEXT:;.JS;=;%
node "%~dp0\..\mkdirp\bin\cmd.js" %*
)
\ No newline at end of file
This diff is collapsed. Click to expand it.
Copyright (C) 2011 by Roly Fentanes
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# youtube-dl
[![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)
Download videos from youtube in node.js using [youtube-dl](http://rg3.github.com/youtube-dl/).
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).
## Installation
With [npm](https://www.npmjs.com/) do:
``` sh
npm install @microlink/youtube-dl
```
## Usage
### Downloading videos
``` js
var fs = require('fs');
var youtubedl = require('youtube-dl');
var video = youtubedl('http://www.youtube.com/watch?v=90AiXO1pAiA',
// Optional arguments passed to youtube-dl.
['--format=18'],
// Additional options can be given for calling `child_process.execFile()`.
{ cwd: __dirname });
// Will be called when the download starts.
video.on('info', function(info) {
console.log('Download started');
console.log('filename: ' + info._filename);
console.log('size: ' + info.size);
});
video.pipe(fs.createWriteStream('myvideo.mp4'));
```
It will produce an output that looks like the following when ran.
```bash
Got video info
saving to T-ara - Number Nine - MV - 티아라-Seku9G1kT0c.mp4
100.00%
```
### Resuming partially downloaded videos
``` js
var youtubedl = require('./');
var fs = require('fs');
var output = 'myvideo.mp4';
var downloaded = 0;
if (fs.existsSync(output)) {
downloaded = fs.statSync(output).size;
}
var video = youtubedl('https://www.youtube.com/watch?v=179MiZSibco',
// Optional arguments passed to youtube-dl.
['--format=18'],
// start will be sent as a range header
{ start: downloaded, cwd: __dirname });
// Will be called when the download starts.
video.on('info', function(info) {
console.log('Download started');
console.log('filename: ' + info._filename);
// info.size will be the amount to download, add
var total = info.size + downloaded;
console.log('size: ' + total);
if (downloaded > 0) {
// size will be the amount already downloaded
console.log('resuming from: ' + downloaded);
// display the remaining bytes to download
console.log('remaining bytes: ' + info.size);
}
});
video.pipe(fs.createWriteStream('myvideo.mp4', { flags: 'a' }));
// Will be called if download was already completed and there is nothing more to download.
video.on('complete', function complete(info) {
'use strict';
console.log('filename: ' + info._filename + ' already downloaded.');
});
video.on('end', function() {
console.log('finished downloading!');
});
```
It will produce an output that looks like the following when ran.
**Output:**
``` sh
[~/nodejs/node-youtube-dl/example]$ node resume.js
Download started
filename: 1 1 1-179MiZSibco.mp4
size: 5109213
^C
```
``` sh
[~/nodejs/node-youtube-dl/example]$ node resume.js
Download started
filename: 1 1 1-179MiZSibco.mp4
size: 5109213
resuming from: 917504
remaining bytes: 4191709
finished downloading
```
### Getting video information
``` js
var youtubedl = require('youtube-dl');
var url = 'http://www.youtube.com/watch?v=WKsjaOqDXgg';
// Optional arguments passed to youtube-dl.
var options = ['--username=user', '--password=hunter2'];
youtubedl.getInfo(url, options, function(err, info) {
if (err) throw err;
console.log('id:', info.id);
console.log('title:', info.title);
console.log('url:', info.url);
console.log('thumbnail:', info.thumbnail);
console.log('description:', info.description);
console.log('filename:', info._filename);
console.log('format id:', info.format_id);
});
```
Running that will produce something like
``` sh
id: WKsjaOqDXgg
title: Ace Rimmer to the Rescue
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
thumbnail: https://i1.ytimg.com/vi/WKsjaOqDXgg/hqdefault.jpg
description: An old Red Dwarf eposide where Ace Rimmer saves the Princess Bonjella.
filename: Ace Rimmer to the Rescue-WKsjaOqDXgg.flv
format id: 34
```
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...)
``` js
var youtubedl = require('youtube-dl');
var url1 = 'http://www.youtube.com/watch?v=WKsjaOqDXgg';
var url2 = 'https://vimeo.com/6586873';
youtubedl.getInfo([url1, url2], function(err, info) {
if (err) throw err;
console.log('title for the url1:', info[0].title);
console.log('title for the url2:', info[1].title);
});
```
### Downloading subtitles
``` js
var youtubedl = require('youtube-dl');
var url = 'https://youtu.be/PizwcirYuGY';
var options = {
// Write automatic subtitle file (youtube only)
auto: false,
// Downloads all the available subtitles.
all: false,
// Subtitle format. YouTube generated subtitles
// are available ttml or vtt.
format: 'ttml',
// Languages of subtitles to download, separated by commas.
lang: 'en',
// The directory to save the downloaded files in.
cwd: __dirname,
};
youtubedl.getSubs(url, options, function(err, files) {
if (err) throw err;
console.log('subtitle files downloaded:', files);
});
```
### Downloading thumbnails
``` js
var youtubedl = require('youtube-dl');
var url = 'https://youtu.be/PizwcirYuGY';
var options = {
// Downloads available thumbnail.
all: false,
// The directory to save the downloaded files in.
cwd: __dirname,
};
youtubedl.getThumbs(url, options, function(err, files) {
if (err) throw err;
console.log('thumbnail file downloaded:', files);
});
```
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][].
### Downloading playlists
``` js
var path = require('path');
var fs = require('fs');
var ytdl = require('youtube-dl');
function playlist(url) {
'use strict';
var video = ytdl(url);
video.on('error', function error(err) {
console.log('error 2:', err);
});
var size = 0;
video.on('info', function(info) {
size = info.size;
var output = path.join(__dirname + '/', size + '.mp4');
video.pipe(fs.createWriteStream(output));
});
var pos = 0;
video.on('data', function data(chunk) {
pos += chunk.length;
// `size` should not be 0 here.
if (size) {
var percent = (pos / size * 100).toFixed(2);
process.stdout.cursorTo(0);
process.stdout.clearLine(1);
process.stdout.write(percent + '%');
}
});
video.on('next', playlist);
}
playlist('https://www.youtube.com/playlist?list=PLEFA9E9D96CB7F807');
```
### Getting the list of extractors
``` js
var youtubedl = require('youtube-dl');
youtubedl.getExtractors(true, function(err, list) {
console.log('Found ' + list.length + ' extractors');
for (var i = 0; i < list.length; i++) {
console.log(list[i]);
}
});
```
Will print something like
``` sh
Found 521 extractors
1up.com
220.ro
24video
3sat
```
### Call the `youtube-dl` binary directly
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.
If that, or none of the above support your use case, you can use `ytdl.exec()` to call `youtube-dl` however you like.
``` js
ytdl.exec(url, ['-x', '--audio-format', 'mp3'], {}, function(err, output) {
if (err) throw err;
console.log(output.join('\n'));
});
```
### Update
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.
``` js
var downloader = require('../lib/downloader');
downloader('path/to-binary', function error(err, done) {
'use strict';
if (err) { return console.log(err.stack); }
console.log(done);
});
```
### Tests
Tests are written with [vows](http://vowsjs.org/)
``` sh
npm test
```
## License
MIT
[youtube-dl]: http://rg3.github.com/youtube-dl/
[youtube-dl documentation]: http://rg3.github.com/youtube-dl/documentation.html
{"version":"2019.05.20","path":null,"exec":"youtube-dl.exe"}
\ No newline at end of file
'use strict'
const request = require('request')
const mkdirp = require('mkdirp')
const path = require('path')
const fs = require('fs')
const [, , ...flags] = process.argv
const isWin = flags.includes('--platform=windows') || require('./util').isWin
// First, look for the download link.
let dir, filePath
const defaultBin = path.join(__dirname, '..', 'bin')
const defaultPath = path.join(defaultBin, 'details')
const url = 'https://yt-dl.org/downloads/latest/youtube-dl'
function download (url, callback) {
let status
// download the correct version of the binary based on the platform
url = exec(url)
request.get(url, { followRedirect: false }, function (err, res) {
if (err) return callback(err)
if (res.statusCode !== 302) {
return callback(
new Error(
'Did not get redirect for the latest version link. Status: ' +
res.statusCode
)
)
}
const url = res.headers.location
const downloadFile = request.get(url)
const newVersion = /yt-dl\.org\/downloads\/(\d{4}\.\d\d\.\d\d(\.\d)?)\/youtube-dl/.exec(
url
)[1]
downloadFile.on('response', function response (res) {
if (res.statusCode !== 200) {
status = new Error('Response Error: ' + res.statusCode)
return
}
downloadFile.pipe(fs.createWriteStream(filePath, { mode: 493 }))
})
downloadFile.on('error', function error (err) {
callback(err)
})
downloadFile.on('end', function end () {
callback(status, newVersion)
})
})
}
const exec = path => (isWin ? path + '.exe' : path)
function createBase (binDir) {
dir = binDir || defaultBin
mkdirp.sync(dir)
if (binDir) mkdirp.sync(defaultBin)
filePath = path.join(dir, exec('youtube-dl'))
}
function downloader (binDir, callback) {
if (typeof binDir === 'function') {
callback = binDir
binDir = null
}
createBase(binDir)
download(url, function error (err, newVersion) {
if (err) return callback(err)
fs.writeFileSync(
defaultPath,
JSON.stringify({
version: newVersion,
path: binDir ? filePath : binDir,
exec: exec('youtube-dl')
}),
'utf8'
)
return callback(null, 'Downloaded youtube-dl ' + newVersion)
})
}
module.exports = downloader
// Arguments we dont want users to use with youtube-dl
// because they will break the module.
const badArgs = [
'-h',
'--help',
'-v',
'--version',
'-U',
'--update',
'-q',
'--quiet',
'-s',
'--simulate',
'-g',
'--get-url',
'-e',
'--get-title',
'--get-id',
'--get-thumbnail',
'--get-description',
'--get-duration',
'--get-filename',
'--get-format',
'-j',
'--dump-json',
'--newline',
'--no-progress',
'--console-title',
'-v',
'--verbose',
'--dump-intermediate-pages',
'--write-pages',
'--print-traffic'
]
/**
* Helps parse options used in youtube-dl command.
*
* @param {Array.<String>}
* @return {Array.<String>}
*/
exports.parseOpts = function (args) {
var pos
for (var i = 0, len = badArgs.length; i < len; i++) {
if ((pos = args.indexOf(badArgs[i])) !== -1) {
args.splice(pos, 1)
}
}
return args
}
/**
* Converts seconds to format hh:mm:ss
*
* @param {Number} seconds
* @return {String}
*/
exports.formatDuration = function (seconds) {
var parts = []
parts.push(seconds % 60)
var minutes = Math.floor(seconds / 60)
if (minutes > 0) {
parts.push(minutes % 60)
var hours = Math.floor(minutes / 60)
if (hours > 0) {
parts.push(hours)
}
}
return parts.reverse().join(':')
}
/**
* Checks wether str is a string or not
*
* @param {String} str
* @return {Boolean}
*/
exports.isString = str => typeof str === 'string'
/**
* Checks arr contains value
*
* @param {Array} arr
* @param {string|number} arr
* @return {Boolean}
*/
exports.has = (arr, value) => arr && arr.indexOf(value) > -1
exports.isYouTubeRegex = /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\//
exports.isWin =
process.platform === 'win32' || process.env.NODE_PLATFORM === 'windows'
'use strict'
const execFile = require('child_process').execFile
const streamify = require('streamify')
const request = require('request')
const hms = require('hh-mm-ss')
const path = require('path')
const http = require('http')
const url = require('url')
const fs = require('fs')
const {
isYouTubeRegex,
isWin,
formatDuration,
has,
isString
} = require('./util')
const detailsPath = path.join(__dirname, '..', 'bin/details')
const TEN_MEGABYTES = 1000 * 1000 * 10
const execFileOpts = { maxBuffer: TEN_MEGABYTES }
let ytdlBinary = (() => {
if (fs.existsSync(detailsPath)) {
const details = JSON.parse(fs.readFileSync(detailsPath))
return details.path
? details.path
: path.resolve(__dirname, '..', 'bin', details.exec)
}
if (!fs.existsSync(ytdlBinary)) {
console.error(
'ERROR: unable to locate youtube-dl details in ' +
path.dirname(ytdlBinary)
)
process.exit(1)
}
})()
function youtubeDl (args, options, cb) {
execFile(ytdlBinary, args, { ...execFileOpts, ...options }, function done (
err,
stdout,
stderr
) {
if (err) return cb(err)
return cb(null, stdout.trim().split(/\r?\n/))
})
}
/**
* Processes data
*
* @param {Object} data
* @param {Object} options
* @param {Object} stream
*/
function processData (data, options, stream) {
const item = !data.length ? data : data.shift()
// fix for pause/resume downloads
const headers = Object.assign(
{ Host: url.parse(item.url).hostname },
data.http_headers
)
if (options && options.start > 0 && options.end > 0) {
headers.Range = 'bytes=' + options.start + '-' + options.end
}
const req = request({ url: item.url, headers: headers, ecdhCurve: 'auto' })
req.on('response', function response (res) {
const size = parseInt(res.headers['content-length'], 10)
if (size) item.size = size
if (options && options.start > 0 && res.statusCode === 416) {
// the file that is being resumed is complete.
return stream.emit('complete', item)
}
if (res.statusCode !== 200 && res.statusCode !== 206) {
return stream.emit('error', new Error('status code ' + res.statusCode))
}
stream.emit('info', item)
stream.on('end', function end () {
if (data.length) stream.emit('next', data)
})
})
return stream.resolve(req)
}
/**
* Downloads a video.
*
* @param {String} videoUrl
* @param {!Array.<String>} args
* @param {!Object} options
*/
const ytdl = (module.exports = function (videoUrl, args, options) {
const stream = streamify({
superCtor: http.ClientResponse,
readable: true,
writable: false
})
if (!isString(videoUrl)) {
processData(videoUrl, options, stream)
return stream
}
ytdl.getInfo(videoUrl, args, options, function getInfo (err, data) {
return err ? stream.emit('error', err) : processData(data, options, stream)
})
return stream
})
/**
* Calls youtube-dl with some arguments and the `cb`
* gets called with the output.
*
* @param {String|Array.<String>}
* @param {Array.<String>} args
* @param {Array.<String>} args2
* @param {Object} options
* @param {Function(!Error, String)} cb
*/
function call (urls, args1, args2, options = {}, cb) {
let args = args1
if (args2) args = args.concat(args2)
// check if encoding is already set
if (isWin && !args.includes('--encoding')) {
args.push('--encoding')
args.push('utf8')
}
if (urls !== null) {
if (isString(urls)) urls = [urls]
for (let i = 0; i < urls.length; i++) {
const video = urls[i]
if (isYouTubeRegex.test(video)) {
// Get possible IDs.
const details = url.parse(video, true)
let id = details.query.v || ''
if (id) {
args.push('http://www.youtube.com/watch?v=' + id)
} else {
// Get possible IDs for youtu.be from urladdr.
id = details.pathname.slice(1).replace(/^v\//, '')
if (id) {
args.push(video)
args.unshift('-i')
}
}
} else {
if (i === 0) args.push('--')
args.push(video)
}
}
}
return youtubeDl(args, options, cb)
}
/**
* Calls youtube-dl with some arguments and the `cb`
* gets called with the output.
*
* @param {String} url
* @param {Array.<String>} args
* @param {Object} options
* @param {Function(!Error, String)} cb
*/
ytdl.exec = function exec (url, args, options, cb) {
return call(url, [], args, options, cb)
}
/**
* @param {Object} data
* @returns {Object}
*/
function parseInfo (data) {
// youtube-dl might return just an url as a string when using the "-g" or "--get-url" flag
if (isString(data) && data.startsWith('http')) {
data = JSON.stringify({ url: data })
}
const info = JSON.parse(data)
info._duration_raw = info.duration
info._duration_hms = info.duration
? hms.fromS(info.duration, 'hh:mm:ss')
: info.duration
info.duration = info.duration ? formatDuration(info.duration) : info.duration
return info
}
/**
* Set path from youtube-dl.
*
* @param {String} path
*/
ytdl.setYtdlBinary = function setYtdlBinary (path) {
ytdlBinary = path
}
/**
* Get path from youtube-dl.
*
* @param {String} path
*/
ytdl.getYtdlBinary = function getYtdlBinary () {
return ytdlBinary
}
/**
* Gets info from a video.
*
* @param {String} url
* @param {Array.<String>} args
* @param {Object} options
* @param {Function(!Error, Object)} cb
*/
ytdl.getInfo = function getInfo (url, args, options, cb) {
if (typeof options === 'function') {
cb = options
options = {}
} else if (typeof args === 'function') {
cb = args
options = {}
args = []
}
const defaultArgs = ['--dump-json']
if (
!args ||
(!has(args, '-f') &&
!has(args, '--format') &&
args.every(function (a) {
return a.indexOf('--format=') !== 0
}))
) {
defaultArgs.push('-f')
defaultArgs.push('best')
}
call(url, defaultArgs, args, options, function done (err, data) {
if (err) return cb(err)
let info
// 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
// This fixes this behaviour
if (has(args, '-g') || has(args, '--get-url')) {
if (Array.isArray(data) && data.length >= 2) data.splice(0, 1)
}
try {
info = data.map(parseInfo)
} catch (err) {
return cb(err)
}
return cb(null, info.length === 1 ? info[0] : info)
})
}
/**
* @param {String} url
* @param {Object} options
* {Boolean} auto
* {Boolean} all
* {String} lang
* {String} format
* {String} cwd
* @param {Function(!Error, Object)} cb
*/
ytdl.getSubs = function getSubs (url, options, cb) {
if (typeof options === 'function') {
cb = options
options = {}
}
const args = ['--skip-download']
args.push('--write' + (options.auto ? '-auto' : '') + '-sub')
if (options.all) args.push('--all-subs')
if (options.lang) args.push('--sub-lang=' + options.lang)
if (options.format) args.push('--sub-format=' + options.format)
if (!options.warrning) args.push('--no-warnings')
call(url, args, [], { cwd: options.cwd }, function (err, data) {
if (err) return cb(err)
const files = []
for (let i = 0, len = data.length; i < len; i++) {
const line = data[i]
if (line.indexOf('[info] Writing video subtitles to: ') === 0) {
files.push(line.slice(35))
}
}
return cb(null, files)
})
}
/**
* @param {String} url
* @param {Object} options
* {Boolean} all
* {String} cwd
* @param {Function(!Error, Object)} cb
*/
ytdl.getThumbs = function getThumbs (url, options, cb) {
if (typeof options === 'function') {
cb = options
options = {}
}
const args = ['--skip-download']
if (options.all) args.push('--write-all-thumbnails')
else args.push('--write-thumbnail')
if (!options.warrning) args.push('--no-warnings')
call(url, args, [], { cwd: options.cwd }, function (err, data) {
if (err) return cb(err)
const files = []
for (let i = 0, len = data.length; i < len; i++) {
const line = data[i]
const info = 'Writing thumbnail to: '
if (has(line, info)) {
files.push(line.slice(line.indexOf(info) + info.length))
}
}
return cb(null, files)
})
}
/**
* @param {!Boolean} descriptions
* @param {!Object} options
* @param {Function(!Error, Object)} cb
*/
ytdl.getExtractors = function getExtractors (descriptions, options, cb) {
if (typeof options === 'function') {
cb = options
options = {}
} else if (typeof descriptions === 'function') {
cb = descriptions
options = {}
descriptions = false
}
const args = descriptions
? ['--extractor-descriptions']
: ['--list-extractors']
return call(null, args, null, options, cb)
}
{
"_from": "@microlink/youtube-dl",
"_id": "@microlink/youtube-dl@2.0.0",
"_inBundle": false,
"_integrity": "sha512-B2DqRrDHFMu1MsBTq6ZAKR4BtKgvOK91Ci9EQiMVbSGC1/3UIPxpIYP4Py4kzcS94B++zVSMirhnCgX//5Qs4w==",
"_location": "/@microlink/youtube-dl",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "@microlink/youtube-dl",
"name": "@microlink/youtube-dl",
"escapedName": "@microlink%2fyoutube-dl",
"scope": "@microlink",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/@microlink/youtube-dl/-/youtube-dl-2.0.0.tgz",
"_shasum": "0120c67949185228afe4d771cfd80719b278cd73",
"_spec": "@microlink/youtube-dl",
"_where": "C:\\Users\\user\\Desktop\\오소git\\오소플젝\\Youtube_MPL",
"author": {
"name": "Roly Fentanes",
"url": "https://github.com/fent"
},
"bugs": {
"url": "https://github.com/przemyslawpluta/node-youtube-dl/issues"
},
"bundleDependencies": false,
"commitlint": {
"extends": [
"@commitlint/config-conventional"
]
},
"contributors": [
{
"name": "Roly Fentanes",
"email": "roly426@gmail.com"
},
{
"name": "przemyslawpluta",
"email": "przemekpluta@hotmail.com"
},
{
"name": "Kiko Beats",
"email": "josefrancisco.verdu@gmail.com"
},
{
"name": "Jay Salvat",
"email": "jay@jaysalvat.com"
},
{
"name": "Benjamin C",
"email": "benjamin@coriou.net"
},
{
"name": "Gregoire Guémas",
"email": "gregoire.guemas@navispeed.eu"
},
{
"name": "Jaime Marquínez Ferrándiz",
"email": "jaime.marquinez.ferrandiz@gmail.com"
},
{
"name": "Jay Baker",
"email": "logikal@gmail.com"
},
{
"name": "Jack Li",
"email": "jack.lee2980@gmail.com"
},
{
"name": "optikfluffel",
"email": "optik@fluffel.io"
},
{
"name": "Calvin",
"email": "calvin@sealtelecom.com.br"
},
{
"name": "Jeremy Louie",
"email": "jeremy@jeremylouie.com"
},
{
"name": "Sergey M․",
"email": "dstftw@gmail.com"
},
{
"name": "t3rr0r",
"email": "mail@t3rr0r.com"
},
{
"name": "EragonJ",
"email": "eragonj@eragonj.me"
},
{
"name": "tifroz",
"email": "hhardel@gmail.com"
},
{
"name": "walheresq",
"email": "walheresq@hotmail.com"
},
{
"name": "Alireza Mirian",
"email": "alireza.mirian@gmail.com"
},
{
"name": "▟ ▖▟ ▖",
"email": "dodo.the.last@gmail.com"
},
{
"name": "Davide Pastore",
"email": "pasdavide@gmail.com"
},
{
"name": "Farrin Reid",
"email": "blakmatrix@gmail.com"
},
{
"name": "Jason Penny",
"email": "jason@jooraccess.com"
},
{
"name": "Juan C. Olivares",
"email": "cristobal@cxsoftware.com"
},
{
"name": "Lopez Hugo",
"email": "hugo.lpz@gmail.com"
},
{
"name": "Meral",
"email": "meral.harbes@gmail.com"
},
{
"name": "Michael Nguyen",
"email": "tehtotalpwnage@gmail.com"
},
{
"name": "Nicolas Gotchac",
"email": "ngotchac@gmail.com"
},
{
"name": "Parikshit Hooda",
"email": "phooda804@live.com"
},
{
"name": "Pietro",
"email": "pietro.passarelli@gmail.com"
},
{
"name": "Sagi Nadir",
"email": "saginadir@gmail.com"
},
{
"name": "bartronicus",
"email": "matthewdavidbarton@gmail.com"
},
{
"name": "btmdave",
"email": "dave@bluetopmedia.com"
},
{
"name": "coderaiser",
"email": "mnemonic.enemy@gmail.com"
}
],
"dependencies": {
"hh-mm-ss": "~1.2.0",
"mkdirp": "~0.5.1",
"request": "~2.88.0",
"streamify": "~0.2.9"
},
"deprecated": false,
"description": "youtube-dl driver for node",
"devDependencies": {
"@commitlint/cli": "latest",
"@commitlint/config-conventional": "latest",
"finepack": "latest",
"git-authors-cli": "latest",
"husky": "latest",
"lint-staged": "latest",
"prettier-standard": "latest",
"standard": "latest",
"standard-markdown": "latest",
"standard-version": "latest",
"vows": "latest"
},
"engines": {
"node": ">= 8"
},
"files": [
"lib",
"scripts"
],
"homepage": "https://github.com/przemyslawpluta/node-youtube-dl#readme",
"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
"pre-commit": "lint-staged"
}
},
"keywords": [
"download",
"video",
"youtube"
],
"license": "MIT",
"lint-staged": {
"linters": {
"package.json": [
"finepack",
"git add"
],
"*.js": [
"prettier-standard",
"git add"
],
"*.md": [
"standard-markdown",
"git add"
]
}
},
"main": "./lib/youtube-dl.js",
"name": "@microlink/youtube-dl",
"repository": {
"type": "git",
"url": "git://github.com/przemyslawpluta/node-youtube-dl.git"
},
"scripts": {
"lint": "standard-markdown README.md && standard",
"postinstall": "node ./scripts/download.js",
"release": "bumped release",
"test": "vows ./test/*.js --spec",
"update": "node ./scripts/download.js"
},
"version": "2.0.0"
}
var downloader = require('../lib/downloader')
downloader(function error (err, done) {
if (err) return console.log(err.stack)
console.log(done)
})
Hashish
=======
Hashish is a node.js library for manipulating hash data structures.
It is distilled from the finest that ruby, perl, and haskell have to offer by
way of hash/map interfaces.
Hashish provides a chaining interface, where you can do:
var Hash = require('hashish');
Hash({ a : 1, b : 2, c : 3, d : 4 })
.map(function (x) { return x * 10 })
.filter(function (x) { return x < 30 })
.forEach(function (x, key) {
console.log(key + ' => ' + x);
})
;
Output:
a => 10
b => 20
Some functions and attributes in the chaining interface are terminal, like
`.items` or `.detect()`. They return values of their own instead of the chain
context.
Each function in the chainable interface is also attached to `Hash` in chainless
form:
var Hash = require('hashish');
var obj = { a : 1, b : 2, c : 3, d : 4 };
var mapped = Hash.map(obj, function (x) {
return x * 10
});
console.dir(mapped);
Output:
{ a: 10, b: 20, c: 30, d: 40 }
In either case, the 'this' context of the function calls is the same object that
the chained functions return, so you can make nested chains.
Methods
=======
forEach(cb)
-----------
For each key/value in the hash, calls `cb(value, key)`.
map(cb)
-------
For each key/value in the hash, calls `cb(value, key)`.
The return value of `cb` is the new value at `key` in the resulting hash.
filter(cb)
----------
For each key/value in the hash, calls `cb(value, key)`.
The resulting hash omits key/value pairs where `cb` returned a falsy value.
detect(cb)
----------
Returns the first value in the hash for which `cb(value, key)` is non-falsy.
Order of hashes is not well-defined so watch out for that.
reduce(cb)
----------
Returns the accumulated value of a left-fold over the key/value pairs.
some(cb)
--------
Returns a boolean: whether or not `cb(value, key)` ever returned a non-falsy
value.
update(obj1, [obj2, obj3, ...])
-----------
Mutate the context hash, merging the key/value pairs from the passed objects
and overwriting keys from the context hash if the current `obj` has keys of
the same name. Falsy arguments are silently ignored.
updateAll([ obj1, obj2, ... ])
------------------------------
Like multi-argument `update()` but operate on an array directly.
merge(obj1, [obj2, obj3, ...])
----------
Merge the key/value pairs from the passed objects into the resultant hash
without modifying the context hash. Falsy arguments are silently ignored.
mergeAll([ obj1, obj2, ... ])
------------------------------
Like multi-argument `merge()` but operate on an array directly.
has(key)
--------
Return whether the hash has a key, `key`.
valuesAt(keys)
--------------
Return an Array with the values at the keys from `keys`.
tap(cb)
-------
Call `cb` with the present raw hash.
This function is chainable.
extract(keys)
-------------
Filter by including only those keys in `keys` in the resulting hash.
exclude(keys)
-------------
Filter by excluding those keys in `keys` in the resulting hash.
Attributes
==========
These are attributes in the chaining interface and functions in the `Hash.xxx`
interface.
keys
----
Return all the enumerable attribute keys in the hash.
values
------
Return all the enumerable attribute values in the hash.
compact
-------
Filter out values which are `=== undefined`.
clone
-----
Make a deep copy of the hash.
copy
----
Make a shallow copy of the hash.
length
------
Return the number of key/value pairs in the hash.
Note: use `Hash.size()` for non-chain mode.
size
----
Alias for `length` since `Hash.length` is masked by `Function.prototype`.
See Also
========
See also [creationix's pattern/hash](http://github.com/creationix/pattern),
which does a similar thing except with hash inputs and array outputs.
Installation
============
To install with [npm](http://github.com/isaacs/npm):
npm install hashish
To run the tests with [expresso](http://github.com/visionmedia/expresso):
expresso
var Hash = require('hashish');
Hash({ a : 1, b : 2, c : 3, d : 4 })
.map(function (x) { return x * 10 })
.filter(function (x) { return x < 30 })
.forEach(function (x, key) {
console.log(key + ' => ' + x);
})
;
var Hash = require('hashish');
var obj = { a : 1, b : 2, c : 3, d : 4 };
var mapped = Hash.map(obj, function (x) {
return x * 10
});
console.dir(mapped);
module.exports = Hash;
var Traverse = require('traverse');
function Hash (hash, xs) {
if (Array.isArray(hash) && Array.isArray(xs)) {
var to = Math.min(hash.length, xs.length);
var acc = {};
for (var i = 0; i < to; i++) {
acc[hash[i]] = xs[i];
}
return Hash(acc);
}
if (hash === undefined) return Hash({});
var self = {
map : function (f) {
var acc = { __proto__ : hash.__proto__ };
Object.keys(hash).forEach(function (key) {
acc[key] = f.call(self, hash[key], key);
});
return Hash(acc);
},
forEach : function (f) {
Object.keys(hash).forEach(function (key) {
f.call(self, hash[key], key);
});
return self;
},
filter : function (f) {
var acc = { __proto__ : hash.__proto__ };
Object.keys(hash).forEach(function (key) {
if (f.call(self, hash[key], key)) {
acc[key] = hash[key];
}
});
return Hash(acc);
},
detect : function (f) {
for (var key in hash) {
if (f.call(self, hash[key], key)) {
return hash[key];
}
}
return undefined;
},
reduce : function (f, acc) {
var keys = Object.keys(hash);
if (acc === undefined) acc = keys.shift();
keys.forEach(function (key) {
acc = f.call(self, acc, hash[key], key);
});
return acc;
},
some : function (f) {
for (var key in hash) {
if (f.call(self, hash[key], key)) return true;
}
return false;
},
update : function (obj) {
if (arguments.length > 1) {
self.updateAll([].slice.call(arguments));
}
else {
Object.keys(obj).forEach(function (key) {
hash[key] = obj[key];
});
}
return self;
},
updateAll : function (xs) {
xs.filter(Boolean).forEach(function (x) {
self.update(x);
});
return self;
},
merge : function (obj) {
if (arguments.length > 1) {
return self.copy.updateAll([].slice.call(arguments));
}
else {
return self.copy.update(obj);
}
},
mergeAll : function (xs) {
return self.copy.updateAll(xs);
},
has : function (key) { // only operates on enumerables
return Array.isArray(key)
? key.every(function (k) { return self.has(k) })
: self.keys.indexOf(key.toString()) >= 0;
},
valuesAt : function (keys) {
return Array.isArray(keys)
? keys.map(function (key) { return hash[key] })
: hash[keys]
;
},
tap : function (f) {
f.call(self, hash);
return self;
},
extract : function (keys) {
var acc = {};
keys.forEach(function (key) {
acc[key] = hash[key];
});
return Hash(acc);
},
exclude : function (keys) {
return self.filter(function (_, key) {
return keys.indexOf(key) < 0
});
},
end : hash,
items : hash
};
var props = {
keys : function () { return Object.keys(hash) },
values : function () {
return Object.keys(hash).map(function (key) { return hash[key] });
},
compact : function () {
return self.filter(function (x) { return x !== undefined });
},
clone : function () { return Hash(Hash.clone(hash)) },
copy : function () { return Hash(Hash.copy(hash)) },
length : function () { return Object.keys(hash).length },
size : function () { return self.length }
};
if (Object.defineProperty) {
// es5-shim has an Object.defineProperty but it throws for getters
try {
for (var key in props) {
Object.defineProperty(self, key, { get : props[key] });
}
}
catch (err) {
for (var key in props) {
if (key !== 'clone' && key !== 'copy' && key !== 'compact') {
// ^ those keys use Hash() so can't call them without
// a stack overflow
self[key] = props[key]();
}
}
}
}
else if (self.__defineGetter__) {
for (var key in props) {
self.__defineGetter__(key, props[key]);
}
}
else {
// non-lazy version for browsers that suck >_<
for (var key in props) {
self[key] = props[key]();
}
}
return self;
};
// deep copy
Hash.clone = function (ref) {
return Traverse.clone(ref);
};
// shallow copy
Hash.copy = function (ref) {
var hash = { __proto__ : ref.__proto__ };
Object.keys(ref).forEach(function (key) {
hash[key] = ref[key];
});
return hash;
};
Hash.map = function (ref, f) {
return Hash(ref).map(f).items;
};
Hash.forEach = function (ref, f) {
Hash(ref).forEach(f);
};
Hash.filter = function (ref, f) {
return Hash(ref).filter(f).items;
};
Hash.detect = function (ref, f) {
return Hash(ref).detect(f);
};
Hash.reduce = function (ref, f, acc) {
return Hash(ref).reduce(f, acc);
};
Hash.some = function (ref, f) {
return Hash(ref).some(f);
};
Hash.update = function (a /*, b, c, ... */) {
var args = Array.prototype.slice.call(arguments, 1);
var hash = Hash(a);
return hash.update.apply(hash, args).items;
};
Hash.merge = function (a /*, b, c, ... */) {
var args = Array.prototype.slice.call(arguments, 1);
var hash = Hash(a);
return hash.merge.apply(hash, args).items;
};
Hash.has = function (ref, key) {
return Hash(ref).has(key);
};
Hash.valuesAt = function (ref, keys) {
return Hash(ref).valuesAt(keys);
};
Hash.tap = function (ref, f) {
return Hash(ref).tap(f).items;
};
Hash.extract = function (ref, keys) {
return Hash(ref).extract(keys).items;
};
Hash.exclude = function (ref, keys) {
return Hash(ref).exclude(keys).items;
};
Hash.concat = function (xs) {
var hash = Hash({});
xs.forEach(function (x) { hash.update(x) });
return hash.items;
};
Hash.zip = function (xs, ys) {
return Hash(xs, ys).items;
};
// .length is already defined for function prototypes
Hash.size = function (ref) {
return Hash(ref).size;
};
Hash.compact = function (ref) {
return Hash(ref).compact.items;
};
{
"_from": "hashish@~0.0.4",
"_id": "hashish@0.0.4",
"_inBundle": false,
"_integrity": "sha1-bWC8b/r3Ebav1g5CbQd5iAFOZVQ=",
"_location": "/hashish",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "hashish@~0.0.4",
"name": "hashish",
"escapedName": "hashish",
"rawSpec": "~0.0.4",
"saveSpec": null,
"fetchSpec": "~0.0.4"
},
"_requiredBy": [
"/streamify"
],
"_resolved": "https://registry.npmjs.org/hashish/-/hashish-0.0.4.tgz",
"_shasum": "6d60bc6ffaf711b6afd60e426d077988014e6554",
"_spec": "hashish@~0.0.4",
"_where": "C:\\Users\\user\\Desktop\\오소git\\오소플젝\\Youtube_MPL\\node_modules\\streamify",
"author": {
"name": "James Halliday",
"email": "mail@substack.net",
"url": "http://substack.net"
},
"bugs": {
"url": "https://github.com/substack/node-hashish/issues"
},
"bundleDependencies": false,
"dependencies": {
"traverse": ">=0.2.4"
},
"deprecated": false,
"description": "Hash data structure manipulation functions",
"devDependencies": {
"expresso": ">=0.6.0"
},
"engine": [
"node >=0.2.0"
],
"engines": {
"node": "*"
},
"homepage": "https://github.com/substack/node-hashish#readme",
"keywords": [
"hash",
"object",
"convenience",
"manipulation",
"data structure"
],
"license": "MIT/X11",
"main": "./index.js",
"name": "hashish",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/substack/node-hashish.git"
},
"scripts": {
"test": "expresso"
},
"version": "0.0.4"
}
var Hash = require('hashish');
var assert = require('assert');
exports.map = function () {
var ref = { a : 1, b : 2 };
var items = Hash(ref).map(function (v) { return v + 1 }).items;
var hash = Hash.map(ref, function (v) { return v + 1 });
assert.deepEqual(ref, { a : 1, b : 2 });
assert.deepEqual(items, { a : 2, b : 3 });
assert.deepEqual(hash, { a : 2, b : 3 });
};
exports['cloned map'] = function () {
var ref = { foo : [1,2], bar : [4,5] };
var hash = Hash(ref).clone.map(
function (v) { v.unshift(v[0] - 1); return v }
).items;
assert.deepEqual(ref.foo, [1,2]);
assert.deepEqual(ref.bar, [4,5]);
assert.deepEqual(hash.foo, [0,1,2]);
assert.deepEqual(hash.bar, [3,4,5]);
};
exports.forEach = function () {
var ref = { a : 5, b : 2, c : 7, 1337 : 'leet' };
var xs = [];
Hash(ref).forEach(function (x, i) {
xs.push([ i, x ]);
});
assert.eql(
xs.map(function (x) { return x[0] }).sort(),
[ '1337', 'a', 'b', 'c' ]
);
assert.eql(
xs.map(function (x) { return x[1] }).sort(),
[ 2, 5, 7, 'leet' ]
);
var ys = [];
Hash.forEach(ref, function (x, i) {
ys.push([ i, x ]);
});
assert.eql(xs.sort(), ys.sort());
};
exports.filter_items = function () {
var ref = { a : 5, b : 2, c : 7, 1337 : 'leet' };
var items = Hash(ref).filter(function (v, k) {
return v > 5 || k > 5
}).items;
var hash = Hash.filter(ref, function (v, k) { return v > 5 || k > 5 });
assert.deepEqual(items, { 1337 : 'leet', c : 7 });
assert.deepEqual(hash, { 1337 : 'leet', c : 7 });
assert.deepEqual(ref, { a : 5, b : 2, c : 7, 1337 : 'leet' });
assert.equal(Hash(ref).length, 4);
};
exports.detect = function () {
var h = { a : 5, b : 6, c : 7, d : 8 };
var hh = Hash(h);
var gt6hh = hh.detect(function (x) { return x > 6 });
assert.ok(gt6hh == 7 || gt6hh == 8);
var gt6h = Hash.detect(h, function (x) { return x > 6 });
assert.ok(gt6h == 7 || gt6h == 8);
assert.equal(hh.detect(function (x) { return x > 100 }), undefined);
};
exports.reduce = function () {
var ref = { foo : [1,2], bar : [4,5] };
var sum1 = Hash(ref).reduce(function (acc, v) {
return acc + v.length
}, 0);
assert.equal(sum1, 4);
var sum2 = Hash.reduce(ref, function (acc, v) {
return acc + v.length
}, 0);
assert.equal(sum2, 4);
};
exports.some = function () {
var h = { a : 5, b : 6, c : 7, d : 8 };
var hh = Hash(h);
assert.ok(Hash.some(h, function (x) { return x > 7 }));
assert.ok(Hash.some(h, function (x) { return x < 6 }));
assert.ok(!Hash.some(h, function (x) { return x > 10 }));
assert.ok(!Hash.some(h, function (x) { return x < 0 }));
assert.ok(hh.some(function (x) { return x > 7 }));
assert.ok(hh.some(function (x) { return x < 6 }));
assert.ok(!hh.some(function (x) { return x > 10 }));
assert.ok(!hh.some(function (x) { return x < 0 }));
};
exports.update = function () {
var ref = { a : 1, b : 2 };
var items = Hash(ref).clone.update({ c : 3, a : 0 }).items;
assert.deepEqual(ref, { a : 1, b : 2 });
assert.deepEqual(items, { a : 0, b : 2, c : 3 });
var hash = Hash.update(ref, { c : 3, a : 0 });
assert.deepEqual(ref, hash);
assert.deepEqual(hash, { a : 0, b : 2, c : 3 });
var ref2 = {a: 1};
var hash2 = Hash.update(ref2, { b: 2, c: 3 }, undefined, { d: 4 });
assert.deepEqual(ref2, { a: 1, b: 2, c: 3, d: 4 });
};
exports.merge = function () {
var ref = { a : 1, b : 2 };
var items = Hash(ref).merge({ b : 3, c : 3.14 }).items;
var hash = Hash.merge(ref, { b : 3, c : 3.14 });
assert.deepEqual(ref, { a : 1, b : 2 });
assert.deepEqual(items, { a : 1, b : 3, c : 3.14 });
assert.deepEqual(hash, { a : 1, b : 3, c : 3.14 });
var ref2 = { a : 1 };
var hash2 = Hash.merge(ref, { b: 2, c: 3 }, undefined, { d: 4 });
assert.deepEqual(hash2, { a: 1, b: 2, c: 3, d: 4 });
};
exports.has = function () {
var h = { a : 4, b : 5 };
var hh = Hash(h);
assert.ok(hh.has('a'));
assert.equal(hh.has('c'), false);
assert.ok(hh.has(['a','b']));
assert.equal(hh.has(['a','b','c']), false);
assert.ok(Hash.has(h, 'a'));
assert.equal(Hash.has(h, 'c'), false);
assert.ok(Hash.has(h, ['a','b']));
assert.equal(Hash.has(h, ['a','b','c']), false);
};
exports.valuesAt = function () {
var h = { a : 4, b : 5, c : 6 };
assert.equal(Hash(h).valuesAt('a'), 4);
assert.equal(Hash(h).valuesAt(['a'])[0], 4);
assert.deepEqual(Hash(h).valuesAt(['a','b']), [4,5]);
assert.equal(Hash.valuesAt(h, 'a'), 4);
assert.deepEqual(Hash.valuesAt(h, ['a']), [4]);
assert.deepEqual(Hash.valuesAt(h, ['a','b']), [4,5]);
};
exports.tap = function () {
var h = { a : 4, b : 5, c : 6 };
var hh = Hash(h);
hh.tap(function (x) {
assert.ok(this === hh)
assert.eql(x, h);
});
Hash.tap(h, function (x) {
assert.eql(
Object.keys(this).sort(),
Object.keys(hh).sort()
);
assert.eql(x, h);
});
};
exports.extract = function () {
var hash = Hash({ a : 1, b : 2, c : 3 }).clone;
var extracted = hash.extract(['a','b']);
assert.equal(extracted.length, 2);
assert.deepEqual(extracted.items, { a : 1, b : 2 });
};
exports.exclude = function () {
var hash = Hash({ a : 1, b : 2, c : 3 }).clone;
var extracted = hash.exclude(['a','b']);
assert.equal(extracted.length, 1);
assert.deepEqual(extracted.items, { c : 3 });
};
exports.concat = function () {
var ref1 = { a : 1, b : 2 };
var ref2 = { foo : 100, bar : 200 };
var ref3 = { b : 3, c : 4, bar : 300 };
assert.deepEqual(
Hash.concat([ ref1, ref2 ]),
{ a : 1, b : 2, foo : 100, bar : 200 }
);
assert.deepEqual(
Hash.concat([ ref1, ref2, ref3 ]),
{ a : 1, b : 3, c : 4, foo : 100, bar : 300 }
);
};
exports.zip = function () {
var xs = ['a','b','c'];
var ys = [1,2,3,4];
var h = Hash(xs,ys);
assert.equal(h.length, 3);
assert.deepEqual(h.items, { a : 1, b : 2, c : 3 });
var zipped = Hash.zip(xs,ys);
assert.deepEqual(zipped, { a : 1, b : 2, c : 3 });
};
exports.length = function () {
assert.equal(Hash({ a : 1, b : [2,3], c : 4 }).length, 3);
assert.equal(Hash({ a : 1, b : [2,3], c : 4 }).size, 3);
assert.equal(Hash.size({ a : 1, b : [2,3], c : 4 }), 3);
};
exports.compact = function () {
var hash = {
a : 1,
b : undefined,
c : false,
d : 4,
e : [ undefined, 4 ],
f : null
};
var compacted = Hash(hash).compact;
assert.deepEqual(
{
a : 1,
b : undefined,
c : false,
d : 4,
e : [ undefined, 4 ],
f : null
},
hash, 'compact modified the hash'
);
assert.deepEqual(
compacted.items,
{
a : 1,
c : false,
d : 4,
e : [ undefined, 4 ],
f : null
}
);
var h = Hash.compact(hash);
assert.deepEqual(h, compacted.items);
};
var Hash = require('hashish');
var assert = require('assert');
var vm = require('vm');
var fs = require('fs');
var src = fs.readFileSync(__dirname + '/../index.js', 'utf8');
exports.defineGetter = function () {
var context = {
module : { exports : {} },
Object : {
keys : Object.keys,
defineProperty : undefined,
},
require : require,
};
context.exports = context.module.exports;
vm.runInNewContext('(function () {' + src + '})()', context);
var Hash_ = context.module.exports;
var times = 0;
Hash_.__proto__.__proto__.__defineGetter__ = function () {
times ++;
return Object.__defineGetter__.apply(this, arguments);
};
assert.equal(vm.runInNewContext('Object.defineProperty', context), null);
assert.deepEqual(
Hash_({ a : 1, b : 2, c : 3 }).values,
[ 1, 2, 3 ]
);
assert.ok(times > 5);
};
exports.defineProperty = function () {
var times = 0;
var context = {
module : { exports : {} },
Object : {
keys : Object.keys,
defineProperty : function (prop) {
times ++;
if (prop.get) throw new TypeError('engine does not support')
assert.fail('should have asserted by now');
},
},
require : require
};
context.exports = context.module.exports;
vm.runInNewContext('(function () {' + src + '})()', context);
var Hash_ = context.module.exports;
Hash_.__proto__.__proto__.__defineGetter__ = function () {
assert.fail('getter called when a perfectly good'
+ ' defineProperty was available'
);
};
assert.deepEqual(
Hash_({ a : 1, b : 2, c : 3 }).values,
[ 1, 2, 3 ]
);
assert.equal(times, 1);
};
language: node_js
node_js:
- 'node'
The MIT License (MIT)
Copyright (c) Adam Gotlib
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# hh-mm-ss: time formatting utility
[![Build Status](https://travis-ci.org/Goldob/hh-mm-ss.svg?branch=master)](https://travis-ci.org/Goldob/hh-mm-ss)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
:watch: Convert seconds or miliseconds to `hh:mm:ss` format and vice versa.
```js
var TimeFormat = require('hh-mm-ss')
TimeFormat.toS('137:00:00') // 493200
TimeFormat.toS('02:00') // 120
TimeFormat.toS('02:00', 'hh:mm') // 7200
TimeFormat.fromS(194) // '03:14'
TimeFormat.fromS(150, 'hh:mm:ss') // '00:02:30'
TimeFormat.fromS(8100, 'hh:mm') // '02:15'
TimeFormat.fromMs(12345) // '00:12.345'
```
## Usage
### `toMs(time, format)`
Convert given `hh:mm:ss` formatted string to miliseconds
#### Parameters
- `time` String representation
- `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
### `toS(time, format)`
Convert given `hh:mm:ss` formatted string to seconds
#### Parameters
- `time` String representation
- `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
### `fromMs(ms, format)`
Generate formatted string from time in miliseconds
#### Parameters
- `ms` Time in miliseconds
- `format` _(optional)_ Default output format. If not specified, `mm:ss` is implied. See section below for supported format list.
### `fromS(s, format)`
Generate formatted string from time in seconds
#### Parameters
- `s` Time in seconds
- `format` _(optional)_ Default output format. If not specified, `mm:ss` is implied. See section below for supported format list
### Supported time formats
The following formats are supported: `mm:ss`, `hh:mm`, `hh:mm:ss`, `mm:ss.sss`, `hh:mm:ss.sss`.
- `hh` - hours
- `mm` - minutes
- `ss` - second
- `sss` - miliseconds
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.
## Install
`npm install hh-mm-ss --save`
## License
MIT
'use strict'
module.exports = {
fromMs,
fromS,
toMs,
toS
}
const zeroFill = require('zero-fill')
// Time units with their corresponding values in miliseconds
const HOUR = 3600000
const MINUTE = 60000
const SECOND = 1000
const TIME_FORMAT_ERRMSG = 'Time format error'
// =============================================================================
// Export functions
// =============================================================================
function fromMs (ms, format = 'mm:ss') {
if (typeof ms !== 'number' || Number.isNaN(ms)) {
throw new Error('NaN error')
}
let absMs = Math.abs(ms)
let negative = (ms < 0)
let hours = Math.floor(absMs / HOUR)
let minutes = Math.floor(absMs % HOUR / MINUTE)
let seconds = Math.floor(absMs % MINUTE / SECOND)
let miliseconds = Math.floor(absMs % SECOND)
return formatTime({
negative, hours, minutes, seconds, miliseconds
}, format)
}
function fromS (s, format = 'mm:ss') {
if (typeof s !== 'number' || Number.isNaN(s)) {
throw new Error('NaN error')
}
let ms = s * SECOND
return fromMs(ms, format)
}
function toMs (time, format = 'mm:ss') {
let re
if (['mm:ss', 'mm:ss.sss', 'hh:mm:ss', 'hh:mm:ss.sss'].includes(format)) {
re = /^(-)?(?:(\d\d+):)?(\d\d):(\d\d)(\.\d+)?$/
} else if (format === 'hh:mm') {
re = /^(-)?(\d\d):(\d\d)(?::(\d\d)(?:(\.\d+))?)?$/
} else {
throw new Error(TIME_FORMAT_ERRMSG)
}
let result = re.exec(time)
if (!result) throw new Error()
let negative = result[1] === '-'
let hours = result[2] | 0
let minutes = result[3] | 0
let seconds = result[4] | 0
let miliseconds = Math.floor(1000 * result[5] | 0)
if (minutes > 60 || seconds > 60) {
throw new Error()
}
return (negative ? -1 : 1) * (
hours * HOUR + minutes * MINUTE + seconds * SECOND + miliseconds
)
}
function toS (time, format = 'mm:ss') {
let ms = toMs(time, format)
return Math.floor(ms / SECOND)
}
// =============================================================================
// Utility functions
// =============================================================================
function formatTime (time, format) {
let showMs
let showSc
let showHr
switch (format.toLowerCase()) {
case 'hh:mm:ss.sss':
showMs = true
showSc = true
showHr = true
break
case 'hh:mm:ss':
showMs = !(!time.miliseconds)
showSc = true
showHr = true
break
case 'hh:mm':
showMs = !(!time.miliseconds)
showSc = showMs || !(!time.seconds)
showHr = true
break
case 'mm:ss':
showMs = !(!time.miliseconds)
showSc = true
showHr = !(!time.hours)
break
case 'mm:ss.sss':
showMs = true
showSc = true
showHr = !(!time.hours)
break
default:
throw new Error(TIME_FORMAT_ERRMSG)
}
let hh = zeroFill(2, time.hours)
let mm = zeroFill(2, time.minutes)
let ss = zeroFill(2, time.seconds)
let sss = zeroFill(3, time.miliseconds)
return (time.negative ? '-' : '') + (showHr ? (
showMs ? `${hh}:${mm}:${ss}.${sss}` : showSc ? `${hh}:${mm}:${ss}` : `${hh}:${mm}`
) : (
showMs ? `${mm}:${ss}.${sss}` : `${mm}:${ss}`
))
}
{
"_from": "hh-mm-ss@~1.2.0",
"_id": "hh-mm-ss@1.2.0",
"_inBundle": false,
"_integrity": "sha512-f4I9Hz1dLpX/3mrEs7yq30+FiuO3tt5NWAqAGeBTaoeoBfB8vhcQ3BphuDc5DjZb/K809agqrAaFlP0jhEU/8w==",
"_location": "/hh-mm-ss",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "hh-mm-ss@~1.2.0",
"name": "hh-mm-ss",
"escapedName": "hh-mm-ss",
"rawSpec": "~1.2.0",
"saveSpec": null,
"fetchSpec": "~1.2.0"
},
"_requiredBy": [
"/youtube-dl"
],
"_resolved": "https://registry.npmjs.org/hh-mm-ss/-/hh-mm-ss-1.2.0.tgz",
"_shasum": "6d0f0b8280824a634cb1d1f20e0bc7bc8b689948",
"_spec": "hh-mm-ss@~1.2.0",
"_where": "C:\\Users\\user\\Desktop\\오소git\\오소플젝\\Youtube_MPL\\node_modules\\youtube-dl",
"author": {
"name": "Adam Gotlib"
},
"bugs": {
"url": "https://github.com/Goldob/hh-mm-ss/issues"
},
"bundleDependencies": false,
"dependencies": {
"zero-fill": "^2.2.3"
},
"deprecated": false,
"description": "Simple hh:mm:ss time formatting utility",
"devDependencies": {
"standard": "^7.1.2",
"tape": "^4.6.0"
},
"homepage": "https://github.com/Goldob/hh-mm-ss#readme",
"keywords": [
"time format",
"hours",
"minutes",
"seconds",
"miliseconds",
"hh:mm:ss"
],
"license": "MIT",
"main": "index.js",
"name": "hh-mm-ss",
"repository": {
"type": "git",
"url": "git+https://github.com/Goldob/hh-mm-ss.git"
},
"scripts": {
"test": "standard & node test"
},
"version": "1.2.0"
}
'use-strict'
const test = require('tape')
const {fromMs, fromS, toMs, toS} = require('../')
// =============================================================================
// Test cases
// =============================================================================
test('fromMs() test', (t) => {
// Basic functionality
t.equal(fromMs(75000), '01:15')
t.equal(fromMs(442800000), '123:00:00')
t.equal(fromMs(90576), '01:30.576')
t.equal(fromMs(-157250), '-02:37.250')
// Output formatting
t.equal(fromMs(38000, 'mm:ss.sss'), '00:38.000')
t.equal(fromMs(0, 'hh:mm:ss'), '00:00:00')
t.equal(fromMs(3600000, 'mm:ss'), '01:00:00')
t.equal(fromMs(4500000, 'hh:mm'), '01:15')
t.equal(fromMs(-9900000, 'hh:mm'), '-02:45')
// Input validation
t.throws(() => fromMs(null))
t.throws(() => fromMs('text'))
t.throws(() => fromMs(0, 'mm:hh:ss'))
t.end()
})
test('fromS() test', (t) => {
// Basic functionality
t.equal(fromS(75), '01:15')
t.equal(fromS(442800), '123:00:00')
t.equal(fromS(-442800), '-123:00:00')
// Output formatting
t.equal(fromS(38, 'mm:ss.sss'), '00:38.000')
t.equal(fromS(0, 'hh:mm:ss'), '00:00:00')
t.equal(fromS(3600, 'mm:ss'), '01:00:00')
t.equal(fromS(4500, 'hh:mm'), '01:15')
t.equal(fromS(-9900, 'hh:mm'), '-02:45')
// Input validation
t.throws(() => fromS(null))
t.throws(() => fromS('text'))
t.throws(() => fromS(0, 'mm:hh:ss'))
t.end()
})
test('toMs() test', (t) => {
// Basic functionality
t.equal(toMs('01:05:17'), 3917000)
t.equal(toMs('137:00:00.0'), 493200000)
t.equal(toMs('00:10.230'), 10230)
t.equal(toMs('00:00:07.10845'), 7108)
t.equal(toMs('-02:07:12'), -7632000)
t.equal(toMs('02:00'), 120000)
t.equal(toMs('02:00', 'hh:mm'), 7200000)
t.equal(toMs('-04:35', 'hh:mm'), -16500000)
t.equal(toMs('00:00:07.10845', 'hh:mm'), 7108)
// Input validation
t.throws(() => toMs('13:05:02:11'))
t.throws(() => toMs('153'))
t.throws(() => toMs(null))
t.throws(() => toMs('00:62'))
t.throws(() => toS('01:30', 'mm:hh:ss'))
t.end()
})
test('toS() test', (t) => {
// Basic functionality
t.equal(toS('01:05:17'), 3917)
t.equal(toS('137:00:00.0'), 493200)
t.equal(toS('00:10.230'), 10)
t.equal(toS('00:00:07.10845'), 7)
t.equal(toS('-02:07:12'), -7632)
t.equal(toS('02:00'), 120)
t.equal(toS('02:00', 'hh:mm'), 7200)
t.equal(toS('-04:35', 'hh:mm'), -16500)
t.equal(toS('00:00:07.10845', 'hh:mm'), 7)
// Input validation
t.throws(() => toS('13:05:02:11'))
t.throws(() => toS('153'))
t.throws(() => toS(null))
t.throws(() => toS('00:62'))
t.throws(() => toS('01:30', 'mm:hh:ss'))
t.end()
})
test('symmetrical conversion test', (t) => {
/*
* fromMs() and toMs() for all formats
*/
// 90000ms = 1m 30s
t.equal(toMs(fromMs(90000, 'mm:ss'), 'mm:ss'), 90000)
t.equal(toMs(fromMs(90000, 'mm:ss.sss'), 'mm:ss.sss'), 90000)
t.equal(toMs(fromMs(90000, 'hh:mm'), 'hh:mm'), 90000)
t.equal(toMs(fromMs(90000, 'hh:mm:ss'), 'hh:mm:ss'), 90000)
t.equal(toMs(fromMs(90000, 'hh:mm:ss.sss'), 'hh:mm:ss.sss'), 90000)
// 7517245ms = 2h 5m 17.245s
t.equal(toMs(fromMs(7517245, 'mm:ss'), 'mm:ss'), 7517245)
t.equal(toMs(fromMs(7517245, 'mm:ss.sss'), 'mm:ss.sss'), 7517245)
t.equal(toMs(fromMs(7517245, 'hh:mm'), 'hh:mm'), 7517245)
t.equal(toMs(fromMs(7517245, 'hh:mm:ss'), 'hh:mm:ss'), 7517245)
t.equal(toMs(fromMs(7517245, 'hh:mm:ss.sss'), 'hh:mm:ss.sss'), 7517245)
// -10800000ms = -3h
t.equal(toMs(fromMs(-10800000, 'mm:ss'), 'mm:ss'), -10800000)
t.equal(toMs(fromMs(-10800000, 'mm:ss.sss'), 'mm:ss.sss'), -10800000)
t.equal(toMs(fromMs(-10800000, 'hh:mm'), 'hh:mm'), -10800000)
t.equal(toMs(fromMs(-10800000, 'hh:mm:ss'), 'hh:mm:ss'), -10800000)
t.equal(toMs(fromMs(-10800000, 'hh:mm:ss.sss'), 'hh:mm:ss.sss'), -10800000)
/*
* fromS() and toMs() for all formats
*/
// 930s = 15m 30s
t.equal(toS(fromS(930, 'mm:ss'), 'mm:ss'), 930)
t.equal(toS(fromS(930, 'mm:ss.sss'), 'mm:ss.sss'), 930)
t.equal(toS(fromS(930, 'hh:mm'), 'hh:mm'), 930)
t.equal(toS(fromS(930, 'hh:mm:ss'), 'hh:mm:ss'), 930)
t.equal(toS(fromS(930, 'hh:mm:ss.sss'), 'hh:mm:ss.sss'), 930)
// 4850s = 1h 20m 50s
t.equal(toS(fromS(4850, 'mm:ss'), 'mm:ss'), 4850)
t.equal(toS(fromS(4850, 'mm:ss.sss'), 'mm:ss.sss'), 4850)
t.equal(toS(fromS(4850, 'hh:mm'), 'hh:mm'), 4850)
t.equal(toS(fromS(4850, 'hh:mm:ss'), 'hh:mm:ss'), 4850)
t.equal(toS(fromS(4850, 'hh:mm:ss.sss'), 'hh:mm:ss.sss'), 4850)
// -300s = -5m
t.equal(toS(fromS(-300, 'mm:ss'), 'mm:ss'), -300)
t.equal(toS(fromS(-300, 'mm:ss.sss'), 'mm:ss.sss'), -300)
t.equal(toS(fromS(-300, 'hh:mm'), 'hh:mm'), -300)
t.equal(toS(fromS(-300, 'hh:mm:ss'), 'hh:mm:ss'), -300)
t.equal(toS(fromS(-300, 'hh:mm:ss.sss'), 'hh:mm:ss.sss'), -300)
t.end()
})
language: node_js
node_js:
- "0.8"
- "0.10"
This software is released under the MIT license:
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
var argv = require('../')(process.argv.slice(2));
console.dir(argv);
module.exports = function (args, opts) {
if (!opts) opts = {};
var flags = { bools : {}, strings : {} };
[].concat(opts['boolean']).filter(Boolean).forEach(function (key) {
flags.bools[key] = true;
});
[].concat(opts.string).filter(Boolean).forEach(function (key) {
flags.strings[key] = true;
});
var aliases = {};
Object.keys(opts.alias || {}).forEach(function (key) {
aliases[key] = [].concat(opts.alias[key]);
aliases[key].forEach(function (x) {
aliases[x] = [key].concat(aliases[key].filter(function (y) {
return x !== y;
}));
});
});
var defaults = opts['default'] || {};
var argv = { _ : [] };
Object.keys(flags.bools).forEach(function (key) {
setArg(key, defaults[key] === undefined ? false : defaults[key]);
});
var notFlags = [];
if (args.indexOf('--') !== -1) {
notFlags = args.slice(args.indexOf('--')+1);
args = args.slice(0, args.indexOf('--'));
}
function setArg (key, val) {
var value = !flags.strings[key] && isNumber(val)
? Number(val) : val
;
setKey(argv, key.split('.'), value);
(aliases[key] || []).forEach(function (x) {
setKey(argv, x.split('.'), value);
});
}
for (var i = 0; i < args.length; i++) {
var arg = args[i];
if (/^--.+=/.test(arg)) {
// Using [\s\S] instead of . because js doesn't support the
// 'dotall' regex modifier. See:
// http://stackoverflow.com/a/1068308/13216
var m = arg.match(/^--([^=]+)=([\s\S]*)$/);
setArg(m[1], m[2]);
}
else if (/^--no-.+/.test(arg)) {
var key = arg.match(/^--no-(.+)/)[1];
setArg(key, false);
}
else if (/^--.+/.test(arg)) {
var key = arg.match(/^--(.+)/)[1];
var next = args[i + 1];
if (next !== undefined && !/^-/.test(next)
&& !flags.bools[key]
&& (aliases[key] ? !flags.bools[aliases[key]] : true)) {
setArg(key, next);
i++;
}
else if (/^(true|false)$/.test(next)) {
setArg(key, next === 'true');
i++;
}
else {
setArg(key, flags.strings[key] ? '' : true);
}
}
else if (/^-[^-]+/.test(arg)) {
var letters = arg.slice(1,-1).split('');
var broken = false;
for (var j = 0; j < letters.length; j++) {
var next = arg.slice(j+2);
if (next === '-') {
setArg(letters[j], next)
continue;
}
if (/[A-Za-z]/.test(letters[j])
&& /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
setArg(letters[j], next);
broken = true;
break;
}
if (letters[j+1] && letters[j+1].match(/\W/)) {
setArg(letters[j], arg.slice(j+2));
broken = true;
break;
}
else {
setArg(letters[j], flags.strings[letters[j]] ? '' : true);
}
}
var key = arg.slice(-1)[0];
if (!broken && key !== '-') {
if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1])
&& !flags.bools[key]
&& (aliases[key] ? !flags.bools[aliases[key]] : true)) {
setArg(key, args[i+1]);
i++;
}
else if (args[i+1] && /true|false/.test(args[i+1])) {
setArg(key, args[i+1] === 'true');
i++;
}
else {
setArg(key, flags.strings[key] ? '' : true);
}
}
}
else {
argv._.push(
flags.strings['_'] || !isNumber(arg) ? arg : Number(arg)
);
}
}
Object.keys(defaults).forEach(function (key) {
if (!hasKey(argv, key.split('.'))) {
setKey(argv, key.split('.'), defaults[key]);
(aliases[key] || []).forEach(function (x) {
setKey(argv, x.split('.'), defaults[key]);
});
}
});
notFlags.forEach(function(key) {
argv._.push(key);
});
return argv;
};
function hasKey (obj, keys) {
var o = obj;
keys.slice(0,-1).forEach(function (key) {
o = (o[key] || {});
});
var key = keys[keys.length - 1];
return key in o;
}
function setKey (obj, keys, value) {
var o = obj;
keys.slice(0,-1).forEach(function (key) {
if (o[key] === undefined) o[key] = {};
o = o[key];
});
var key = keys[keys.length - 1];
if (o[key] === undefined || typeof o[key] === 'boolean') {
o[key] = value;
}
else if (Array.isArray(o[key])) {
o[key].push(value);
}
else {
o[key] = [ o[key], value ];
}
}
function isNumber (x) {
if (typeof x === 'number') return true;
if (/^0x[0-9a-f]+$/i.test(x)) return true;
return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
}
function longest (xs) {
return Math.max.apply(null, xs.map(function (x) { return x.length }));
}
{
"_from": "minimist@0.0.8",
"_id": "minimist@0.0.8",
"_inBundle": false,
"_integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"_location": "/minimist",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "minimist@0.0.8",
"name": "minimist",
"escapedName": "minimist",
"rawSpec": "0.0.8",
"saveSpec": null,
"fetchSpec": "0.0.8"
},
"_requiredBy": [
"/mkdirp"
],
"_resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"_shasum": "857fcabfc3397d2625b8228262e86aa7a011b05d",
"_spec": "minimist@0.0.8",
"_where": "C:\\Users\\user\\Desktop\\오소git\\오소플젝\\Youtube_MPL\\node_modules\\mkdirp",
"author": {
"name": "James Halliday",
"email": "mail@substack.net",
"url": "http://substack.net"
},
"bugs": {
"url": "https://github.com/substack/minimist/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "parse argument options",
"devDependencies": {
"tap": "~0.4.0",
"tape": "~1.0.4"
},
"homepage": "https://github.com/substack/minimist",
"keywords": [
"argv",
"getopt",
"parser",
"optimist"
],
"license": "MIT",
"main": "index.js",
"name": "minimist",
"repository": {
"type": "git",
"url": "git://github.com/substack/minimist.git"
},
"scripts": {
"test": "tap test/*.js"
},
"testling": {
"files": "test/*.js",
"browsers": [
"ie/6..latest",
"ff/5",
"firefox/latest",
"chrome/10",
"chrome/latest",
"safari/5.1",
"safari/latest",
"opera/12"
]
},
"version": "0.0.8"
}
# minimist
parse argument options
This module is the guts of optimist's argument parser without all the
fanciful decoration.
[![browser support](https://ci.testling.com/substack/minimist.png)](http://ci.testling.com/substack/minimist)
[![build status](https://secure.travis-ci.org/substack/minimist.png)](http://travis-ci.org/substack/minimist)
# example
``` js
var argv = require('minimist')(process.argv.slice(2));
console.dir(argv);
```
```
$ node example/parse.js -a beep -b boop
{ _: [], a: 'beep', b: 'boop' }
```
```
$ node example/parse.js -x 3 -y 4 -n5 -abc --beep=boop foo bar baz
{ _: [ 'foo', 'bar', 'baz' ],
x: 3,
y: 4,
n: 5,
a: true,
b: true,
c: true,
beep: 'boop' }
```
# methods
``` js
var parseArgs = require('minimist')
```
## var argv = parseArgs(args, opts={})
Return an argument object `argv` populated with the array arguments from `args`.
`argv._` contains all the arguments that didn't have an option associated with
them.
Numeric-looking arguments will be returned as numbers unless `opts.string` or
`opts.boolean` is set for that argument name.
Any arguments after `'--'` will not be parsed and will end up in `argv._`.
options can be:
* `opts.string` - a string or array of strings argument names to always treat as
strings
* `opts.boolean` - a string or array of strings to always treat as booleans
* `opts.alias` - an object mapping string names to strings or arrays of string
argument names to use as aliases
* `opts.default` - an object mapping string argument names to default values
# install
With [npm](https://npmjs.org) do:
```
npm install minimist
```
# license
MIT
var parse = require('../');
var test = require('tape');
test('-', function (t) {
t.plan(5);
t.deepEqual(parse([ '-n', '-' ]), { n: '-', _: [] });
t.deepEqual(parse([ '-' ]), { _: [ '-' ] });
t.deepEqual(parse([ '-f-' ]), { f: '-', _: [] });
t.deepEqual(
parse([ '-b', '-' ], { boolean: 'b' }),
{ b: true, _: [ '-' ] }
);
t.deepEqual(
parse([ '-s', '-' ], { string: 's' }),
{ s: '-', _: [] }
);
});
test('-a -- b', function (t) {
t.plan(3);
t.deepEqual(parse([ '-a', '--', 'b' ]), { a: true, _: [ 'b' ] });
t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] });
t.deepEqual(parse([ '--a', '--', 'b' ]), { a: true, _: [ 'b' ] });
});
var test = require('tape');
var parse = require('../');
test('boolean default true', function (t) {
var argv = parse([], {
boolean: 'sometrue',
default: { sometrue: true }
});
t.equal(argv.sometrue, true);
t.end();
});
test('boolean default false', function (t) {
var argv = parse([], {
boolean: 'somefalse',
default: { somefalse: false }
});
t.equal(argv.somefalse, false);
t.end();
});
var parse = require('../');
var test = require('tape');
test('dotted alias', function (t) {
var argv = parse(['--a.b', '22'], {default: {'a.b': 11}, alias: {'a.b': 'aa.bb'}});
t.equal(argv.a.b, 22);
t.equal(argv.aa.bb, 22);
t.end();
});
test('dotted default', function (t) {
var argv = parse('', {default: {'a.b': 11}, alias: {'a.b': 'aa.bb'}});
t.equal(argv.a.b, 11);
t.equal(argv.aa.bb, 11);
t.end();
});
var test = require('tape');
var parse = require('../');
test('long opts', function (t) {
t.deepEqual(
parse([ '--bool' ]),
{ bool : true, _ : [] },
'long boolean'
);
t.deepEqual(
parse([ '--pow', 'xixxle' ]),
{ pow : 'xixxle', _ : [] },
'long capture sp'
);
t.deepEqual(
parse([ '--pow=xixxle' ]),
{ pow : 'xixxle', _ : [] },
'long capture eq'
);
t.deepEqual(
parse([ '--host', 'localhost', '--port', '555' ]),
{ host : 'localhost', port : 555, _ : [] },
'long captures sp'
);
t.deepEqual(
parse([ '--host=localhost', '--port=555' ]),
{ host : 'localhost', port : 555, _ : [] },
'long captures eq'
);
t.end();
});
var parse = require('../');
var test = require('tape');
test('parse args', function (t) {
t.deepEqual(
parse([ '--no-moo' ]),
{ moo : false, _ : [] },
'no'
);
t.deepEqual(
parse([ '-v', 'a', '-v', 'b', '-v', 'c' ]),
{ v : ['a','b','c'], _ : [] },
'multi'
);
t.end();
});
test('comprehensive', function (t) {
t.deepEqual(
parse([
'--name=meowmers', 'bare', '-cats', 'woo',
'-h', 'awesome', '--multi=quux',
'--key', 'value',
'-b', '--bool', '--no-meep', '--multi=baz',
'--', '--not-a-flag', 'eek'
]),
{
c : true,
a : true,
t : true,
s : 'woo',
h : 'awesome',
b : true,
bool : true,
key : 'value',
multi : [ 'quux', 'baz' ],
meep : false,
name : 'meowmers',
_ : [ 'bare', '--not-a-flag', 'eek' ]
}
);
t.end();
});
test('nums', function (t) {
var argv = parse([
'-x', '1234',
'-y', '5.67',
'-z', '1e7',
'-w', '10f',
'--hex', '0xdeadbeef',
'789'
]);
t.deepEqual(argv, {
x : 1234,
y : 5.67,
z : 1e7,
w : '10f',
hex : 0xdeadbeef,
_ : [ 789 ]
});
t.deepEqual(typeof argv.x, 'number');
t.deepEqual(typeof argv.y, 'number');
t.deepEqual(typeof argv.z, 'number');
t.deepEqual(typeof argv.w, 'string');
t.deepEqual(typeof argv.hex, 'number');
t.deepEqual(typeof argv._[0], 'number');
t.end();
});
test('flag boolean', function (t) {
var argv = parse([ '-t', 'moo' ], { boolean: 't' });
t.deepEqual(argv, { t : true, _ : [ 'moo' ] });
t.deepEqual(typeof argv.t, 'boolean');
t.end();
});
test('flag boolean value', function (t) {
var argv = parse(['--verbose', 'false', 'moo', '-t', 'true'], {
boolean: [ 't', 'verbose' ],
default: { verbose: true }
});
t.deepEqual(argv, {
verbose: false,
t: true,
_: ['moo']
});
t.deepEqual(typeof argv.verbose, 'boolean');
t.deepEqual(typeof argv.t, 'boolean');
t.end();
});
test('flag boolean default false', function (t) {
var argv = parse(['moo'], {
boolean: ['t', 'verbose'],
default: { verbose: false, t: false }
});
t.deepEqual(argv, {
verbose: false,
t: false,
_: ['moo']
});
t.deepEqual(typeof argv.verbose, 'boolean');
t.deepEqual(typeof argv.t, 'boolean');
t.end();
});
test('boolean groups', function (t) {
var argv = parse([ '-x', '-z', 'one', 'two', 'three' ], {
boolean: ['x','y','z']
});
t.deepEqual(argv, {
x : true,
y : false,
z : true,
_ : [ 'one', 'two', 'three' ]
});
t.deepEqual(typeof argv.x, 'boolean');
t.deepEqual(typeof argv.y, 'boolean');
t.deepEqual(typeof argv.z, 'boolean');
t.end();
});
test('newlines in params' , function (t) {
var args = parse([ '-s', "X\nX" ])
t.deepEqual(args, { _ : [], s : "X\nX" });
// reproduce in bash:
// VALUE="new
// line"
// node program.js --s="$VALUE"
args = parse([ "--s=X\nX" ])
t.deepEqual(args, { _ : [], s : "X\nX" });
t.end();
});
test('strings' , function (t) {
var s = parse([ '-s', '0001234' ], { string: 's' }).s;
t.equal(s, '0001234');
t.equal(typeof s, 'string');
var x = parse([ '-x', '56' ], { string: 'x' }).x;
t.equal(x, '56');
t.equal(typeof x, 'string');
t.end();
});
test('stringArgs', function (t) {
var s = parse([ ' ', ' ' ], { string: '_' })._;
t.same(s.length, 2);
t.same(typeof s[0], 'string');
t.same(s[0], ' ');
t.same(typeof s[1], 'string');
t.same(s[1], ' ');
t.end();
});
test('empty strings', function(t) {
var s = parse([ '-s' ], { string: 's' }).s;
t.equal(s, '');
t.equal(typeof s, 'string');
var str = parse([ '--str' ], { string: 'str' }).str;
t.equal(str, '');
t.equal(typeof str, 'string');
var letters = parse([ '-art' ], {
string: [ 'a', 't' ]
});
t.equal(letters.a, '');
t.equal(letters.r, true);
t.equal(letters.t, '');
t.end();
});
test('slashBreak', function (t) {
t.same(
parse([ '-I/foo/bar/baz' ]),
{ I : '/foo/bar/baz', _ : [] }
);
t.same(
parse([ '-xyz/foo/bar/baz' ]),
{ x : true, y : true, z : '/foo/bar/baz', _ : [] }
);
t.end();
});
test('alias', function (t) {
var argv = parse([ '-f', '11', '--zoom', '55' ], {
alias: { z: 'zoom' }
});
t.equal(argv.zoom, 55);
t.equal(argv.z, argv.zoom);
t.equal(argv.f, 11);
t.end();
});
test('multiAlias', function (t) {
var argv = parse([ '-f', '11', '--zoom', '55' ], {
alias: { z: [ 'zm', 'zoom' ] }
});
t.equal(argv.zoom, 55);
t.equal(argv.z, argv.zoom);
t.equal(argv.z, argv.zm);
t.equal(argv.f, 11);
t.end();
});
test('nested dotted objects', function (t) {
var argv = parse([
'--foo.bar', '3', '--foo.baz', '4',
'--foo.quux.quibble', '5', '--foo.quux.o_O',
'--beep.boop'
]);
t.same(argv.foo, {
bar : 3,
baz : 4,
quux : {
quibble : 5,
o_O : true
}
});
t.same(argv.beep, { boop : true });
t.end();
});
test('boolean and alias with chainable api', function (t) {
var aliased = [ '-h', 'derp' ];
var regular = [ '--herp', 'derp' ];
var opts = {
herp: { alias: 'h', boolean: true }
};
var aliasedArgv = parse(aliased, {
boolean: 'herp',
alias: { h: 'herp' }
});
var propertyArgv = parse(regular, {
boolean: 'herp',
alias: { h: 'herp' }
});
var expected = {
herp: true,
h: true,
'_': [ 'derp' ]
};
t.same(aliasedArgv, expected);
t.same(propertyArgv, expected);
t.end();
});
test('boolean and alias with options hash', function (t) {
var aliased = [ '-h', 'derp' ];
var regular = [ '--herp', 'derp' ];
var opts = {
alias: { 'h': 'herp' },
boolean: 'herp'
};
var aliasedArgv = parse(aliased, opts);
var propertyArgv = parse(regular, opts);
var expected = {
herp: true,
h: true,
'_': [ 'derp' ]
};
t.same(aliasedArgv, expected);
t.same(propertyArgv, expected);
t.end();
});
test('boolean and alias using explicit true', function (t) {
var aliased = [ '-h', 'true' ];
var regular = [ '--herp', 'true' ];
var opts = {
alias: { h: 'herp' },
boolean: 'h'
};
var aliasedArgv = parse(aliased, opts);
var propertyArgv = parse(regular, opts);
var expected = {
herp: true,
h: true,
'_': [ ]
};
t.same(aliasedArgv, expected);
t.same(propertyArgv, expected);
t.end();
});
// regression, see https://github.com/substack/node-optimist/issues/71
test('boolean and --x=true', function(t) {
var parsed = parse(['--boool', '--other=true'], {
boolean: 'boool'
});
t.same(parsed.boool, true);
t.same(parsed.other, 'true');
parsed = parse(['--boool', '--other=false'], {
boolean: 'boool'
});
t.same(parsed.boool, true);
t.same(parsed.other, 'false');
t.end();
});
var parse = require('../');
var test = require('tape');
test('parse with modifier functions' , function (t) {
t.plan(1);
var argv = parse([ '-b', '123' ], { boolean: 'b' });
t.deepEqual(argv, { b: true, _: ['123'] });
});
var parse = require('../');
var test = require('tape');
test('numeric short args', function (t) {
t.plan(2);
t.deepEqual(parse([ '-n123' ]), { n: 123, _: [] });
t.deepEqual(
parse([ '-123', '456' ]),
{ 1: true, 2: true, 3: 456, _: [] }
);
});
test('short', function (t) {
t.deepEqual(
parse([ '-b' ]),
{ b : true, _ : [] },
'short boolean'
);
t.deepEqual(
parse([ 'foo', 'bar', 'baz' ]),
{ _ : [ 'foo', 'bar', 'baz' ] },
'bare'
);
t.deepEqual(
parse([ '-cats' ]),
{ c : true, a : true, t : true, s : true, _ : [] },
'group'
);
t.deepEqual(
parse([ '-cats', 'meow' ]),
{ c : true, a : true, t : true, s : 'meow', _ : [] },
'short group next'
);
t.deepEqual(
parse([ '-h', 'localhost' ]),
{ h : 'localhost', _ : [] },
'short capture'
);
t.deepEqual(
parse([ '-h', 'localhost', '-p', '555' ]),
{ h : 'localhost', p : 555, _ : [] },
'short captures'
);
t.end();
});
test('mixed short bool and capture', function (t) {
t.same(
parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]),
{
f : true, p : 555, h : 'localhost',
_ : [ 'script.js' ]
}
);
t.end();
});
test('short and long', function (t) {
t.deepEqual(
parse([ '-h', 'localhost', '-fp', '555', 'script.js' ]),
{
f : true, p : 555, h : 'localhost',
_ : [ 'script.js' ]
}
);
t.end();
});
var parse = require('../');
var test = require('tape');
test('whitespace should be whitespace' , function (t) {
t.plan(1);
var x = parse([ '-x', '\t' ]).x;
t.equal(x, '\t');
});
language: node_js
node_js:
- "0.8"
- "0.10"
- "0.12"
- "iojs"
before_install:
- npm install -g npm@~1.4.6
Copyright 2010 James Halliday (mail@substack.net)
This project is free software released under the MIT/X11 license:
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
#!/usr/bin/env node
var mkdirp = require('../');
var minimist = require('minimist');
var fs = require('fs');
var argv = minimist(process.argv.slice(2), {
alias: { m: 'mode', h: 'help' },
string: [ 'mode' ]
});
if (argv.help) {
fs.createReadStream(__dirname + '/usage.txt').pipe(process.stdout);
return;
}
var paths = argv._.slice();
var mode = argv.mode ? parseInt(argv.mode, 8) : undefined;
(function next () {
if (paths.length === 0) return;
var p = paths.shift();
if (mode === undefined) mkdirp(p, cb)
else mkdirp(p, mode, cb)
function cb (err) {
if (err) {
console.error(err.message);
process.exit(1);
}
else next();
}
})();
usage: mkdirp [DIR1,DIR2..] {OPTIONS}
Create each supplied directory including any necessary parent directories that
don't yet exist.
If the directory already exists, do nothing.
OPTIONS are:
-m, --mode If a directory needs to be created, set the mode as an octal
permission string.
var mkdirp = require('mkdirp');
mkdirp('/tmp/foo/bar/baz', function (err) {
if (err) console.error(err)
else console.log('pow!')
});
var path = require('path');
var fs = require('fs');
var _0777 = parseInt('0777', 8);
module.exports = mkdirP.mkdirp = mkdirP.mkdirP = mkdirP;
function mkdirP (p, opts, f, made) {
if (typeof opts === 'function') {
f = opts;
opts = {};
}
else if (!opts || typeof opts !== 'object') {
opts = { mode: opts };
}
var mode = opts.mode;
var xfs = opts.fs || fs;
if (mode === undefined) {
mode = _0777 & (~process.umask());
}
if (!made) made = null;
var cb = f || function () {};
p = path.resolve(p);
xfs.mkdir(p, mode, function (er) {
if (!er) {
made = made || p;
return cb(null, made);
}
switch (er.code) {
case 'ENOENT':
mkdirP(path.dirname(p), opts, function (er, made) {
if (er) cb(er, made);
else mkdirP(p, opts, cb, made);
});
break;
// In the case of any other error, just see if there's a dir
// there already. If so, then hooray! If not, then something
// is borked.
default:
xfs.stat(p, function (er2, stat) {
// if the stat fails, then that's super weird.
// let the original error be the failure reason.
if (er2 || !stat.isDirectory()) cb(er, made)
else cb(null, made);
});
break;
}
});
}
mkdirP.sync = function sync (p, opts, made) {
if (!opts || typeof opts !== 'object') {
opts = { mode: opts };
}
var mode = opts.mode;
var xfs = opts.fs || fs;
if (mode === undefined) {
mode = _0777 & (~process.umask());
}
if (!made) made = null;
p = path.resolve(p);
try {
xfs.mkdirSync(p, mode);
made = made || p;
}
catch (err0) {
switch (err0.code) {
case 'ENOENT' :
made = sync(path.dirname(p), opts, made);
sync(p, opts, made);
break;
// In the case of any other error, just see if there's a dir
// there already. If so, then hooray! If not, then something
// is borked.
default:
var stat;
try {
stat = xfs.statSync(p);
}
catch (err1) {
throw err0;
}
if (!stat.isDirectory()) throw err0;
break;
}
}
return made;
};
{
"_from": "mkdirp@~0.5.1",
"_id": "mkdirp@0.5.1",
"_inBundle": false,
"_integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"_location": "/mkdirp",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "mkdirp@~0.5.1",
"name": "mkdirp",
"escapedName": "mkdirp",
"rawSpec": "~0.5.1",
"saveSpec": null,
"fetchSpec": "~0.5.1"
},
"_requiredBy": [
"/youtube-dl"
],
"_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"_shasum": "30057438eac6cf7f8c4767f38648d6697d75c903",
"_spec": "mkdirp@~0.5.1",
"_where": "C:\\Users\\user\\Desktop\\오소git\\오소플젝\\Youtube_MPL\\node_modules\\youtube-dl",
"author": {
"name": "James Halliday",
"email": "mail@substack.net",
"url": "http://substack.net"
},
"bin": {
"mkdirp": "bin/cmd.js"
},
"bugs": {
"url": "https://github.com/substack/node-mkdirp/issues"
},
"bundleDependencies": false,
"dependencies": {
"minimist": "0.0.8"
},
"deprecated": false,
"description": "Recursively mkdir, like `mkdir -p`",
"devDependencies": {
"mock-fs": "2 >=2.7.0",
"tap": "1"
},
"homepage": "https://github.com/substack/node-mkdirp#readme",
"keywords": [
"mkdir",
"directory"
],
"license": "MIT",
"main": "index.js",
"name": "mkdirp",
"repository": {
"type": "git",
"url": "git+https://github.com/substack/node-mkdirp.git"
},
"scripts": {
"test": "tap test/*.js"
},
"version": "0.5.1"
}
# mkdirp
Like `mkdir -p`, but in node.js!
[![build status](https://secure.travis-ci.org/substack/node-mkdirp.png)](http://travis-ci.org/substack/node-mkdirp)
# example
## pow.js
```js
var mkdirp = require('mkdirp');
mkdirp('/tmp/foo/bar/baz', function (err) {
if (err) console.error(err)
else console.log('pow!')
});
```
Output
```
pow!
```
And now /tmp/foo/bar/baz exists, huzzah!
# methods
```js
var mkdirp = require('mkdirp');
```
## mkdirp(dir, opts, cb)
Create a new directory and any necessary subdirectories at `dir` with octal
permission string `opts.mode`. If `opts` is a non-object, it will be treated as
the `opts.mode`.
If `opts.mode` isn't specified, it defaults to `0777 & (~process.umask())`.
`cb(err, made)` fires with the error or the first directory `made`
that had to be created, if any.
You can optionally pass in an alternate `fs` implementation by passing in
`opts.fs`. Your implementation should have `opts.fs.mkdir(path, mode, cb)` and
`opts.fs.stat(path, cb)`.
## mkdirp.sync(dir, opts)
Synchronously create a new directory and any necessary subdirectories at `dir`
with octal permission string `opts.mode`. If `opts` is a non-object, it will be
treated as the `opts.mode`.
If `opts.mode` isn't specified, it defaults to `0777 & (~process.umask())`.
Returns the first directory that had to be created, if any.
You can optionally pass in an alternate `fs` implementation by passing in
`opts.fs`. Your implementation should have `opts.fs.mkdirSync(path, mode)` and
`opts.fs.statSync(path)`.
# usage
This package also ships with a `mkdirp` command.
```
usage: mkdirp [DIR1,DIR2..] {OPTIONS}
Create each supplied directory including any necessary parent directories that
don't yet exist.
If the directory already exists, do nothing.
OPTIONS are:
-m, --mode If a directory needs to be created, set the mode as an octal
permission string.
```
# install
With [npm](http://npmjs.org) do:
```
npm install mkdirp
```
to get the library, or
```
npm install -g mkdirp
```
to get the command.
# license
MIT
var mkdirp = require('../').mkdirp;
var path = require('path');
var fs = require('fs');
var test = require('tap').test;
var _0777 = parseInt('0777', 8);
var _0755 = parseInt('0755', 8);
var _0744 = parseInt('0744', 8);
var ps = [ '', 'tmp' ];
for (var i = 0; i < 25; i++) {
var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
ps.push(dir);
}
var file = ps.join('/');
test('chmod-pre', function (t) {
var mode = _0744
mkdirp(file, mode, function (er) {
t.ifError(er, 'should not error');
fs.stat(file, function (er, stat) {
t.ifError(er, 'should exist');
t.ok(stat && stat.isDirectory(), 'should be directory');
t.equal(stat && stat.mode & _0777, mode, 'should be 0744');
t.end();
});
});
});
test('chmod', function (t) {
var mode = _0755
mkdirp(file, mode, function (er) {
t.ifError(er, 'should not error');
fs.stat(file, function (er, stat) {
t.ifError(er, 'should exist');
t.ok(stat && stat.isDirectory(), 'should be directory');
t.end();
});
});
});
var mkdirp = require('../').mkdirp;
var path = require('path');
var fs = require('fs');
var test = require('tap').test;
var _0755 = parseInt('0755', 8);
var ps = [ '', 'tmp' ];
for (var i = 0; i < 25; i++) {
var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
ps.push(dir);
}
var file = ps.join('/');
// a file in the way
var itw = ps.slice(0, 3).join('/');
test('clobber-pre', function (t) {
console.error("about to write to "+itw)
fs.writeFileSync(itw, 'I AM IN THE WAY, THE TRUTH, AND THE LIGHT.');
fs.stat(itw, function (er, stat) {
t.ifError(er)
t.ok(stat && stat.isFile(), 'should be file')
t.end()
})
})
test('clobber', function (t) {
t.plan(2);
mkdirp(file, _0755, function (err) {
t.ok(err);
t.equal(err.code, 'ENOTDIR');
t.end();
});
});
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var exists = fs.exists || path.exists;
var test = require('tap').test;
var _0777 = parseInt('0777', 8);
var _0755 = parseInt('0755', 8);
test('woo', function (t) {
t.plan(5);
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var file = '/tmp/' + [x,y,z].join('/');
mkdirp(file, _0755, function (err) {
t.ifError(err);
exists(file, function (ex) {
t.ok(ex, 'file created');
fs.stat(file, function (err, stat) {
t.ifError(err);
t.equal(stat.mode & _0777, _0755);
t.ok(stat.isDirectory(), 'target not a directory');
})
})
});
});
var mkdirp = require('../');
var path = require('path');
var test = require('tap').test;
var mockfs = require('mock-fs');
var _0777 = parseInt('0777', 8);
var _0755 = parseInt('0755', 8);
test('opts.fs', function (t) {
t.plan(5);
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var file = '/beep/boop/' + [x,y,z].join('/');
var xfs = mockfs.fs();
mkdirp(file, { fs: xfs, mode: _0755 }, function (err) {
t.ifError(err);
xfs.exists(file, function (ex) {
t.ok(ex, 'created file');
xfs.stat(file, function (err, stat) {
t.ifError(err);
t.equal(stat.mode & _0777, _0755);
t.ok(stat.isDirectory(), 'target not a directory');
});
});
});
});
var mkdirp = require('../');
var path = require('path');
var test = require('tap').test;
var mockfs = require('mock-fs');
var _0777 = parseInt('0777', 8);
var _0755 = parseInt('0755', 8);
test('opts.fs sync', function (t) {
t.plan(4);
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var file = '/beep/boop/' + [x,y,z].join('/');
var xfs = mockfs.fs();
mkdirp.sync(file, { fs: xfs, mode: _0755 });
xfs.exists(file, function (ex) {
t.ok(ex, 'created file');
xfs.stat(file, function (err, stat) {
t.ifError(err);
t.equal(stat.mode & _0777, _0755);
t.ok(stat.isDirectory(), 'target not a directory');
});
});
});
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var exists = fs.exists || path.exists;
var test = require('tap').test;
var _0777 = parseInt('0777', 8);
var _0755 = parseInt('0755', 8);
test('async perm', function (t) {
t.plan(5);
var file = '/tmp/' + (Math.random() * (1<<30)).toString(16);
mkdirp(file, _0755, function (err) {
t.ifError(err);
exists(file, function (ex) {
t.ok(ex, 'file created');
fs.stat(file, function (err, stat) {
t.ifError(err);
t.equal(stat.mode & _0777, _0755);
t.ok(stat.isDirectory(), 'target not a directory');
})
})
});
});
test('async root perm', function (t) {
mkdirp('/tmp', _0755, function (err) {
if (err) t.fail(err);
t.end();
});
t.end();
});
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var exists = fs.exists || path.exists;
var test = require('tap').test;
var _0777 = parseInt('0777', 8);
var _0755 = parseInt('0755', 8);
test('sync perm', function (t) {
t.plan(4);
var file = '/tmp/' + (Math.random() * (1<<30)).toString(16) + '.json';
mkdirp.sync(file, _0755);
exists(file, function (ex) {
t.ok(ex, 'file created');
fs.stat(file, function (err, stat) {
t.ifError(err);
t.equal(stat.mode & _0777, _0755);
t.ok(stat.isDirectory(), 'target not a directory');
});
});
});
test('sync root perm', function (t) {
t.plan(3);
var file = '/tmp';
mkdirp.sync(file, _0755);
exists(file, function (ex) {
t.ok(ex, 'file created');
fs.stat(file, function (err, stat) {
t.ifError(err);
t.ok(stat.isDirectory(), 'target not a directory');
})
});
});
var mkdirp = require('../').mkdirp;
var path = require('path');
var fs = require('fs');
var exists = fs.exists || path.exists;
var test = require('tap').test;
var _0777 = parseInt('0777', 8);
var _0755 = parseInt('0755', 8);
test('race', function (t) {
t.plan(10);
var ps = [ '', 'tmp' ];
for (var i = 0; i < 25; i++) {
var dir = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
ps.push(dir);
}
var file = ps.join('/');
var res = 2;
mk(file);
mk(file);
function mk (file, cb) {
mkdirp(file, _0755, function (err) {
t.ifError(err);
exists(file, function (ex) {
t.ok(ex, 'file created');
fs.stat(file, function (err, stat) {
t.ifError(err);
t.equal(stat.mode & _0777, _0755);
t.ok(stat.isDirectory(), 'target not a directory');
});
})
});
}
});
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var exists = fs.exists || path.exists;
var test = require('tap').test;
var _0777 = parseInt('0777', 8);
var _0755 = parseInt('0755', 8);
test('rel', function (t) {
t.plan(5);
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var cwd = process.cwd();
process.chdir('/tmp');
var file = [x,y,z].join('/');
mkdirp(file, _0755, function (err) {
t.ifError(err);
exists(file, function (ex) {
t.ok(ex, 'file created');
fs.stat(file, function (err, stat) {
t.ifError(err);
process.chdir(cwd);
t.equal(stat.mode & _0777, _0755);
t.ok(stat.isDirectory(), 'target not a directory');
})
})
});
});
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var test = require('tap').test;
test('return value', function (t) {
t.plan(4);
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var file = '/tmp/' + [x,y,z].join('/');
// should return the first dir created.
// By this point, it would be profoundly surprising if /tmp didn't
// already exist, since every other test makes things in there.
mkdirp(file, function (err, made) {
t.ifError(err);
t.equal(made, '/tmp/' + x);
mkdirp(file, function (err, made) {
t.ifError(err);
t.equal(made, null);
});
});
});
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var test = require('tap').test;
test('return value', function (t) {
t.plan(2);
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var file = '/tmp/' + [x,y,z].join('/');
// should return the first dir created.
// By this point, it would be profoundly surprising if /tmp didn't
// already exist, since every other test makes things in there.
// Note that this will throw on failure, which will fail the test.
var made = mkdirp.sync(file);
t.equal(made, '/tmp/' + x);
// making the same file again should have no effect.
made = mkdirp.sync(file);
t.equal(made, null);
});
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var test = require('tap').test;
var _0755 = parseInt('0755', 8);
test('root', function (t) {
// '/' on unix, 'c:/' on windows.
var file = path.resolve('/');
mkdirp(file, _0755, function (err) {
if (err) throw err
fs.stat(file, function (er, stat) {
if (er) throw er
t.ok(stat.isDirectory(), 'target is a directory');
t.end();
})
});
});
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var exists = fs.exists || path.exists;
var test = require('tap').test;
var _0777 = parseInt('0777', 8);
var _0755 = parseInt('0755', 8);
test('sync', function (t) {
t.plan(4);
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var file = '/tmp/' + [x,y,z].join('/');
try {
mkdirp.sync(file, _0755);
} catch (err) {
t.fail(err);
return t.end();
}
exists(file, function (ex) {
t.ok(ex, 'file created');
fs.stat(file, function (err, stat) {
t.ifError(err);
t.equal(stat.mode & _0777, _0755);
t.ok(stat.isDirectory(), 'target not a directory');
});
});
});
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var exists = fs.exists || path.exists;
var test = require('tap').test;
var _0777 = parseInt('0777', 8);
var _0755 = parseInt('0755', 8);
test('implicit mode from umask', function (t) {
t.plan(5);
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var file = '/tmp/' + [x,y,z].join('/');
mkdirp(file, function (err) {
t.ifError(err);
exists(file, function (ex) {
t.ok(ex, 'file created');
fs.stat(file, function (err, stat) {
t.ifError(err);
t.equal(stat.mode & _0777, _0777 & (~process.umask()));
t.ok(stat.isDirectory(), 'target not a directory');
});
})
});
});
var mkdirp = require('../');
var path = require('path');
var fs = require('fs');
var exists = fs.exists || path.exists;
var test = require('tap').test;
var _0777 = parseInt('0777', 8);
var _0755 = parseInt('0755', 8);
test('umask sync modes', function (t) {
t.plan(4);
var x = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var y = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var z = Math.floor(Math.random() * Math.pow(16,4)).toString(16);
var file = '/tmp/' + [x,y,z].join('/');
try {
mkdirp.sync(file);
} catch (err) {
t.fail(err);
return t.end();
}
exists(file, function (ex) {
t.ok(ex, 'file created');
fs.stat(file, function (err, stat) {
t.ifError(err);
t.equal(stat.mode & _0777, (_0777 & (~process.umask())));
t.ok(stat.isDirectory(), 'target not a directory');
});
});
});
Copyright (C) 2012 by Roly Fentanes
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# node-streamify
Streamify helps you easily provide a streaming interface for your code.
[![Build Status](https://secure.travis-ci.org/fent/node-streamify.svg)](http://travis-ci.org/fent/node-streamify)
[![Dependency Status](https://david-dm.org/fent/node-streamify.svg)](https://david-dm.org/fent/node-streamify)
[![codecov](https://codecov.io/gh/fent/node-streamify/branch/master/graph/badge.svg)](https://codecov.io/gh/fent/node-streamify)
# Usage
```js
var streamify = require('streamify');
var request = require('request');
exports.doSomething = function doSomething() {
var stream = streamify();
request(url1, function(err, res, body) {
// do something with `body`
// once the actual stream you want to return is ready,
// call `stream.resolve()`
stream.resolve(request(url2));
});
// your function can return back a stream!!
return stream;
}
// because `doSomething()` returns a stream, it can be piped
exports.doSomething().pipe(anotherStream);
```
# API
### streamify([options])
Returns an instance of a stream. `options` can be
* `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`.
* `readable` - Defaults to `true`.
* `writable` - Defaults to `true`.
### Stream#resolve(stream)
Must be called only once when the actual stream you are proxying to becomes available after an asynchronous operation.
### Stream#unresolve()
Can be used to unbind a a resolved stream to later call `resolve()` again.
### Stream#addSource(stream)
Add a source readable stream.
### Stream#removeSource()
Remove previously added source stream.
### Stream#addDest(stream)
Add a destination writable stream.
### Stream#removeDest()
Remove a previously added destination stream.
# Install
npm install streamify
# Tests
Tests are written with [mocha](https://mochajs.org)
```bash
npm test
```
# License
MIT
var Readable = require('stream').Readable;
var Writable = require('stream').Writable;
var Duplex = require('stream').Duplex;
var hashish = require('hashish');
/**
* Proxy some events from underlying readable and writable streams.
*/
var SOURCE_EVENTS = ['error', 'close'];
var DEST_EVENTS = ['drain', 'close'];
/**
* Creates property to use with `Object.create()`
*
* @param {Object} value
* @return {Object}
*/
function prop(value) {
return {
writable: true,
enumerable: true,
configurable: true,
value: value
};
}
/**
* @constructor
* @param {Object} options
* {Object} superCtor
* {Boolean} readable
* {Boolean} writable
* @return {Duplex}
*/
var Streamify = module.exports = function Streamify(options) {
options = options || {};
options.readable = typeof options.readable !== 'undefined' ?
options.readable : true;
options.writable = typeof options.writable !== 'undefined' ?
options.writable : true;
var superCtor = getConstructor(options);
// Add `Streamify.prototype` methods.
var properties = hashish.map(Streamify.prototype, prop);
var o = Object.create(superCtor.prototype, properties);
superCtor.call(o);
o.readable = options.readable;
o.writable = options.writable;
o.__options = options;
o._onevent = function onevent() {
};
o._destWritten = [];
if (options.writable) {
o.once('finish', function() {
if (o._dest) {
o._dest.stream.end();
}
});
}
return o;
};
/**
* Required implementation by streaming API.
*
* @param {Number} size
*/
Streamify.prototype._read = function(size) {
if (this._source) {
var self = this;
var onreadable = this._source.onreadable = function onreadable() {
if (!self._source) { return; }
var data = self._source.stream.read(size);
if (data) {
self.push(data);
} else {
self._source.stream.once('readable', onreadable);
}
};
onreadable();
} else {
this._sourceRead = size;
}
};
/**
* Required implementation by streaming API.
*
* @param {Buffer|String} chunk
* @param {!String} encoding
* @param {Function(!Error)} callback
*/
Streamify.prototype._write = function(chunk, encoding, callback) {
if (this._dest) {
this._dest.stream.write(chunk, encoding, callback);
} else {
this._destWritten.push(arguments);
}
};
/**
* Add a stream to be the readable stream source.
*
* @param {Readable|Stream} stream
*/
Streamify.prototype.addSource = function(stream) {
if (this._source) {
throw Error('A source stream has already been added.');
}
stream = getReadable(stream);
this._source = { stream: stream, listeners: {}, onend: onend };
var self = this;
SOURCE_EVENTS.forEach(function(event) {
var onevent = self._source.listeners[event] = function onevent() {
var args = Array.prototype.slice.call(arguments);
self.emit.apply(self, [event].concat(args));
};
stream.on(event, onevent);
});
// Listen for `end` event to signal for end of data.
function onend() {
self.push(null);
}
stream.on('end', onend);
// Check if `Readable#_read()` has already been called.
this._read(this._sourceRead);
};
/**
* Remove a stream from being the source.
*/
Streamify.prototype.removeSource = function() {
if (!this._source) {
throw Error('A source stream has not been added.');
}
var source = this._source;
SOURCE_EVENTS.forEach(function(event) {
source.stream.removeListener(event, source.listeners[event]);
});
source.stream.removeListener('readable', source.onreadable);
source.stream.removeListener('end', source.onend);
delete this._source;
};
/**
* Add a stream to be the writable stream destination.
*
* @param {Writable|Stream} stream
*/
Streamify.prototype.addDest = function(stream) {
if (this._dest) {
throw Error('A destination stream has already been added.');
}
this._dest = { stream: stream, listeners: {} };
var self = this;
DEST_EVENTS.forEach(function(event) {
var onevent = self._dest.listeners[event] = function onevent() {
var args = Array.prototype.slice.call(arguments);
self.emit.apply(self, [event].concat(args));
};
stream.on(event, onevent);
});
if (this._destWritten.length) {
this._destWritten.forEach(function(args) {
stream.write.apply(stream, args);
});
}
};
/**
* Remove a stream from being the destination.
*/
Streamify.prototype.removeDest = function() {
if (!this._dest) {
throw Error('A destination stream has not been added.');
}
var dest = this._dest;
DEST_EVENTS.forEach(function(event) {
dest.stream.removeListener(event, dest.listeners[event]);
});
delete this._dest;
this._destWritten = [];
};
/**
* Begins fueling data from actual stream into Streamify instance.
*
* @param {Readable|Writable|Duplex|Stream} stream
*/
Streamify.prototype.resolve = function(stream) {
if (this.__options.readable && stream.readable) {
this.addSource(stream);
}
if (this.__options.writable && stream.writable) {
this.addDest(stream);
}
};
/**
* Removes a stream from this, possibly because another is replacing it.
*/
Streamify.prototype.unresolve = function() {
if (this._source) {
this.removeSource();
}
if (this._dest) {
this.removeDest();
}
};
/**
* Returns a readable new stream API stream if the stream is using the
* old API. Otherwise it returns the same stream.
*
* @param {Readable|Stream} stream
* @return {Readable}
*/
function getReadable(stream) {
if (isOldStyleStream(stream)) {
var readable = new Readable();
readable.wrap(stream);
return readable;
} else {
return stream;
}
}
/**
* Returns true if a stream is an old style API stream.
*
* @param {Readable|Stream} stream
* @return {Boolean}
*/
function isOldStyleStream(stream) {
return typeof stream.read !== 'function' ||
typeof stream._read !== 'function' ||
typeof stream.push !== 'function' ||
typeof stream.unshift !== 'function' ||
typeof stream.wrap !== 'function';
}
function getConstructor (options) {
var superCtor = Duplex;
if (options.readable && !options.writable) {
superCtor = Readable;
}
if (options.writable && !options.readable) {
superCtor = Writable;
}
return superCtor;
}
\ No newline at end of file
{
"_from": "streamify@~0.2.9",
"_id": "streamify@0.2.9",
"_inBundle": false,
"_integrity": "sha512-8pUxeLEef9UO1FxtTt5iikAiyzGI4SZRnGuJ3sz8axZ5Xk+/7ezEV5kuJQsMEFxw7AKYw3xp0Ow+20mmSaJbQQ==",
"_location": "/streamify",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "streamify@~0.2.9",
"name": "streamify",
"escapedName": "streamify",
"rawSpec": "~0.2.9",
"saveSpec": null,
"fetchSpec": "~0.2.9"
},
"_requiredBy": [
"/youtube-dl"
],
"_resolved": "https://registry.npmjs.org/streamify/-/streamify-0.2.9.tgz",
"_shasum": "8938b14db491e2b6be4f8d99cc4133c9f0384f0b",
"_spec": "streamify@~0.2.9",
"_where": "C:\\Users\\user\\Desktop\\오소git\\오소플젝\\Youtube_MPL\\node_modules\\youtube-dl",
"author": {
"name": "Roly Fentanes",
"url": "https://github.com/fent"
},
"bugs": {
"url": "https://github.com/fent/node-streamify/issues"
},
"bundleDependencies": false,
"dependencies": {
"hashish": "~0.0.4"
},
"deprecated": false,
"description": "Streamify helps you easily provide a streaming interface for code.",
"devDependencies": {
"istanbul": "*",
"mocha": "*",
"stream-equal": "~1.0.0"
},
"directories": {
"lib": "./lib"
},
"engines": {
"node": ">=0.12"
},
"files": [
"lib"
],
"homepage": "https://github.com/fent/node-streamify#readme",
"keywords": [
"stream",
"input",
"output",
"api"
],
"license": "MIT",
"main": "./lib/index.js",
"name": "streamify",
"repository": {
"type": "git",
"url": "git://github.com/fent/node-streamify.git"
},
"scripts": {
"test": "istanbul cover node_modules/.bin/_mocha -- test/*-test.js"
},
"version": "0.2.9"
}
language: node_js
node_js:
- 0.6
Copyright 2010 James Halliday (mail@substack.net)
This project is free software released under the MIT/X11 license:
http://www.opensource.org/licenses/mit-license.php
Copyright 2010 James Halliday (mail@substack.net)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
var traverse = require('traverse');
var id = 54;
var callbacks = {};
var obj = { moo : function () {}, foo : [2,3,4, function () {}] };
var scrubbed = traverse(obj).map(function (x) {
if (typeof x === 'function') {
callbacks[id] = { id : id, f : x, path : this.path };
this.update('[Function]');
id++;
}
});
console.dir(scrubbed);
console.dir(callbacks);
var traverse = require('traverse');
var obj = {
a : [1,2,3],
b : 4,
c : [5,6],
d : { e : [7,8], f : 9 },
};
var leaves = traverse(obj).reduce(function (acc, x) {
if (this.isLeaf) acc.push(x);
return acc;
}, []);
console.dir(leaves);
var traverse = require('traverse');
var obj = [ 5, 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
traverse(obj).forEach(function (x) {
if (x < 0) this.update(x + 128);
});
console.dir(obj);
// scrub out circular references
var traverse = require('traverse');
var obj = { a : 1, b : 2, c : [ 3, 4 ] };
obj.c.push(obj);
var scrubbed = traverse(obj).map(function (x) {
if (this.circular) this.remove()
});
console.dir(scrubbed);
#!/usr/bin/env node
var traverse = require('traverse');
var obj = [ 'five', 6, -3, [ 7, 8, -2, 1 ], { f : 10, g : -13 } ];
var s = '';
traverse(obj).forEach(function to_s (node) {
if (Array.isArray(node)) {
this.before(function () { s += '[' });
this.post(function (child) {
if (!child.isLast) s += ',';
});
this.after(function () { s += ']' });
}
else if (typeof node == 'object') {
this.before(function () { s += '{' });
this.pre(function (x, key) {
to_s(key);
s += ':';
});
this.post(function (child) {
if (!child.isLast) s += ',';
});
this.after(function () { s += '}' });
}
else if (typeof node == 'string') {
s += '"' + node.toString().replace(/"/g, '\\"') + '"';
}
else if (typeof node == 'function') {
s += 'null';
}
else {
s += node.toString();
}
});
console.log('JSON.stringify: ' + JSON.stringify(obj));
console.log('this stringify: ' + s);
var traverse = module.exports = function (obj) {
return new Traverse(obj);
};
function Traverse (obj) {
this.value = obj;
}
Traverse.prototype.get = function (ps) {
var node = this.value;
for (var i = 0; i < ps.length; i ++) {
var key = ps[i];
if (!node || !hasOwnProperty.call(node, key)) {
node = undefined;
break;
}
node = node[key];
}
return node;
};
Traverse.prototype.has = function (ps) {
var node = this.value;
for (var i = 0; i < ps.length; i ++) {
var key = ps[i];
if (!node || !hasOwnProperty.call(node, key)) {
return false;
}
node = node[key];
}
return true;
};
Traverse.prototype.set = function (ps, value) {
var node = this.value;
for (var i = 0; i < ps.length - 1; i ++) {
var key = ps[i];
if (!hasOwnProperty.call(node, key)) node[key] = {};
node = node[key];
}
node[ps[i]] = value;
return value;
};
Traverse.prototype.map = function (cb) {
return walk(this.value, cb, true);
};
Traverse.prototype.forEach = function (cb) {
this.value = walk(this.value, cb, false);
return this.value;
};
Traverse.prototype.reduce = function (cb, init) {
var skip = arguments.length === 1;
var acc = skip ? this.value : init;
this.forEach(function (x) {
if (!this.isRoot || !skip) {
acc = cb.call(this, acc, x);
}
});
return acc;
};
Traverse.prototype.paths = function () {
var acc = [];
this.forEach(function (x) {
acc.push(this.path);
});
return acc;
};
Traverse.prototype.nodes = function () {
var acc = [];
this.forEach(function (x) {
acc.push(this.node);
});
return acc;
};
Traverse.prototype.clone = function () {
var parents = [], nodes = [];
return (function clone (src) {
for (var i = 0; i < parents.length; i++) {
if (parents[i] === src) {
return nodes[i];
}
}
if (typeof src === 'object' && src !== null) {
var dst = copy(src);
parents.push(src);
nodes.push(dst);
forEach(objectKeys(src), function (key) {
dst[key] = clone(src[key]);
});
parents.pop();
nodes.pop();
return dst;
}
else {
return src;
}
})(this.value);
};
function walk (root, cb, immutable) {
var path = [];
var parents = [];
var alive = true;
return (function walker (node_) {
var node = immutable ? copy(node_) : node_;
var modifiers = {};
var keepGoing = true;
var state = {
node : node,
node_ : node_,
path : [].concat(path),
parent : parents[parents.length - 1],
parents : parents,
key : path.slice(-1)[0],
isRoot : path.length === 0,
level : path.length,
circular : null,
update : function (x, stopHere) {
if (!state.isRoot) {
state.parent.node[state.key] = x;
}
state.node = x;
if (stopHere) keepGoing = false;
},
'delete' : function (stopHere) {
delete state.parent.node[state.key];
if (stopHere) keepGoing = false;
},
remove : function (stopHere) {
if (isArray(state.parent.node)) {
state.parent.node.splice(state.key, 1);
}
else {
delete state.parent.node[state.key];
}
if (stopHere) keepGoing = false;
},
keys : null,
before : function (f) { modifiers.before = f },
after : function (f) { modifiers.after = f },
pre : function (f) { modifiers.pre = f },
post : function (f) { modifiers.post = f },
stop : function () { alive = false },
block : function () { keepGoing = false }
};
if (!alive) return state;
function updateState() {
if (typeof state.node === 'object' && state.node !== null) {
if (!state.keys || state.node_ !== state.node) {
state.keys = objectKeys(state.node)
}
state.isLeaf = state.keys.length == 0;
for (var i = 0; i < parents.length; i++) {
if (parents[i].node_ === node_) {
state.circular = parents[i];
break;
}
}
}
else {
state.isLeaf = true;
state.keys = null;
}
state.notLeaf = !state.isLeaf;
state.notRoot = !state.isRoot;
}
updateState();
// use return values to update if defined
var ret = cb.call(state, state.node);
if (ret !== undefined && state.update) state.update(ret);
if (modifiers.before) modifiers.before.call(state, state.node);
if (!keepGoing) return state;
if (typeof state.node == 'object'
&& state.node !== null && !state.circular) {
parents.push(state);
updateState();
forEach(state.keys, function (key, i) {
path.push(key);
if (modifiers.pre) modifiers.pre.call(state, state.node[key], key);
var child = walker(state.node[key]);
if (immutable && hasOwnProperty.call(state.node, key)) {
state.node[key] = child.node;
}
child.isLast = i == state.keys.length - 1;
child.isFirst = i == 0;
if (modifiers.post) modifiers.post.call(state, child);
path.pop();
});
parents.pop();
}
if (modifiers.after) modifiers.after.call(state, state.node);
return state;
})(root).node;
}
function copy (src) {
if (typeof src === 'object' && src !== null) {
var dst;
if (isArray(src)) {
dst = [];
}
else if (isDate(src)) {
dst = new Date(src.getTime ? src.getTime() : src);
}
else if (isRegExp(src)) {
dst = new RegExp(src);
}
else if (isError(src)) {
dst = { message: src.message };
}
else if (isBoolean(src)) {
dst = new Boolean(src);
}
else if (isNumber(src)) {
dst = new Number(src);
}
else if (isString(src)) {
dst = new String(src);
}
else if (Object.create && Object.getPrototypeOf) {
dst = Object.create(Object.getPrototypeOf(src));
}
else if (src.constructor === Object) {
dst = {};
}
else {
var proto =
(src.constructor && src.constructor.prototype)
|| src.__proto__
|| {}
;
var T = function () {};
T.prototype = proto;
dst = new T;
}
forEach(objectKeys(src), function (key) {
dst[key] = src[key];
});
return dst;
}
else return src;
}
var objectKeys = Object.keys || function keys (obj) {
var res = [];
for (var key in obj) res.push(key)
return res;
};
function toS (obj) { return Object.prototype.toString.call(obj) }
function isDate (obj) { return toS(obj) === '[object Date]' }
function isRegExp (obj) { return toS(obj) === '[object RegExp]' }
function isError (obj) { return toS(obj) === '[object Error]' }
function isBoolean (obj) { return toS(obj) === '[object Boolean]' }
function isNumber (obj) { return toS(obj) === '[object Number]' }
function isString (obj) { return toS(obj) === '[object String]' }
var isArray = Array.isArray || function isArray (xs) {
return Object.prototype.toString.call(xs) === '[object Array]';
};
var forEach = function (xs, fn) {
if (xs.forEach) return xs.forEach(fn)
else for (var i = 0; i < xs.length; i++) {
fn(xs[i], i, xs);
}
};
forEach(objectKeys(Traverse.prototype), function (key) {
traverse[key] = function (obj) {
var args = [].slice.call(arguments, 1);
var t = new Traverse(obj);
return t[key].apply(t, args);
};
});
var hasOwnProperty = Object.hasOwnProperty || function (obj, key) {
return key in obj;
};
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
No preview for this file type
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.