index.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. var util = require('util')
  2. var isProperty = require('is-property')
  3. var INDENT_START = /[\{\[]/
  4. var INDENT_END = /[\}\]]/
  5. // from https://mathiasbynens.be/notes/reserved-keywords
  6. var RESERVED = [
  7. 'do',
  8. 'if',
  9. 'in',
  10. 'for',
  11. 'let',
  12. 'new',
  13. 'try',
  14. 'var',
  15. 'case',
  16. 'else',
  17. 'enum',
  18. 'eval',
  19. 'null',
  20. 'this',
  21. 'true',
  22. 'void',
  23. 'with',
  24. 'await',
  25. 'break',
  26. 'catch',
  27. 'class',
  28. 'const',
  29. 'false',
  30. 'super',
  31. 'throw',
  32. 'while',
  33. 'yield',
  34. 'delete',
  35. 'export',
  36. 'import',
  37. 'public',
  38. 'return',
  39. 'static',
  40. 'switch',
  41. 'typeof',
  42. 'default',
  43. 'extends',
  44. 'finally',
  45. 'package',
  46. 'private',
  47. 'continue',
  48. 'debugger',
  49. 'function',
  50. 'arguments',
  51. 'interface',
  52. 'protected',
  53. 'implements',
  54. 'instanceof',
  55. 'NaN',
  56. 'undefined'
  57. ]
  58. var RESERVED_MAP = {}
  59. for (var i = 0; i < RESERVED.length; i++) {
  60. RESERVED_MAP[RESERVED[i]] = true
  61. }
  62. var isVariable = function (name) {
  63. return isProperty(name) && !RESERVED_MAP.hasOwnProperty(name)
  64. }
  65. var formats = {
  66. s: function(s) {
  67. return '' + s
  68. },
  69. d: function(d) {
  70. return '' + Number(d)
  71. },
  72. o: function(o) {
  73. return JSON.stringify(o)
  74. }
  75. }
  76. var genfun = function() {
  77. var lines = []
  78. var indent = 0
  79. var vars = {}
  80. var push = function(str) {
  81. var spaces = ''
  82. while (spaces.length < indent*2) spaces += ' '
  83. lines.push(spaces+str)
  84. }
  85. var pushLine = function(line) {
  86. if (INDENT_END.test(line.trim()[0]) && INDENT_START.test(line[line.length-1])) {
  87. indent--
  88. push(line)
  89. indent++
  90. return
  91. }
  92. if (INDENT_START.test(line[line.length-1])) {
  93. push(line)
  94. indent++
  95. return
  96. }
  97. if (INDENT_END.test(line.trim()[0])) {
  98. indent--
  99. push(line)
  100. return
  101. }
  102. push(line)
  103. }
  104. var line = function(fmt) {
  105. if (!fmt) return line
  106. if (arguments.length === 1 && fmt.indexOf('\n') > -1) {
  107. var lines = fmt.trim().split('\n')
  108. for (var i = 0; i < lines.length; i++) {
  109. pushLine(lines[i].trim())
  110. }
  111. } else {
  112. pushLine(util.format.apply(util, arguments))
  113. }
  114. return line
  115. }
  116. line.scope = {}
  117. line.formats = formats
  118. line.sym = function(name) {
  119. if (!name || !isVariable(name)) name = 'tmp'
  120. if (!vars[name]) vars[name] = 0
  121. return name + (vars[name]++ || '')
  122. }
  123. line.property = function(obj, name) {
  124. if (arguments.length === 1) {
  125. name = obj
  126. obj = ''
  127. }
  128. name = name + ''
  129. if (isProperty(name)) return (obj ? obj + '.' + name : name)
  130. return obj ? obj + '[' + JSON.stringify(name) + ']' : JSON.stringify(name)
  131. }
  132. line.toString = function() {
  133. return lines.join('\n')
  134. }
  135. line.toFunction = function(scope) {
  136. if (!scope) scope = {}
  137. var src = 'return ('+line.toString()+')'
  138. Object.keys(line.scope).forEach(function (key) {
  139. if (!scope[key]) scope[key] = line.scope[key]
  140. })
  141. var keys = Object.keys(scope).map(function(key) {
  142. return key
  143. })
  144. var vals = keys.map(function(key) {
  145. return scope[key]
  146. })
  147. return Function.apply(null, keys.concat(src)).apply(null, vals)
  148. }
  149. if (arguments.length) line.apply(null, arguments)
  150. return line
  151. }
  152. genfun.formats = formats
  153. module.exports = genfun