Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80522 views
1
#! /usr/bin/env node
2
3
var 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
15
exports.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 (value) {
45
if (!this.root)
46
stream.root = 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)) {
70
i++;
71
this.stack[j].value = null
72
break
73
}
74
j++
75
}
76
}
77
78
}
79
if (j !== this.stack.length) return
80
81
count ++
82
var actualPath = this.stack.slice(1).map(function(element) { return element.key }).concat([this.key])
83
var data = this.value[this.key]
84
if(null != data)
85
if(null != (data = map ? map(data, actualPath) : data))
86
stream.queue(data)
87
delete this.value[this.key]
88
for(var k in this.stack)
89
this.stack[k].value = null
90
}
91
parser._onToken = parser.onToken;
92
93
parser.onToken = function (token, value) {
94
parser._onToken(token, value);
95
if (this.stack.length === 0) {
96
if (stream.root) {
97
if(!path)
98
stream.queue(stream.root)
99
count = 0;
100
stream.root = null;
101
}
102
}
103
}
104
105
parser.onError = function (err) {
106
if(err.message.indexOf("at position") > -1)
107
err.message = "Invalid JSON (" + err.message + ")";
108
stream.emit('error', err)
109
}
110
111
112
return stream
113
}
114
115
function check (x, y) {
116
if ('string' === typeof x)
117
return y == x
118
else if (x && 'function' === typeof x.exec)
119
return x.exec(y)
120
else if ('boolean' === typeof x)
121
return x
122
else if ('function' === typeof x)
123
return x(y)
124
return false
125
}
126
127
exports.stringify = function (op, sep, cl, indent) {
128
indent = indent || 0
129
if (op === false){
130
op = ''
131
sep = '\n'
132
cl = ''
133
} else if (op == null) {
134
135
op = '[\n'
136
sep = '\n,\n'
137
cl = '\n]\n'
138
139
}
140
141
//else, what ever you like
142
143
var stream
144
, first = true
145
, anyData = false
146
stream = through(function (data) {
147
anyData = true
148
var json = JSON.stringify(data, null, indent)
149
if(first) { first = false ; stream.queue(op + json)}
150
else stream.queue(sep + json)
151
},
152
function (data) {
153
if(!anyData)
154
stream.queue(op)
155
stream.queue(cl)
156
stream.queue(null)
157
})
158
159
return stream
160
}
161
162
exports.stringifyObject = function (op, sep, cl, indent) {
163
indent = indent || 0
164
if (op === false){
165
op = ''
166
sep = '\n'
167
cl = ''
168
} else if (op == null) {
169
170
op = '{\n'
171
sep = '\n,\n'
172
cl = '\n}\n'
173
174
}
175
176
//else, what ever you like
177
178
var first = true
179
, anyData = false
180
stream = through(function (data) {
181
anyData = true
182
var json = JSON.stringify(data[0]) + ':' + JSON.stringify(data[1], null, indent)
183
if(first) { first = false ; this.queue(op + json)}
184
else this.queue(sep + json)
185
},
186
function (data) {
187
if(!anyData) this.queue(op)
188
this.queue(cl)
189
190
this.queue(null)
191
})
192
193
return stream
194
}
195
196
if(!module.parent && process.title !== 'browser') {
197
process.stdin
198
.pipe(exports.parse(process.argv[2]))
199
.pipe(exports.stringify('[', ',\n', ']\n', 2))
200
.pipe(process.stdout)
201
}
202
203