Skip to content

Commit

Permalink
feat: add fromAcornAst method to create stringified object from acorn…
Browse files Browse the repository at this point in the history
… ast expressions
  • Loading branch information
thetutlage committed Mar 10, 2020
1 parent 689f7fa commit 06c1cd6
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 1 deletion.
41 changes: 41 additions & 0 deletions src/StringifiedObject/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
* file that was distributed with this source code.
*/

import { Parser } from 'edge-parser'

/**
* This class generates a valid object as a string, which is written to the template
* output. The reason we need a string like object, since we don't want it's
Expand Down Expand Up @@ -42,4 +44,43 @@ export class StringifiedObject {
this.obj = ''
return obj
}

/**
* Parses an array of expressions to form an object. Each expression inside the array must
* be `ObjectExpression` or an `AssignmentExpression`, otherwise it will be ignored.
*
* ```js
* (title = 'hello')
* // returns { title: 'hello' }
*
* ({ title: 'hello' })
* // returns { title: 'hello' }
*
* ({ title: 'hello' }, username = 'virk')
* // returns { title: 'hello', username: 'virk' }
* ```
*/
public static fromAcornExpressions (expressions: any[], parser: Parser): string {
if (!Array.isArray(expressions)) {
throw new Error('"fromAcornExpressions" expects an array of acorn ast expressions')
}

const objectifyString = new this()

expressions.forEach((arg) => {
if (arg.type === 'ObjectExpression') {
arg.properties.forEach((prop: any) => {
const key = parser.utils.stringify(prop.key)
const value = parser.utils.stringify(prop.value)
objectifyString.add(key, value)
})
}

if (arg.type === 'AssignmentExpression') {
objectifyString.add(arg.left.name, parser.utils.stringify(arg.right))
}
})

return objectifyString.flush()
}
}
96 changes: 95 additions & 1 deletion test/stringified-object.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,23 @@
*/

import test from 'japa'

import { Parser } from 'edge-parser'
import { StringifiedObject } from '../src/StringifiedObject'

/**
* Sample loc
*/
const LOC = {
start: {
line: 1,
col: 0,
},
end: {
line: 1,
col: 0,
},
}

test.group('StringifiedObject', () => {
test('add string as a key-value pair to object', (assert) => {
const stringified = new StringifiedObject()
Expand Down Expand Up @@ -42,3 +56,83 @@ test.group('StringifiedObject', () => {
assert.equal(stringified.flush(), '{ username: { [10, 20] } }')
})
})

test.group('StringifiedObject | fromAcornAst', () => {
test('stringify object expression', (assert) => {
const parser = new Parser({}, { filename: 'eval.edge' })
const expression = parser.utils.transformAst(
parser.utils.generateAST(`({ username: 'virk' })`, LOC, parser.options.filename),
parser.options.filename,
)

const props = StringifiedObject.fromAcornExpressions([expression], parser)
assert.equal(props, `{ username: 'virk' }`)
})

test('parse props with shorthand obj', (assert) => {
const parser = new Parser({}, { filename: 'eval.edge' })
const expression = parser.utils.transformAst(
parser.utils.generateAST(`({ username })`, LOC, parser.options.filename),
parser.options.filename,
)

const props = StringifiedObject.fromAcornExpressions([expression], parser)
assert.equal(props, `{ username: ctx.resolve('username') }`)
})

test('parse props with computed obj', (assert) => {
const parser = new Parser({}, { filename: 'eval.edge' })
const expression = parser.utils.transformAst(
parser.utils.generateAST(`({ [username]: username })`, LOC, parser.options.filename),
parser.options.filename,
)

const props = StringifiedObject.fromAcornExpressions([expression], parser)
assert.equal(props, `{ ctx.resolve('username'): ctx.resolve('username') }`)
})

test('parse props with multiple obj properties', (assert) => {
const parser = new Parser({}, { filename: 'eval.edge' })
const expression = parser.utils.transformAst(
parser.utils.generateAST(`({ username: 'virk', age: 22 })`, LOC, parser.options.filename),
parser.options.filename,
)

const props = StringifiedObject.fromAcornExpressions([expression], parser)

assert.equal(props, `{ username: 'virk', age: 22 }`)
})

test('parse props with shorthand and full properties', (assert) => {
const parser = new Parser({}, { filename: 'eval.edge' })
const expression = parser.utils.transformAst(
parser.utils.generateAST(`({ username, age: 22 })`, LOC, parser.options.filename),
parser.options.filename,
)

const props = StringifiedObject.fromAcornExpressions([expression], parser)
assert.equal(props, `{ username: ctx.resolve('username'), age: 22 }`)
})

test('parse props with assignment expression', (assert) => {
const parser = new Parser({}, { filename: 'eval.edge' })
const expression = parser.utils.transformAst(
parser.utils.generateAST(`(title = 'Hello')`, LOC, parser.options.filename),
parser.options.filename,
)

const props = StringifiedObject.fromAcornExpressions([expression], parser)
assert.equal(props, `{ title: 'Hello' }`)
})

test('parse props with more than one assignment expression', (assert) => {
const parser = new Parser({}, { filename: 'eval.edge' })
const expression = parser.utils.transformAst(
parser.utils.generateAST(`(title = 'Hello', body = 'Some content')`, LOC, parser.options.filename),
parser.options.filename,
)

const props = StringifiedObject.fromAcornExpressions(expression.expressions, parser)
assert.equal(props, `{ title: 'Hello', body: 'Some content' }`)
})
})

0 comments on commit 06c1cd6

Please sign in to comment.