Skip to content

Commit 61ce8f0

Browse files
committed
Evaluate multiple functions.
1 parent 16db6e7 commit 61ce8f0

File tree

2 files changed

+106
-25
lines changed

2 files changed

+106
-25
lines changed

index.js

Lines changed: 71 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,89 @@
22

33
function build (schema) {
44
/*eslint no-new-func: "off"*/
5-
6-
let code = `
5+
var code = `
76
'use strict'
8-
let json = '{'
7+
8+
${$asString.toString()}
9+
${$asNumber.toString()}
10+
`
11+
var main
12+
13+
switch (schema.type) {
14+
case 'object':
15+
main = '$main'
16+
code = buildObject(schema, code, main)
17+
break
18+
case 'string':
19+
main = $asString.name
20+
break
21+
case 'integer':
22+
case 'number':
23+
main = $asNumber.name
24+
break
25+
default:
26+
throw new Error(`${schema.type} unsupported`)
27+
}
28+
29+
code += `
30+
;
31+
return ${main}
32+
`
33+
34+
return (new Function(code))()
35+
}
36+
37+
function $asNumber (i) {
38+
var num = Number(i)
39+
if (isNaN(num)) {
40+
return 'null'
41+
} else {
42+
return '' + i
43+
}
44+
}
45+
46+
function $asString (s) {
47+
var str = s.toString()
48+
var result = ''
49+
var last = 0
50+
var l = str.length
51+
for (var i = 0; i < l; i++) {
52+
if (str[i] === '"') {
53+
result += str.slice(last, i) + '\\"'
54+
last = i + 1
55+
}
56+
}
57+
if (last === 0) {
58+
result = str
59+
} else {
60+
result += str.slice(last)
61+
}
62+
return '"' + result + '"'
63+
}
64+
65+
function buildObject (schema, code, name) {
66+
code += `
67+
function ${name} (obj) {
68+
var json = '{'
969
`
1070

1171
Object.keys(schema.properties).forEach((key, i, a) => {
1272
const type = schema.properties[key].type
1373

1474
code += `
15-
json += '"${key}":'
75+
json += '${$asString(key)}:'
1676
`
1777

1878
switch (type) {
1979
case 'string':
2080
code += `
21-
json += '"' + obj.${key} + '"'
81+
json += $asString(obj.${key})
2282
`
2383
break
84+
case 'number':
2485
case 'integer':
2586
code += `
26-
json += '' + obj.${key}
87+
json += $asNumber(obj.${key})
2788
`
2889
break
2990
default:
@@ -36,11 +97,12 @@ function build (schema) {
3697
})
3798

3899
code += `
39-
json += '}'
40-
return json
100+
json += '}'
101+
return json
102+
}
41103
`
42104

43-
return new Function('obj', code)
105+
return code
44106
}
45107

46108
module.exports = build

test.js

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,20 @@
33
const test = require('tap').test
44
const build = require('.')
55

6-
const example = {
7-
'title': 'Example Schema',
6+
function buildTest (schema, toStringify) {
7+
test(`render a ${schema.title} as JSON`, (t) => {
8+
t.plan(2)
9+
10+
const stringify = build(schema)
11+
const output = stringify(toStringify)
12+
13+
t.deepEqual(JSON.parse(output), toStringify)
14+
t.equal(output, JSON.stringify(toStringify))
15+
})
16+
}
17+
18+
buildTest({
19+
'title': 'basic',
820
'type': 'object',
921
'properties': {
1022
'firstName': {
@@ -17,23 +29,30 @@ const example = {
1729
'description': 'Age in years',
1830
'type': 'integer',
1931
'minimum': 0
32+
},
33+
'magic': {
34+
'type': 'number'
2035
}
2136
},
2237
'required': ['firstName', 'lastName']
23-
}
24-
25-
test('render a basic json', (t) => {
26-
t.plan(2)
38+
}, {
39+
firstName: 'Matteo',
40+
lastName: 'Collina',
41+
age: 32,
42+
magic: 42.42
43+
})
2744

28-
const stringify = build(example)
29-
const obj = {
30-
firstName: 'Matteo',
31-
lastName: 'Collina',
32-
age: 32
33-
}
45+
buildTest({
46+
title: 'string',
47+
type: 'string'
48+
}, 'hello world')
3449

35-
const output = stringify(obj)
50+
buildTest({
51+
title: 'an integer',
52+
type: 'integer'
53+
}, 42)
3654

37-
t.deepEqual(JSON.parse(output), obj)
38-
t.equal(output, JSON.stringify(obj))
39-
})
55+
buildTest({
56+
title: 'a number',
57+
type: 'number'
58+
}, 42.42)

0 commit comments

Comments
 (0)