UNPKG

4 kBJavaScriptView Raw
1#! /usr/bin/env node
2
3var Parser = require('jsonparse')
4 , through = require('through')
5
6/*
7
8 the value of this.stack that creationix's jsonparse has is weird.
9
10 it makes this code ugly, but his problem is way harder that mine,
11 so i'll forgive him.
12
13*/
14
15exports.parse = function (path, map) {
16
17 var parser = new Parser()
18 var stream = through(function (chunk) {
19 if('string' === typeof chunk)
20 chunk = new Buffer(chunk)
21 parser.write(chunk)
22 },
23 function (data) {
24 if(data)
25 stream.write(data)
26 stream.queue(null)
27 })
28
29 if('string' === typeof path)
30 path = path.split('.').map(function (e) {
31 if (e === '*')
32 return true
33 else if (e === '') // '..'.split('.') returns an empty string
34 return {recurse: true}
35 else
36 return e
37 })
38
39
40 var count = 0, _key
41 if(!path || !path.length)
42 path = null
43
44 parser.onValue = function () {
45 if (!this.root && this.stack.length == 1)
46 stream.root = this.value
47
48 if(! path) return
49
50 var i = 0 // iterates on path
51 var j = 0 // iterates on stack
52 while (i < path.length) {
53 var key = path[i]
54 var c
55 j++
56
57 if (key && !key.recurse) {
58 c = (j === this.stack.length) ? this : this.stack[j]
59 if (!c) return
60 if (! check(key, c.key)) return
61 i++
62 } else {
63 i++
64 var nextKey = path[i]
65 if (! nextKey) return
66 while (true) {
67 c = (j === this.stack.length) ? this : this.stack[j]
68 if (!c) return
69 if (check(nextKey, c.key)) { i++; break}
70 j++
71 }
72 }
73 }
74 if (j !== this.stack.length) return
75
76 count ++
77 var data = this.value[this.key]
78 if(null != data)
79 if(null != (data = map ? map(data) : data))
80 stream.queue(data)
81 delete this.value[this.key]
82 }
83 parser._onToken = parser.onToken;
84
85 parser.onToken = function (token, value) {
86 parser._onToken(token, value);
87 if (this.stack.length === 0) {
88 if (stream.root) {
89 if(!path)
90 stream.queue(stream.root)
91 stream.emit('root', stream.root, count)
92 count = 0;
93 stream.root = null;
94 }
95 }
96 }
97
98 parser.onError = function (err) {
99 stream.emit('error', err)
100 }
101
102
103 return stream
104}
105
106function check (x, y) {
107 if ('string' === typeof x)
108 return y == x
109 else if (x && 'function' === typeof x.exec)
110 return x.exec(y)
111 else if ('boolean' === typeof x)
112 return x
113 else if ('function' === typeof x)
114 return x(y)
115 return false
116}
117
118exports.stringify = function (op, sep, cl, indent) {
119 indent = indent || 0
120 if (op === false){
121 op = ''
122 sep = '\n'
123 cl = ''
124 } else if (op == null) {
125
126 op = '[\n'
127 sep = '\n,\n'
128 cl = '\n]\n'
129
130 }
131
132 //else, what ever you like
133
134 var stream
135 , first = true
136 , anyData = false
137 stream = through(function (data) {
138 anyData = true
139 var json = JSON.stringify(data, null, indent)
140 if(first) { first = false ; stream.queue(op + json)}
141 else stream.queue(sep + json)
142 },
143 function (data) {
144 if(!anyData)
145 stream.queue(op)
146 stream.queue(cl)
147 stream.queue(null)
148 })
149
150 return stream
151}
152
153exports.stringifyObject = function (op, sep, cl, indent) {
154 indent = indent || 0
155 if (op === false){
156 op = ''
157 sep = '\n'
158 cl = ''
159 } else if (op == null) {
160
161 op = '{\n'
162 sep = '\n,\n'
163 cl = '\n}\n'
164
165 }
166
167 //else, what ever you like
168
169 var first = true
170 , anyData = false
171 stream = through(function (data) {
172 anyData = true
173 var json = JSON.stringify(data[0]) + ':' + JSON.stringify(data[1], null, indent)
174 if(first) { first = false ; this.queue(op + json)}
175 else this.queue(sep + json)
176 },
177 function (data) {
178 if(!anyData) this.queue(op)
179 this.queue(cl)
180
181 this.queue(null)
182 })
183
184 return stream
185}
186
187if(!module.parent && process.title !== 'browser') {
188 process.stdin
189 .pipe(exports.parse(process.argv[2]))
190 .pipe(exports.stringify('[', ',\n', ']\n', 2))
191 .pipe(process.stdout)
192}