UNPKG

3.46 kBMarkdownView Raw
1# transform-ast
2
3Transform an AST with source maps.
4Basically @substack's [falafel](https://github.com/substack/node-falafel), but based on [magic-string][].
5
6## Example
7
8```js
9var result = require('transform-ast')(`
10 var multiply = (a, b) => {
11 return a * b
12 }
13 var add = (a, b) => a + b
14`, function (node) {
15 if (node.type === 'ArrowFunctionExpression') {
16 var params = node.params.map(function (param) { return param.getSource() })
17 if (node.body.type !== 'BlockStatement') {
18 node.body.edit.update(`{ return ${node.body.getSource()} }`)
19 }
20 node.edit.update(`function (${params.join(', ')}) ${node.body.getSource()}`)
21 }
22})
23result.toString() === `
24 var multiply = function (a, b) {
25 return a * b
26 }
27 var add = function (a, b) { return a + b }
28`
29fs.writeFile('output.js.map', result.generateMap().toString())
30```
31
32## Install
33
34```bash
35npm install --save transform-ast
36```
37
38## API
39
40### `magicString = transformAst(source, opts = {}, fn = function () {})`
41
42Parse and transform a `source` string.
43`fn` will be called on each node.
44The returned `magicString` is a [magic-string][] instance, with a `toString()` method to get the transformed string and a `generateMap()` method to generate a source map.
45
46### `magicString.walk(fn)`
47
48Walk the AST again.
49`fn` will be called on each node.
50
51### nodes
52
53In addition to the usual AST node properties, each node object also has some additional methods.
54Unlike falafel, these methods live on the `.edit` property, to prevent name conflicts (such as the `update()` method and the `.update` property of a ForStatement).
55They're still also defined on the `node`s themselves, but only if there is no naming conflict.
56It's better to use the `.edit` property.
57
58### `node.getSource()`, `node.edit.source()`
59
60Get the source string for a node, including transformations.
61
62### `node.edit.update(string)`
63
64Replace `node` with the given string.
65
66### `node.edit.append(string)`
67
68Append the source `string` after this node.
69
70### `node.edit.prepend(string)`
71
72Prepend the source `string` before this node.
73
74## Custom Parser
75
76You can pass in a custom parser using the `parser` option.
77The parser should be an object with a `parse` function that takes a string and returns an AST.
78Each AST node should have `.start` and `.end` properties indicating their position in the source string.
79
80For example, parsing JSX using [babylon](https://github.com/babel/babylon):
81
82```js
83var babylon = require('babylon')
84var transform = require('transform-ast')
85var assert = require('assert')
86
87assert.equal(transform(`
88 var el = <div />;
89`, { parser: babylon, plugins: [ 'jsx' ] }, function (node) {
90 if (node.type === 'JSXElement') {
91 node.edit.update(JSON.stringify(node.source()))
92 }
93}).toString(), `
94 var el = "<div />";
95`)
96```
97
98But parsers for other languages too, like [tacoscript](https://tacoscript.github.io)'s parser module [horchata](https://github.com/forivall/tacoscript/tree/master/packages/horchata):
99
100```js
101var horchata = require('horchata')
102var transform = require('transform-ast')
103var assert = require('assert')
104
105assert.equal(transform(`
106X = () -> {
107 @prop or= 'value'
108}
109new X
110`, { parser: horchata }, function (node) {
111 switch (node.type) {
112 case 'FunctionExpression':
113 node.edit.update('function () ' + node.body.getSource())
114 }
115}).toString(), `
116X = function () {
117 @prop or= 'value'
118}
119new X
120`)
121```
122
123## License
124
125[MIT](./LICENSE)
126
127[magic-string]: https://github.com/rich-harris/magic-string