var util = require('util') var isProperty = require('is-property') var INDENT_START = /[\{\[]/ var INDENT_END = /[\}\]]/ // from https://mathiasbynens.be/notes/reserved-keywords var RESERVED = [ 'do', 'if', 'in', 'for', 'let', 'new', 'try', 'var', 'case', 'else', 'enum', 'eval', 'null', 'this', 'true', 'void', 'with', 'await', 'break', 'catch', 'class', 'const', 'false', 'super', 'throw', 'while', 'yield', 'delete', 'export', 'import', 'public', 'return', 'static', 'switch', 'typeof', 'default', 'extends', 'finally', 'package', 'private', 'continue', 'debugger', 'function', 'arguments', 'interface', 'protected', 'implements', 'instanceof', 'NaN', 'undefined' ] var RESERVED_MAP = {} for (var i = 0; i < RESERVED.length; i++) { RESERVED_MAP[RESERVED[i]] = true } var isVariable = function (name) { return isProperty(name) && !RESERVED_MAP.hasOwnProperty(name) } var formats = { s: function(s) { return '' + s }, d: function(d) { return '' + Number(d) }, o: function(o) { return JSON.stringify(o) } } var genfun = function() { var lines = [] var indent = 0 var vars = {} var push = function(str) { var spaces = '' while (spaces.length < indent*2) spaces += ' ' lines.push(spaces+str) } var pushLine = function(line) { if (INDENT_END.test(line.trim()[0]) && INDENT_START.test(line[line.length-1])) { indent-- push(line) indent++ return } if (INDENT_START.test(line[line.length-1])) { push(line) indent++ return } if (INDENT_END.test(line.trim()[0])) { indent-- push(line) return } push(line) } var line = function(fmt) { if (!fmt) return line if (arguments.length === 1 && fmt.indexOf('\n') > -1) { var lines = fmt.trim().split('\n') for (var i = 0; i < lines.length; i++) { pushLine(lines[i].trim()) } } else { pushLine(util.format.apply(util, arguments)) } return line } line.scope = {} line.formats = formats line.sym = function(name) { if (!name || !isVariable(name)) name = 'tmp' if (!vars[name]) vars[name] = 0 return name + (vars[name]++ || '') } line.property = function(obj, name) { if (arguments.length === 1) { name = obj obj = '' } name = name + '' if (isProperty(name)) return (obj ? obj + '.' + name : name) return obj ? obj + '[' + JSON.stringify(name) + ']' : JSON.stringify(name) } line.toString = function() { return lines.join('\n') } line.toFunction = function(scope) { if (!scope) scope = {} var src = 'return ('+line.toString()+')' Object.keys(line.scope).forEach(function (key) { if (!scope[key]) scope[key] = line.scope[key] }) var keys = Object.keys(scope).map(function(key) { return key }) var vals = keys.map(function(key) { return scope[key] }) return Function.apply(null, keys.concat(src)).apply(null, vals) } if (arguments.length) line.apply(null, arguments) return line } genfun.formats = formats module.exports = genfun