UNPKG

j2j

Version:
336 lines (276 loc) 9.54 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>JSDoc: Source: j2j.js</title> <script src="scripts/prettify/prettify.js"> </script> <script src="scripts/prettify/lang-css.js"> </script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css"> <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css"> </head> <body> <div id="main"> <h1 class="page-title">Source: j2j.js</h1> <section> <article> <pre class="prettyprint source linenums"><code>#!/usr/bin/env node /** * @file Attempts to convert your JavaScript to JSON. * @author Christopher Hiller &lt;chiller@badwing.com> * @copyright 2014 Christopher Hiller * @license MIT */ /** * @module j2j * @description Attempts to convert your JavaScript to JSON. */ 'use strict'; var defaults = require('defaults'), /** * @description Default # of spaces to indent JSON output * @constant * @private * @type {string} */ DEFAULT_INDENT = 2, /** * @description Whether to turn off colors by default. * @private * @type {boolean} */ DEFAULT_NOCOLOR = true, /** * @description Enable debug by default? * @constant * @private * @type {boolean} */ DEFAULT_DEBUG = false, /** * @description Line #'s in output? * @constant * @private * @type {boolean} */ DEFAULT_LINENOS = false, stringify = JSON.stringify; /** * @summary Attempts to parse a string into JSONable. * @description If you pass something like `"{foo: 'bar'}"` into `JSON.stringify()`, it will of course * return `"{foo: 'bar'}"` because you gave it a string. We need to give `JSON.stringify()` some actual * JavaScript. So we attempt to evaluate the string as JS within a sandbox. Because it's evaluated, * you can actually put expressions in it, call functions, etc., as long as everything is defined. * @param {String} s Raw string to evaluate * @param {(Object|Function)} opts See {@link module:j2j.options}. Callback if function. * @param {Function} [callback] Callback to call with results from evaluation, if you don't like Promises. * @alias module:j2j.parse * @returns {Promise} */ var parse = function parse(s, opts, callback) { var sandbox = new (require('sandbox'))(), Q = require('q'), dfrd = Q.defer(), fn = '(function() { console.log((' + s + ')); return typeof function() { return (' + s + ');}();})();'; opts = options(opts); opts.debug &amp;&amp; console.info('Executing:\n' + fn); // log the evaluated string, get the evaluated type, and trap them. sandbox.run(fn, function (info) { if (["'object'", "'string'", "'number'"].indexOf(info.result) > -1) { return dfrd.resolve(info.console[0]); } opts.debug &amp;&amp; console.info('Sandbox output: \n' + stringify(info, null, parseInt(opts.indent, 10))); return dfrd.reject('input evaluated to ' + info.result + ', which is no good.'); }); return dfrd.promise .nodeify(typeof opts === 'function' ? opts : callback); }; /** * @summary Given a JS variable, stringify it, with optional color * @description This function is synchronous. * @param {(Object|Array|string|number)} o Thing to stringify and output. * @param {Object} [opts] Options. See {@link module:j2j.options} * @alias module:j2j.output * @returns {string} */ var output = function output(o, opts) { var out; opts = options(opts); out = stringify(o, null, parseInt(opts.indent, 10)); if (process.stdout.isTTY &amp;&amp; !opts['no-color'] &amp;&amp; !opts.output) { out = require('cardinal').highlight(out, { json: true, linenos: opts['line-nos'] }); } return out; }; /** * @description Merge options object with default options. * @param {(Object|Function)} [opts] Options! If function, ignored. * @param {boolean} [opts.debug=false] Debug mode? * @param {number} [opts.indent=2] How many spaces to indent JSON output * @param {boolean} [opts.no-color] No colors? Even a little? `false` in programmatic usage; `true` otherwise. * @param {boolean} [opts.line-nos] Display line numbers? * @returns {Object} * @alias module:j2j.options */ var options = function options(opts) { opts = typeof opts === 'function' ? {} : opts; return defaults(opts, { debug: DEFAULT_DEBUG, indent: DEFAULT_INDENT, 'no-color': DEFAULT_NOCOLOR, 'line-nos': DEFAULT_LINENOS }); }; /** * @summary Parses and generates output from a string, then writes the output somewhere. * @description Used by CLI. Exits with nonzero code if error and `callback` is NOT specified. * @param {string} input String to parse * @param {(Object|Function)} [opts] See {@link module:j2j.options}. Callback if function. * @param {Function} [callback] Optional callback if you don't want to use Promises. * @see module:j2j * @alias module:j2j.write * @returns {Promise} */ var write = function write(input, opts, callback) { return require('q')(function (input, opts) { opts = options(opts); return parse(input, opts) .then(function (s) { return output(s, opts); }, function (err) { if (opts.debug) { !opts['no-color'] &amp;&amp; require('ttycolor').defaults(); console.error(err); } throw new Error('cannot coerce input into anything JSON.stringify() can handle'); }) .then(function (out) { if (opts.output) { return require('graceful-fs').writeFileSync(opts.output, out); } process.stdout.write(out); }, function (err) { require('ttycolor').defaults(); console.error(err); !callback &amp;&amp; process.exit(1); }); }(input, opts)) .nodeify(typeof opts === 'function' ? opts : callback); }; /** * @summary Parses and generates output from a string. Fulfills with output. * @description For programmatic use. If for some reason you pass it a non-string, * it will just give you output, which is a shortcut for `JSON.stringify()`. * @param {string} input String to parse * @param {Object} [opts] See {@link module:j2j.options} * @param {Function} [callback] Optional callback if you don't want to use Promises. * @see module:j2j.write * @alias module:j2j * @returns {Promise} * @example * var j2j = require('j2j'); * * j2j("{foo: 'bar', baz: 2}", {indent: false}) * .then(function(output) { * expect(output).to.equal('{"foo":"bar","baz":2}'); * }); */ var j2j = function j2j(input, opts, callback) { var Q = require('q'); return Q(function (input, opts) { if (!input) { throw new Error('input parameter cannot be empty'); } opts = options(opts); if (typeof input === 'string') { return output(input, opts); } return parse(input, opts) .then(function (o) { return output(o, opts); }); }(input, opts)) .nodeify(typeof opts === 'function' ? opts : callback); }; j2j.parse = parse; j2j.output = output; j2j.write = write; j2j.options = options; var main = function main() { var input, stdin, chunks = [], version = require(require('path').join(__dirname, 'package.json')).version, argv = require('yargs') .usage('Convert JavaScript to JSON.\nUsage: j2j ["&lt;JavaScript>"] [options]') .example('echo "{foo: \'bar\'}" | j2j -i 0', 'Stringify JS object w/o indentation to STDOUT') .example('j2j "{foo: \'bar\'}" -i 0', 'Equivalent to above') .example('j2j "{foo: 2+2}"', 'Evaluate, stringify, indent &amp; output to STDOUT') .example('j2j -f bar.js -o bar.json', 'Parse JS file &amp; output to bar.json. Good luck!') .describe('f', 'Read file for input') .alias('f', 'file') .describe('o', 'Output file; if not specified, STDOUT is used') .alias('o', 'output') .describe('C', 'Do not output color') .alias('C', 'no-color') .default('C', false) .boolean('C') .describe('i', 'Indentation (0 for none)') .default('i', DEFAULT_INDENT) .alias('i', 'indent') .describe('l', 'Display line numbers') .boolean('l') .default('l', false) .alias('l', 'line-nos') .describe('debug', 'Debug mode') .boolean('debug') .default('debug', false) .help('h') .alias('h', 'help') .version(version, 'v') .alias('v', 'version') .argv; input = argv.file ? require('graceful-fs').readFileSync(argv.file) : argv._[0]; // nocolor will be false in CLI mode argv = defaults(argv, { 'no-color': false }); if (!input) { stdin = process.stdin; stdin.resume(); stdin.setEncoding('utf8'); stdin.on('data', function (chunk) { chunks.push(chunk); }); stdin.on('end', function () { write(chunks.join(), argv); }); } else { write(input, argv); } }; require.main === module &amp;&amp; main(); module.exports = j2j; </code></pre> </article> </section> </div> <nav> <h2><a href="index.html">Index</a></h2><h3>Modules</h3><ul><li><a href="module-j2j.html">j2j</a></li></ul> </nav> <br clear="both"> <footer> Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.3.0-alpha9</a> on Sun Sep 07 2014 10:49:15 GMT-0700 (PDT) </footer> <script> prettyPrint(); </script> <script src="scripts/linenumber.js"> </script> </body> </html>