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
 |