Print js code in errors; add @ map syntax

pull/291/head
Anton Medvedev 6 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) {
const process = await import('node:process')
let i, code, output = json
let i, code, jsCode, output = json
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) {
printErr(err)
process.exit(1)
@ -73,52 +78,50 @@ async function runTransforms(json, args, theme) {
console.error(
`\n ${pre} ${code} ${post}\n` +
` ${' '.repeat(pre.length + 1)}${'^'.repeat(code.length)}\n` +
(jsCode !== code ? `\n${jsCode}\n` : ``) +
`\n${err.stack || err}`,
)
}
}
async function transform(json, code) {
function transpile(code) {
if ('.' === code)
return json
return 'x'
if (/^(\.\w*)+\[]/.test(code))
return eval(`(function () {
return (${fold(code.split('[]'))})(this)
})`).call(json)
return `(${fold(code.split('[]'))})(x)`
function fold(s) {
if (s.length === 1)
return 'x => x' + s[0]
let obj = s.shift()
obj = obj === '.' ? 'x' : 'x' + obj
return `x => Object.values(${obj}).flatMap(${fold(s)})`
return `x => ${obj}.flatMap(${fold(s)})`
}
if (/^\.\[/.test(code))
return eval(`(function () {
const x = this
return this${code.substring(1)}
})`).call(json)
return `x${code.substring(1)}`
if (/^\./.test(code))
return eval(`(function () {
const x = this
return this${code}
})`).call(json)
return `x${code}`
// deprecated
if (/^map\(.+?\)$/i.test(code)) {
let s = code.substring(4, code.length - 1)
if (s[0] === '.') s = 'x' + s
return eval(`(function () {
return this.map((x, i) => apply(${s}, x, i))
})`).call(json)
return `x.map((x, i) => apply(${s}, x, i))`
}
const fn = eval(`(function () {
const x = this
return ${code}
})`).call(json)
if (/^@/.test(code)) {
const jsCode = transpile(code.substring(1))
return `x.map((x, i) => apply(${jsCode}, x, i))`
}
return code
}
async function run(json, code) {
const fn = eval(code).call(json)
return apply(fn, json)

@ -139,6 +139,16 @@ void async function main() {
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 => {
const {stdout} = await run({master: {foo: [{bar: [{val: 1}]}]}}, '.master.foo[].bar[].val')
t.deepEqual(JSON.parse(stdout), [1])

Loading…
Cancel
Save