You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: posts/jsfmt.md
+12-6
Original file line number
Diff line number
Diff line change
@@ -13,7 +13,7 @@ Analyze What?
13
13
14
14
The Rdio app uses a component architecture where a component is a collection of HTML, CSS and JavaScript that form a complete set of functionality. Buttons, forms, and views are all components as well as the overall Rdio app itself which in turn depends on a number of other components. We explicitly declare these dependencies in each component declaration so we know which subsequent components to load at runtime:
15
15
16
-
```
16
+
```javascript
17
17
R.Components.create('MyComponent', {
18
18
dependencies: ['MyOtherComponent']
19
19
});
@@ -44,7 +44,7 @@ I've spent the last year thinking about the problem and a more elegant solution
44
44
45
45
The first thing we want to do is take a plain JavaScript string that represents what we want to search for and parse it into an AST. For example, if we want to find the function call `"_.reduce()"` then we parse that string into an AST that looks something like this:
46
46
47
-
```
47
+
```json
48
48
{
49
49
"type": "ExpressionStatement",
50
50
"expression": {
@@ -76,23 +76,29 @@ I've iterated a lot on how to best handle a list in the AST, such as the `argume
76
76
77
77
As an example, if we wanted to find all occurrences of Underscore's reduce function with 3 arguments:
78
78
79
-
`jsfmt --search "_.reduce(a, b, c)" <source>`
79
+
```bash
80
+
jsfmt --search "_.reduce(a, b, c)"<source>
81
+
```
80
82
81
83
The wildcards `a`, `b` and `c` will match any expression at that location. Furthermore, we match any `_.reduce` call with 3 _or more_ arguments.
82
84
83
85
Taking this example a step further, what if we wanted to replace all occurrences of one function with another such as a library upgrade or dropping support for an older browser? For example, replacing all `_.reduce` calls with the native JavaScript `Array.prototype.reduce`. We use the same syntax as before but also specifying the replacement after an arrow (`[match] -> [replacement]`):
84
86
85
-
`jsfmt --replace "_.reduce(a, b, c) -> a.reduce(b, c)" <source>`
87
+
```bash
88
+
jsfmt --replace "_.reduce(a, b, c) -> a.reduce(b, c)"<source>
89
+
```
86
90
87
91
We can use the same wildcards in the "match" as placeholders in our "replacement".
88
92
89
93
Back to the original problem of finding component dependencies. Before `jsfmt` even our simple static analysis was unwieldy. Now searching for component dependencies is simple and intuitive:
90
94
91
-
`jsfmt --search "R.Component.create(a, { dependencies: z })" <source>`
95
+
```bash
96
+
jsfmt --search "R.Component.create(a, { dependencies: z })"<source>
97
+
```
92
98
93
99
There's also a JavaScript API exposed:
94
100
95
-
```
101
+
```javascript
96
102
jsfmt.search(source, "R.Component.create(a, { dependencies: z })").forEach(function(matches, wildcards) {
0 commit comments