Skip to content

Commit ba3dd44

Browse files
authored
Merge pull request #5 from emberjs/jsutils
Allow AST plugins to manipulate Javascript scope
2 parents 7adbf36 + 73b7789 commit ba3dd44

File tree

10 files changed

+1736
-262
lines changed

10 files changed

+1736
-262
lines changed

README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ interface NodeOptions extends Options {
7777
// Options handling rules:
7878
//
7979
// - we add `content`, which is the original string form of the template
80+
// - we add `meta.jsutils`, which gives AST transform plugins access to methods for manipulating the surrounding javascript scope. See "JSUtils" below.
8081
// - we have special parsing for `scope` which becomes `locals` when passed
8182
// to your precompile
8283
// - anything else the user passes to `precompileTemplate` will be passed
@@ -98,6 +99,45 @@ import * as babel from '@babel/core';
9899
babel.transform(someCode, { plugins: [makePlugin(loadTemplateCompiler)] });
99100
```
100101

102+
# JSUtils: Manipulating Javascript from within AST transforms
103+
104+
AST transforms are plugins for modifying HBS templates at build time. Because those templates are embedded in Javascript and can access the Javascript scope, an AST plugin may want to introduce some new things into Javascript scope. That is what the JSUtils API is for.
105+
106+
Your AST transform can access the JSUtils API via `env.meta.jsutils`. Here's an example transform.
107+
108+
```js
109+
function myAstTransform(env) {
110+
return {
111+
name: 'my-ast-transform',
112+
visitor: {
113+
PathExpression(node, path) {
114+
if (node.original === 'onePlusOne') {
115+
let name = env.meta.jsutils.bindExpression('1+1', path, { nameHint: 'two' });
116+
return env.syntax.builders.path(name);
117+
}
118+
},
119+
},
120+
};
121+
}
122+
```
123+
124+
The example transform above would rewrite:
125+
126+
```js
127+
import { precompileTemplate } from '@ember/template-compilation';
128+
precompileTemplate('<Counter @value={{onePlusOne}} />>');
129+
```
130+
131+
To:
132+
133+
```js
134+
import { precompileTemplate } from '@ember/template-compilation';
135+
let two = 1 + 1;
136+
precompileTemplate('<Counter @value={{two}} />', { scope: () => ({ two }) });
137+
```
138+
139+
See the jsdoc comments in js-utils.js for details on the methods available.
140+
101141
# Acknowledgement / History
102142

103143
This repo derives from https://github.com/ember-cli/babel-plugin-htmlbars-inline-precompile

__tests__/mock-precompile.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
export function precompile(value: string) {
22
return `precompiledFromPath(${value})`;
33
}
4+
5+
export function _preprocess(...args: unknown[]) {
6+
return args;
7+
}

0 commit comments

Comments
 (0)