Skip to content

Instantly share code, notes, and snippets.

@FND
Last active September 16, 2019 13:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FND/70f7df09b498ebc450d59f1c4b33f9bd to your computer and use it in GitHub Desktop.
Save FND/70f7df09b498ebc450d59f1c4b33f9bd to your computer and use it in GitHub Desktop.
JavaScript AST manipulation
#!/usr/bin/env node
let { generate } = require("escodegen");
let jsx = require("acorn-jsx");
let acorn = require("acorn");
let { strictEqual: assertSame } = require("assert");
let JSXParser = acorn.Parser.extend(jsx());
let ast = JSXParser.parse(`<Card title={123}>
lorem ipsum
{9.87}
</Card>`);
let root = ast.body[0].expression;
validateNode(root, "JSXElement"); // sanity check
console.error(root);
console.error("\n----\n");
// rewrite node in place -- FIXME: discards `start`, `end`
Object.keys(root).forEach(key => {
delete root[key]; // XXX: crude?
});
Object.assign(root, $array(
$invocation("Card", $object({ title: $literal(123) }),
$literal("lorem ipsum"), $literal(9.87)),
$literal(false),
$literal(null)
));
let code = generate(ast);
console.error(`<pre>\n${code}\n</pre>`);
function $invocation(functionName, ...args) {
return {
type: "CallExpression",
callee: {
type: "Identifier",
name: functionName
},
arguments: args
};
}
function $array(...elements) {
return {
type: "ArrayExpression",
elements
};
}
function $object(obj) {
return {
type: "ObjectExpression",
properties: Object.entries(obj).map(([key, value]) => ({
type: "Property",
kind: "init", // XXX: ?
method: false,
shorthand: false,
computed: false,
key: {
type: "Identifier",
name: key
},
value
}))
};
}
function $literal(value) {
return {
type: "Literal",
value,
raw: JSON.stringify(value) // XXX: unnecessary?
};
}
function validateNode({ type }, expected) {
assertSame(type, expected, `expected \`${expected}\`, got \`${type}\``);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment