Name: js-handler/node_modules/nodeunit/node_modules/tap/node_modules/yamlish/yamlish.js 
1:
exports.encode = encode
2:
exports.decode = decode
3:
 
4:
var seen = []
5:
function encode (obj, indent) {
6:
  var deep = arguments[2]
7:
  if (!indent) indent = "  "
8:
 
9:
  if (obj instanceof String ||
10:
      Object.prototype.toString.call(obj) === "[object String]") {
11:
    obj = obj.toString()
12:
  }
13:
 
14:
  if (obj instanceof Number ||
15:
      Object.prototype.toString.call(obj) === "[object Number]") {
16:
    obj = obj.valueOf()
17:
  }
18:
 
19:
  // take out the easy ones.
20:
  switch (typeof obj) {
21:
    case "string":
22:
      obj = obj.trim()
23:
      if (obj.indexOf("\n") !== -1) {
24:
        return "|\n" + indent + obj.split(/\r?\n/).join("\n"+indent)
25:
      } else {
26:
        return (obj)
27:
      }
28:
 
29:
    case "number":
30:
      return obj.toString(10)
31:
 
32:
    case "function":
33:
      return encode(obj.toString(), indent, true)
34:
 
35:
    case "boolean":
36:
      return obj.toString()
37:
 
38:
    case "undefined":
39:
      // fallthrough
40:
    case "object":
41:
      // at this point we know it types as an object
42:
      if (!obj) return "~"
43:
 
44:
      if (obj instanceof Date ||
45:
          Object.prototype.toString.call(obj) === "[object Date]") {
46:
        return JSON.stringify("[Date " + obj.toISOString() + "]")
47:
      }
48:
 
49:
      if (obj instanceof RegExp ||
50:
          Object.prototype.toString.call(obj) === "[object RegExp]") {
51:
        return JSON.stringify(obj.toString())
52:
      }
53:
 
54:
      if (obj instanceof Boolean ||
55:
          Object.prototype.toString.call(obj) === "[object Boolean]") {
56:
        return obj.toString()
57:
      }
58:
 
59:
      if (seen.indexOf(obj) !== -1) {
60:
        return "[Circular]"
61:
      }
62:
      seen.push(obj)
63:
 
64:
      if (typeof Buffer === "function" &&
65:
          typeof Buffer.isBuffer === "function" &&
66:
          Buffer.isBuffer(obj)) return obj.inspect()
67:
 
68:
      if (obj instanceof Error) {
69:
        var o = { name: obj.name
70:
                , message: obj.message
71:
                , type: obj.type }
72:
 
73:
        if (obj.code) o.code = obj.code
74:
        if (obj.errno) o.errno = obj.errno
75:
        if (obj.type) o.type = obj.type
76:
        obj = o
77:
      }
78:
 
79:
      var out = ""
80:
 
81:
      if (Array.isArray(obj)) {
82:
        var out = "\n" + indent + "- " +obj.map(function (item) {
83:
          return encode(item, indent + "  ", true)
84:
        }).join("\n"+indent + "- ")
85:
        break
86:
      }
87:
 
88:
      // an actual object
89:
      var keys = Object.keys(obj)
90:
        , niceKeys = keys.map(function (k) {
91:
            return (k.match(/^[a-zA-Z0-9_]+$/) ? k : JSON.stringify(k)) + ": "
92:
          })
93:
      //console.error(keys, niceKeys, obj)
94:
      var maxLength = Math.max.apply(Math, niceKeys.map(function (k) {
95:
            return k.length
96:
          }).concat(0))
97:
      //console.error(niceKeys, maxLength)
98:
 
99:
      var spaces = new Array(maxLength + 1).join(" ")
100:
 
101:
      if (!deep) indent += "  "
102:
      out = "\n" + indent + keys.map(function (k, i) {
103:
        var niceKey = niceKeys[i]
104:
        return niceKey + spaces.substr(niceKey.length)
105:
                       + encode(obj[k], indent + "  ", true)
106:
      }).join("\n" + indent)
107:
      break
108:
 
109:
    default: return ""
110:
  }
111:
  if (!deep) seen.length = 0
112:
  return out
113:
}
114:
 
115:
function decode (str) {
116:
  var v = str.trim()
117:
    , d
118:
    , dateRe = /^\[Date ([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}(?::[0-9]{2})?(?:\.[0-9]{3})?(?:[A-Z]+)?)\]$/
119:
 
120:
  if (v === "~") return null
121:
 
122:
  try {
123:
    var jp = JSON.parse(str)
124:
  } catch (e) {
125:
    var jp = ""
126:
  }
127:
 
128:
  if (jp &&
129:
      typeof jp === "string" &&
130:
      (d = jp.match(dateRe)) &&
131:
      (d = Date.parse(d[1]))) {
132:
    return new Date(d)
133:
  }
134:
 
135:
  if (typeof jp === "boolean") return jp
136:
  if (v && !isNaN(v)) return parseInt(v, 10)
137:
 
138:
  // something interesting.
139:
  var lines = str.split(/\r?\n/)
140:
  // check if it's some kind of string or something.
141:
  // if the first line is > or | then it's a wrapping indented string.
142:
  // if the first line is blank, and there are many lines,
143:
  // then it's an array or object.
144:
  // otherwise, it's just ""
145:
  var first = lines.shift().trim()
146:
  if (lines.length) lines = undent(lines)
147:
  switch (first) {
148:
    case "|":
149:
      return lines.join("\n")
150:
    case ">":
151:
      return lines.join("\n").split(/\n{2,}/).map(function (l) {
152:
        return l.split(/\n/).join(" ")
153:
      }).join("\n")
154:
    default:
155:
      if (!lines.length) return first
156:
      // array or object.
157:
      // the first line will be either "- value" or "key: value"
158:
      return lines[0].charAt(0) === "-" ? decodeArr(lines) : decodeObj(lines)
159:
  }
160:
}
161:
 
162:
function decodeArr (lines) {
163:
  var out = []
164:
    , key = 0
165:
    , val = []
166:
  for (var i = 0, l = lines.length; i < l; i ++) {
167:
    // if it starts with a -, then it's a new thing
168:
    var line = lines[i]
169:
    if (line.charAt(0) === "-") {
170:
      if (val.length) {
171:
        out[key ++] = decode(val.join("\n"))
172:
        val.length = 0
173:
      }
174:
      val.push(line.substr(1).trim())
175:
    } else if (line.charAt(0) === " ") {
176:
      val.push(line)
177:
    } else return []
178:
  }
179:
  if (val.length) {
180:
    out[key ++] = decode(val.join("\n"))
181:
  }
182:
  return out
183:
}
184:
 
185:
function decodeObj (lines) {
186:
  var out = {}
187:
    , val = []
188:
    , key = null
189:
 
190:
  for (var i = 0, l = lines.length; i < l; i ++) {
191:
    var line = lines[i]
192:
    if (line.charAt(0) === " ") {
193:
      val.push(line)
194:
      continue
195:
    }
196:
    // some key:val
197:
    if (val.length) {
198:
      out[key] = decode(val.join("\n"))
199:
      val.length = 0
200:
    }
201:
    // parse out the quoted key
202:
    var first
203:
    if (line.charAt(0) === "\"") {
204:
      for (var ii = 1, ll = line.length, esc = false; ii < ll; ii ++) {
205:
        var c = line.charAt(ii)
206:
        if (c === "\\") {
207:
          esc = !esc
208:
        } else if (c === "\"" && !esc) {
209:
          break
210:
        }
211:
      }
212:
      key = JSON.parse(line.substr(0, ii + 1))
213:
      line = line.substr(ii + 1)
214:
      first = line.substr(line.indexOf(":") + 1).trim()
215:
    } else {
216:
      var kv = line.split(":")
217:
      key = kv.shift()
218:
      first = kv.join(":").trim()
219:
    }
220:
    // now we've set a key, and "first" has the first line of the value.
221:
    val.push(first.trim())
222:
  }
223:
  if (val.length) out[key] = decode(val.join("\n"))
224:
  return out
225:
}
226:
 
227:
function undent (lines) {
228:
  var i = lines[0].match(/^\s*/)[0].length
229:
  return lines.map(function (line) {
230:
    return line.substr(i)
231:
  })
232:
}
233:
 
234:
 
235:
// XXX Turn this into proper tests.
236:
if (require.main === module) {
237:
var obj = [{"bigstring":new Error().stack}
238:
          ,{ar:[{list:"of"},{some:"objects"}]}
239:
          ,{date:new Date()}
240:
          ,{"super huge string":new Error().stack}
241:
          ]
242:
 
243:
Date.prototype.toJSON = function (k, val) {
244:
  console.error(k, val, this)
245:
  return this.toISOString() + " (it's a date)"
246:
}
247:
 
248:
var enc = encode(obj)
249:
  , dec = decode(enc)
250:
  , encDec = encode(dec)
251:
 
252:
console.error(JSON.stringify({ obj : obj
253:
                             , enc : enc.split(/\n/)
254:
                             , dec : dec }, null, 2), encDec === enc)
255:
 
256:
var num = 100
257:
  , encNum = encode(num)
258:
  , decEncNum = decode(encNum)
259:
console.error([num, encNum, decEncNum])
260:
}