2023-01-06 09:29:26 +11:00
|
|
|
import {
|
|
|
|
Program,
|
|
|
|
CallExpression,
|
|
|
|
PipeExpression,
|
|
|
|
VariableDeclaration,
|
2023-02-12 10:56:45 +11:00
|
|
|
VariableDeclarator,
|
2023-01-06 09:29:26 +11:00
|
|
|
ExpressionStatement,
|
|
|
|
Value,
|
|
|
|
getNodeFromPath,
|
2023-02-12 10:56:45 +11:00
|
|
|
Literal,
|
|
|
|
PipeSubstitution,
|
|
|
|
Identifier,
|
|
|
|
ArrayExpression,
|
|
|
|
ObjectExpression,
|
2023-01-06 09:29:26 +11:00
|
|
|
} from './abstractSyntaxTree'
|
2023-02-12 10:56:45 +11:00
|
|
|
import { PathToNode, ProgramMemory } from './executor'
|
|
|
|
import { addTagForSketchOnFace } from './std/sketch'
|
2023-01-06 09:29:26 +11:00
|
|
|
|
|
|
|
export function addSketchTo(
|
|
|
|
node: Program,
|
|
|
|
axis: 'xy' | 'xz' | 'yz',
|
|
|
|
name = ''
|
|
|
|
): { modifiedAst: Program; id: string; pathToNode: (string | number)[] } {
|
|
|
|
const _node = { ...node }
|
|
|
|
const dumbyStartend = { start: 0, end: 0 }
|
|
|
|
const _name = name || findUniqueName(node, 'part')
|
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
const startSketchAt = createCallExpression('startSketchAt', [
|
|
|
|
createArrayExpression([createLiteral(0), createLiteral(0)]),
|
|
|
|
])
|
|
|
|
const rotate = createCallExpression(axis === 'xz' ? 'rx' : 'ry', [
|
|
|
|
createLiteral(90),
|
|
|
|
createPipeSubstitution(),
|
|
|
|
])
|
|
|
|
const initialLineTo = createCallExpression('lineTo', [
|
|
|
|
createArrayExpression([createLiteral(1), createLiteral(1)]),
|
|
|
|
createPipeSubstitution(),
|
|
|
|
])
|
2023-01-06 09:29:26 +11:00
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
const pipeBody =
|
|
|
|
axis !== 'xy'
|
|
|
|
? [startSketchAt, rotate, initialLineTo]
|
|
|
|
: [startSketchAt, initialLineTo]
|
|
|
|
|
|
|
|
const variableDeclaration = createVariableDeclaration(
|
|
|
|
_name,
|
|
|
|
createPipeExpression(pipeBody)
|
|
|
|
)
|
2023-01-06 09:29:26 +11:00
|
|
|
|
|
|
|
const showCallIndex = getShowIndex(_node)
|
|
|
|
let sketchIndex = showCallIndex
|
|
|
|
if (showCallIndex === -1) {
|
2023-02-12 10:56:45 +11:00
|
|
|
_node.body = [...node.body, variableDeclaration]
|
2023-01-06 09:29:26 +11:00
|
|
|
sketchIndex = _node.body.length - 1
|
|
|
|
} else {
|
|
|
|
const newBody = [...node.body]
|
2023-02-12 10:56:45 +11:00
|
|
|
newBody.splice(showCallIndex, 0, variableDeclaration)
|
2023-01-06 09:29:26 +11:00
|
|
|
_node.body = newBody
|
|
|
|
}
|
|
|
|
let pathToNode: (string | number)[] = [
|
|
|
|
'body',
|
|
|
|
sketchIndex,
|
|
|
|
'declarations',
|
|
|
|
'0',
|
|
|
|
'init',
|
|
|
|
]
|
|
|
|
if (axis !== 'xy') {
|
|
|
|
pathToNode = [...pathToNode, 'body', '0']
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
modifiedAst: addToShow(_node, _name),
|
|
|
|
id: _name,
|
|
|
|
pathToNode,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
export function findUniqueName(
|
2023-01-06 09:29:26 +11:00
|
|
|
ast: Program | string,
|
|
|
|
name: string,
|
2023-01-09 13:19:14 +11:00
|
|
|
pad = 3,
|
2023-01-06 09:29:26 +11:00
|
|
|
index = 1
|
|
|
|
): string {
|
|
|
|
let searchStr = ''
|
|
|
|
if (typeof ast === 'string') {
|
|
|
|
searchStr = ast
|
|
|
|
} else {
|
|
|
|
searchStr = JSON.stringify(ast)
|
|
|
|
}
|
2023-01-09 13:19:14 +11:00
|
|
|
const indexStr = `${index}`.padStart(pad, '0')
|
2023-01-06 09:29:26 +11:00
|
|
|
const newName = `${name}${indexStr}`
|
|
|
|
const isInString = searchStr.includes(newName)
|
|
|
|
if (!isInString) {
|
|
|
|
return newName
|
|
|
|
}
|
2023-01-09 13:19:14 +11:00
|
|
|
return findUniqueName(searchStr, name, pad, index + 1)
|
2023-01-06 09:29:26 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
function addToShow(node: Program, name: string): Program {
|
|
|
|
const _node = { ...node }
|
|
|
|
const dumbyStartend = { start: 0, end: 0 }
|
|
|
|
const showCallIndex = getShowIndex(_node)
|
|
|
|
if (showCallIndex === -1) {
|
|
|
|
const showCall: CallExpression = {
|
|
|
|
type: 'CallExpression',
|
|
|
|
...dumbyStartend,
|
|
|
|
callee: {
|
|
|
|
type: 'Identifier',
|
|
|
|
...dumbyStartend,
|
|
|
|
name: 'show',
|
|
|
|
},
|
|
|
|
optional: false,
|
|
|
|
arguments: [
|
|
|
|
{
|
|
|
|
type: 'Identifier',
|
|
|
|
...dumbyStartend,
|
|
|
|
name,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
}
|
|
|
|
const showExpressionStatement: ExpressionStatement = {
|
|
|
|
type: 'ExpressionStatement',
|
|
|
|
...dumbyStartend,
|
|
|
|
expression: showCall,
|
|
|
|
}
|
|
|
|
_node.body = [..._node.body, showExpressionStatement]
|
|
|
|
return _node
|
|
|
|
}
|
|
|
|
const showCall = { ..._node.body[showCallIndex] } as ExpressionStatement
|
|
|
|
const showCallArgs = (showCall.expression as CallExpression).arguments
|
|
|
|
const newShowCallArgs: Value[] = [
|
|
|
|
...showCallArgs,
|
|
|
|
{
|
|
|
|
type: 'Identifier',
|
|
|
|
...dumbyStartend,
|
|
|
|
name,
|
|
|
|
},
|
|
|
|
]
|
|
|
|
const newShowExpression: CallExpression = {
|
|
|
|
type: 'CallExpression',
|
|
|
|
...dumbyStartend,
|
|
|
|
callee: {
|
|
|
|
type: 'Identifier',
|
|
|
|
...dumbyStartend,
|
|
|
|
name: 'show',
|
|
|
|
},
|
|
|
|
optional: false,
|
|
|
|
arguments: newShowCallArgs,
|
|
|
|
}
|
|
|
|
|
|
|
|
_node.body[showCallIndex] = {
|
|
|
|
...showCall,
|
|
|
|
expression: newShowExpression,
|
|
|
|
}
|
|
|
|
return _node
|
|
|
|
}
|
|
|
|
|
|
|
|
function getShowIndex(node: Program): number {
|
|
|
|
return node.body.findIndex(
|
|
|
|
(statement) =>
|
|
|
|
statement.type === 'ExpressionStatement' &&
|
|
|
|
statement.expression.type === 'CallExpression' &&
|
|
|
|
statement.expression.callee.type === 'Identifier' &&
|
|
|
|
statement.expression.callee.name === 'show'
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
export function mutateArrExp(
|
|
|
|
node: Value,
|
|
|
|
updateWith: ArrayExpression
|
|
|
|
): boolean {
|
|
|
|
if (node.type === 'ArrayExpression') {
|
|
|
|
node.elements.forEach((element, i) => {
|
|
|
|
if (element.type === 'Literal') {
|
|
|
|
node.elements[i] = updateWith.elements[i]
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return true
|
2023-01-06 09:29:26 +11:00
|
|
|
}
|
2023-02-12 10:56:45 +11:00
|
|
|
return false
|
2023-01-06 09:29:26 +11:00
|
|
|
}
|
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
export function mutateObjExpProp(
|
|
|
|
node: Value,
|
|
|
|
updateWith: Literal | ArrayExpression,
|
|
|
|
key: string
|
|
|
|
): boolean {
|
|
|
|
if (node.type === 'ObjectExpression') {
|
|
|
|
const keyIndex = node.properties.findIndex((a) => a.key.name === key)
|
|
|
|
if (keyIndex !== -1) {
|
|
|
|
if (
|
|
|
|
updateWith.type === 'Literal' &&
|
|
|
|
node.properties[keyIndex].value.type === 'Literal'
|
|
|
|
) {
|
|
|
|
node.properties[keyIndex].value = updateWith
|
|
|
|
return true
|
|
|
|
} else if (
|
|
|
|
node.properties[keyIndex].value.type === 'ArrayExpression' &&
|
|
|
|
updateWith.type === 'ArrayExpression'
|
|
|
|
) {
|
|
|
|
const arrExp = node.properties[keyIndex].value as ArrayExpression
|
|
|
|
arrExp.elements.forEach((element, i) => {
|
|
|
|
if (element.type === 'Literal') {
|
|
|
|
arrExp.elements[i] = updateWith.elements[i]
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
} else {
|
|
|
|
node.properties.push({
|
|
|
|
type: 'ObjectProperty',
|
|
|
|
key: createIdentifier(key),
|
|
|
|
value: updateWith,
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
})
|
|
|
|
}
|
2023-01-06 09:29:26 +11:00
|
|
|
}
|
2023-02-12 10:56:45 +11:00
|
|
|
return false
|
2023-01-06 09:29:26 +11:00
|
|
|
}
|
2023-01-06 12:45:34 +11:00
|
|
|
|
|
|
|
export function extrudeSketch(
|
|
|
|
node: Program,
|
|
|
|
pathToNode: (string | number)[],
|
|
|
|
shouldPipe = true
|
2023-01-13 17:58:37 +11:00
|
|
|
): {
|
|
|
|
modifiedAst: Program
|
|
|
|
pathToNode: PathToNode
|
|
|
|
pathToExtrudeArg: PathToNode
|
|
|
|
} {
|
2023-01-06 12:45:34 +11:00
|
|
|
const _node = { ...node }
|
|
|
|
const dumbyStartend = { start: 0, end: 0 }
|
2023-02-12 10:56:45 +11:00
|
|
|
const { node: sketchExpression } = getNodeFromPath(
|
2023-01-06 12:45:34 +11:00
|
|
|
_node,
|
|
|
|
pathToNode,
|
2023-02-12 10:56:45 +11:00
|
|
|
'SketchExpression' // TODO fix this #25
|
2023-01-13 17:58:37 +11:00
|
|
|
)
|
2023-01-06 12:45:34 +11:00
|
|
|
|
|
|
|
// determine if sketchExpression is in a pipeExpression or not
|
2023-01-13 17:58:37 +11:00
|
|
|
const { node: pipeExpression } = getNodeFromPath<PipeExpression>(
|
2023-01-06 12:45:34 +11:00
|
|
|
_node,
|
|
|
|
pathToNode,
|
2023-01-13 17:58:37 +11:00
|
|
|
'PipeExpression'
|
|
|
|
)
|
|
|
|
const isInPipeExpression = pipeExpression.type === 'PipeExpression'
|
|
|
|
|
|
|
|
const { node: variableDeclorator, path: pathToDecleration } =
|
|
|
|
getNodeFromPath<VariableDeclarator>(_node, pathToNode, 'VariableDeclarator')
|
2023-01-06 12:45:34 +11:00
|
|
|
|
|
|
|
const extrudeCall: CallExpression = {
|
|
|
|
type: 'CallExpression',
|
|
|
|
...dumbyStartend,
|
|
|
|
callee: {
|
|
|
|
type: 'Identifier',
|
|
|
|
...dumbyStartend,
|
|
|
|
name: 'extrude',
|
|
|
|
},
|
|
|
|
optional: false,
|
|
|
|
arguments: [
|
2023-02-12 10:56:45 +11:00
|
|
|
createLiteral(4),
|
2023-01-06 12:45:34 +11:00
|
|
|
shouldPipe
|
2023-02-12 10:56:45 +11:00
|
|
|
? createPipeSubstitution()
|
2023-01-06 12:45:34 +11:00
|
|
|
: {
|
|
|
|
type: 'Identifier',
|
|
|
|
...dumbyStartend,
|
|
|
|
name: variableDeclorator.id.name,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
}
|
|
|
|
if (shouldPipe) {
|
|
|
|
const pipeChain: PipeExpression = isInPipeExpression
|
|
|
|
? {
|
|
|
|
type: 'PipeExpression',
|
2023-02-01 07:30:55 +11:00
|
|
|
nonCodeMeta: {},
|
2023-01-06 12:45:34 +11:00
|
|
|
...dumbyStartend,
|
|
|
|
body: [...pipeExpression.body, extrudeCall],
|
|
|
|
}
|
|
|
|
: {
|
|
|
|
type: 'PipeExpression',
|
2023-02-01 07:30:55 +11:00
|
|
|
nonCodeMeta: {},
|
2023-01-06 12:45:34 +11:00
|
|
|
...dumbyStartend,
|
2023-02-12 10:56:45 +11:00
|
|
|
body: [sketchExpression as any, extrudeCall], // TODO fix this #25
|
2023-01-06 12:45:34 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
variableDeclorator.init = pipeChain
|
2023-01-13 17:58:37 +11:00
|
|
|
const pathToExtrudeArg = [
|
|
|
|
...pathToDecleration,
|
|
|
|
'init',
|
|
|
|
'body',
|
|
|
|
pipeChain.body.length - 1,
|
|
|
|
'arguments',
|
|
|
|
0,
|
|
|
|
]
|
2023-01-06 12:45:34 +11:00
|
|
|
|
|
|
|
return {
|
|
|
|
modifiedAst: _node,
|
|
|
|
pathToNode,
|
2023-01-13 17:58:37 +11:00
|
|
|
pathToExtrudeArg,
|
2023-01-06 12:45:34 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
const name = findUniqueName(node, 'part')
|
|
|
|
const VariableDeclaration: VariableDeclaration = {
|
|
|
|
type: 'VariableDeclaration',
|
|
|
|
...dumbyStartend,
|
|
|
|
declarations: [
|
|
|
|
{
|
|
|
|
type: 'VariableDeclarator',
|
|
|
|
...dumbyStartend,
|
|
|
|
id: {
|
|
|
|
type: 'Identifier',
|
|
|
|
...dumbyStartend,
|
|
|
|
name,
|
|
|
|
},
|
|
|
|
init: extrudeCall,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
kind: 'const',
|
|
|
|
}
|
|
|
|
const showCallIndex = getShowIndex(_node)
|
|
|
|
_node.body.splice(showCallIndex, 0, VariableDeclaration)
|
2023-01-13 17:58:37 +11:00
|
|
|
const pathToExtrudeArg = [
|
|
|
|
'body',
|
|
|
|
showCallIndex,
|
|
|
|
'declarations',
|
|
|
|
0,
|
|
|
|
'init',
|
|
|
|
'arguments',
|
|
|
|
0,
|
|
|
|
]
|
2023-01-06 12:45:34 +11:00
|
|
|
return {
|
|
|
|
modifiedAst: addToShow(_node, name),
|
|
|
|
pathToNode: [...pathToNode.slice(0, -1), showCallIndex],
|
2023-01-13 17:58:37 +11:00
|
|
|
pathToExtrudeArg,
|
2023-01-06 12:45:34 +11:00
|
|
|
}
|
|
|
|
}
|
2023-01-09 13:19:14 +11:00
|
|
|
|
|
|
|
export function sketchOnExtrudedFace(
|
|
|
|
node: Program,
|
2023-02-12 10:56:45 +11:00
|
|
|
pathToNode: (string | number)[],
|
|
|
|
programMemory: ProgramMemory
|
2023-01-09 13:19:14 +11:00
|
|
|
): { modifiedAst: Program; pathToNode: (string | number)[] } {
|
2023-02-12 10:56:45 +11:00
|
|
|
let _node = { ...node }
|
2023-01-09 13:19:14 +11:00
|
|
|
const newSketchName = findUniqueName(node, 'part')
|
2023-02-12 10:56:45 +11:00
|
|
|
const { node: oldSketchNode, path: pathToOldSketch } =
|
|
|
|
getNodeFromPath<VariableDeclarator>(
|
|
|
|
_node,
|
|
|
|
pathToNode,
|
|
|
|
'VariableDeclarator',
|
|
|
|
true
|
|
|
|
)
|
|
|
|
const oldSketchName = oldSketchNode.id.name
|
|
|
|
const { node: expression } = getNodeFromPath<CallExpression>(
|
2023-01-10 15:40:34 +11:00
|
|
|
_node,
|
|
|
|
pathToNode,
|
2023-02-12 10:56:45 +11:00
|
|
|
'CallExpression'
|
|
|
|
)
|
2023-01-09 13:19:14 +11:00
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
const { modifiedAst, tag } = addTagForSketchOnFace(
|
|
|
|
{
|
|
|
|
previousProgramMemory: programMemory,
|
2023-01-13 17:58:37 +11:00
|
|
|
pathToNode,
|
2023-02-12 10:56:45 +11:00
|
|
|
node: _node,
|
|
|
|
},
|
|
|
|
expression.callee.name
|
|
|
|
)
|
|
|
|
_node = modifiedAst
|
|
|
|
|
|
|
|
const newSketch = createVariableDeclaration(
|
|
|
|
newSketchName,
|
|
|
|
createPipeExpression([
|
|
|
|
createCallExpression('startSketchAt', [
|
|
|
|
createArrayExpression([createLiteral(0), createLiteral(0)]),
|
|
|
|
]),
|
|
|
|
createCallExpression('lineTo', [
|
|
|
|
createArrayExpression([createLiteral(1), createLiteral(1)]),
|
|
|
|
createPipeSubstitution(),
|
|
|
|
]),
|
|
|
|
createCallExpression('transform', [
|
|
|
|
createCallExpression('getExtrudeWallTransform', [
|
|
|
|
createLiteral(tag),
|
|
|
|
createIdentifier(oldSketchName),
|
|
|
|
]),
|
|
|
|
createPipeSubstitution(),
|
|
|
|
]),
|
|
|
|
]),
|
|
|
|
'const'
|
|
|
|
)
|
|
|
|
const expressionIndex = getLastIndex(pathToOldSketch)
|
|
|
|
_node.body.splice(expressionIndex + 1, 0, newSketch)
|
|
|
|
|
|
|
|
return {
|
|
|
|
modifiedAst: addToShow(_node, newSketchName),
|
|
|
|
pathToNode: [...pathToNode.slice(0, -1), expressionIndex],
|
|
|
|
}
|
|
|
|
}
|
2023-01-09 13:19:14 +11:00
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
const getLastIndex = (pathToNode: PathToNode): number => {
|
|
|
|
const last = pathToNode[pathToNode.length - 1]
|
|
|
|
if (typeof last === 'number') {
|
|
|
|
return last
|
2023-01-09 13:19:14 +11:00
|
|
|
}
|
2023-02-12 10:56:45 +11:00
|
|
|
return getLastIndex(pathToNode.slice(0, -1))
|
|
|
|
}
|
2023-01-09 13:19:14 +11:00
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
export function createLiteral(value: string | number): Literal {
|
|
|
|
return {
|
|
|
|
type: 'Literal',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
value,
|
|
|
|
raw: `${value}`,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createIdentifier(name: string): Identifier {
|
|
|
|
return {
|
|
|
|
type: 'Identifier',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
name,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createPipeSubstitution(): PipeSubstitution {
|
|
|
|
return {
|
|
|
|
type: 'PipeSubstitution',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createCallExpression(
|
|
|
|
name: string,
|
|
|
|
args: CallExpression['arguments']
|
|
|
|
): CallExpression {
|
|
|
|
return {
|
|
|
|
type: 'CallExpression',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
callee: {
|
|
|
|
type: 'Identifier',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
name,
|
|
|
|
},
|
|
|
|
optional: false,
|
|
|
|
arguments: args,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createArrayExpression(
|
|
|
|
elements: ArrayExpression['elements']
|
|
|
|
): ArrayExpression {
|
|
|
|
return {
|
|
|
|
type: 'ArrayExpression',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
elements,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function createPipeExpression(
|
|
|
|
body: PipeExpression['body']
|
|
|
|
): PipeExpression {
|
|
|
|
return {
|
2023-01-09 13:19:14 +11:00
|
|
|
type: 'PipeExpression',
|
2023-02-12 10:56:45 +11:00
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
body,
|
2023-02-01 07:30:55 +11:00
|
|
|
nonCodeMeta: {},
|
2023-01-09 13:19:14 +11:00
|
|
|
}
|
2023-02-12 10:56:45 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
export function createVariableDeclaration(
|
|
|
|
varName: string,
|
|
|
|
init: VariableDeclarator['init'],
|
|
|
|
kind: VariableDeclaration['kind'] = 'const'
|
|
|
|
): VariableDeclaration {
|
|
|
|
return {
|
2023-01-09 13:19:14 +11:00
|
|
|
type: 'VariableDeclaration',
|
2023-02-12 10:56:45 +11:00
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2023-01-09 13:19:14 +11:00
|
|
|
declarations: [
|
|
|
|
{
|
|
|
|
type: 'VariableDeclarator',
|
2023-02-12 10:56:45 +11:00
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
id: createIdentifier(varName),
|
|
|
|
init,
|
2023-01-09 13:19:14 +11:00
|
|
|
},
|
|
|
|
],
|
2023-02-12 10:56:45 +11:00
|
|
|
kind,
|
2023-01-09 13:19:14 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-12 10:56:45 +11:00
|
|
|
export function createObjectExpression(properties: {
|
|
|
|
[key: string]: Value
|
|
|
|
}): ObjectExpression {
|
|
|
|
return {
|
|
|
|
type: 'ObjectExpression',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
properties: Object.entries(properties).map(([key, value]) => ({
|
|
|
|
type: 'ObjectProperty',
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
|
|
|
key: createIdentifier(key),
|
|
|
|
value,
|
|
|
|
})),
|
2023-01-09 13:19:14 +11:00
|
|
|
}
|
|
|
|
}
|