Print js code in errors; add @ map syntax

pull/291/head
Anton Medvedev 7 months ago
parent 6520c2c6b7
commit c699c8c992
No known key found for this signature in database

@ -48,9 +48,14 @@ const skip = Symbol('skip')
async function runTransforms(json, args, theme) { async function runTransforms(json, args, theme) {
const process = await import('node:process') const process = await import('node:process')
let i, code, output = json let i, code, jsCode, output = json
for ([i, code] of args.entries()) try { for ([i, code] of args.entries()) try {
output = await transform(output, code) jsCode = transpile(code)
const fn = `(function () {
const x = this
return ${jsCode}
})`
output = await run(output, fn)
} catch (err) { } catch (err) {
printErr(err) printErr(err)
process.exit(1) process.exit(1)
@ -73,52 +78,50 @@ async function runTransforms(json, args, theme) {
console.error( console.error(
`\n ${pre} ${code} ${post}\n` + `\n ${pre} ${code} ${post}\n` +
` ${' '.repeat(pre.length + 1)}${'^'.repeat(code.length)}\n` + ` ${' '.repeat(pre.length + 1)}${'^'.repeat(code.length)}\n` +
(jsCode !== code ? `\n${jsCode}\n` : ``) +
`\n${err.stack || err}`, `\n${err.stack || err}`,
) )
} }
} }
async function transform(json, code) { function transpile(code) {
if ('.' === code) if ('.' === code)
return json return 'x'
if (/^(\.\w*)+\[]/.test(code)) if (/^(\.\w*)+\[]/.test(code))
return eval(`(function () { return `(${fold(code.split('[]'))})(x)`
return (${fold(code.split('[]'))})(this)
})`).call(json)
function fold(s) { function fold(s) {
if (s.length === 1) if (s.length === 1)
return 'x => x' + s[0] return 'x => x' + s[0]
let obj = s.shift() let obj = s.shift()
obj = obj === '.' ? 'x' : 'x' + obj obj = obj === '.' ? 'x' : 'x' + obj
return `x => Object.values(${obj}).flatMap(${fold(s)})` return `x => ${obj}.flatMap(${fold(s)})`
} }
if (/^\.\[/.test(code)) if (/^\.\[/.test(code))
return eval(`(function () { return `x${code.substring(1)}`
const x = this
return this${code.substring(1)}
})`).call(json)
if (/^\./.test(code)) if (/^\./.test(code))
return eval(`(function () { return `x${code}`
const x = this
return this${code}
})`).call(json)
// deprecated
if (/^map\(.+?\)$/i.test(code)) { if (/^map\(.+?\)$/i.test(code)) {
let s = code.substring(4, code.length - 1) let s = code.substring(4, code.length - 1)
if (s[0] === '.') s = 'x' + s if (s[0] === '.') s = 'x' + s
return eval(`(function () { return `x.map((x, i) => apply(${s}, x, i))`
return this.map((x, i) => apply(${s}, x, i))
})`).call(json)
} }
const fn = eval(`(function () { if (/^@/.test(code)) {
const x = this const jsCode = transpile(code.substring(1))
return ${code} return `x.map((x, i) => apply(${jsCode}, x, i))`
})`).call(json) }
return code
}
async function run(json, code) {
const fn = eval(code).call(json)
return apply(fn, json) return apply(fn, json)

@ -139,6 +139,16 @@ void async function main() {
t.deepEqual(JSON.parse(stdout), [0, 2, 6]) t.deepEqual(JSON.parse(stdout), [0, 2, 6])
}) })
await test('transform - @ works', async t => {
const {stdout} = await run([1, 2, 3], `'@x * 2'`)
t.deepEqual(JSON.parse(stdout), [2, 4, 6])
})
await test('transform - @ works with dot', async t => {
const {stdout} = await run([{foo: 'bar'}], `@.foo`)
t.deepEqual(JSON.parse(stdout), ['bar'])
})
await test('transform - flat map works', async t => { await test('transform - flat map works', async t => {
const {stdout} = await run({master: {foo: [{bar: [{val: 1}]}]}}, '.master.foo[].bar[].val') const {stdout} = await run({master: {foo: [{bar: [{val: 1}]}]}}, '.master.foo[].bar[].val')
t.deepEqual(JSON.parse(stdout), [1]) t.deepEqual(JSON.parse(stdout), [1])

Loading…
Cancel
Save