182 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			182 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | 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 |