@@ -7,13 +7,13 @@ const KNOWN_HELPERS = require('./known-helpers');
77/**
88 * plugin entrypoint
99 */
10- function transformPlugin ( env , runtimeData , options = { } ) {
10+ function transformPlugin ( env , options = { } ) {
1111 let { builders : b } = env . syntax ;
1212
1313 let scopedParams = [ ] ;
1414 let [ components , helpers ] = populateInvokeables ( ) ;
1515
16- let nonThises = { scopedParams , components , helpers } ;
16+ let customHelpers = options . customHelpers || [ ] ;
1717
1818 let paramTracker = {
1919 enter ( node ) {
@@ -29,87 +29,121 @@ function transformPlugin(env, runtimeData, options = {}) {
2929 } ,
3030 } ;
3131
32- return {
33- Program : paramTracker ,
34- ElementNode : paramTracker ,
35- PathExpression ( ast ) {
36- if ( ast . data ) return ;
37- if ( ast . original === 'this' ) return ;
32+ function handleParams ( params ) {
33+ for ( let param of params ) {
34+ if ( param . type !== 'PathExpression' ) continue ;
35+ handlePathExpression ( param ) ;
36+ }
37+ }
3838
39- let token = ast . parts [ 0 ] ;
39+ function handleHash ( hash ) {
40+ for ( let pair of hash . pairs ) {
41+ if ( pair . value . type !== 'PathExpression' ) continue ;
42+ handlePathExpression ( pair . value ) ;
43+ }
44+ }
4045
41- if ( token !== 'this' ) {
42- let isThisNeeded = doesTokenNeedThis ( token , nonThises , runtimeData , options ) ;
46+ function handlePathExpression ( node ) {
47+ // skip this.foo
48+ if ( node . this ) return ;
4349
44- if ( isThisNeeded ) {
45- return b . path ( `this. ${ ast . parts . join ( '.' ) } ` ) ;
46- }
47- }
48- } ,
49- } ;
50- }
50+ // skip @foo
51+ if ( node . data ) return ;
52+
53+ // skip {#foo as |bar|} }{{bar}}{{/foo} }
54+ // skip <Foo as |bar|>{{bar}}</Foo>
55+ let firstPart = node . parts [ 0 ] ;
56+ if ( scopedParams . includes ( firstPart ) ) return ;
5157
52- // Does the runtime data (for the c
53- // urrent file)
54- // contain a definition for the token?
55- // - yes:
56- // - in-let: false
57- // - in-each: false
58- // - true
59- // - no:
60- // - is-helper: false
61- // - is-component: false
62- function doesTokenNeedThis (
63- token ,
64- { components, helpers, scopedParams } ,
65- runtimeData ,
66- { dontAssumeThis, customHelpers }
67- ) {
68- if ( KNOWN_HELPERS . includes ( token ) || customHelpers . includes ( token ) ) {
69- return false ;
58+ // add `this.` prefix
59+ Object . assign ( node , b . path ( `this.${ node . original } ` ) ) ;
7060 }
7161
72- let isBlockParam = scopedParams . includes ( token ) ;
62+ function isHelper ( name ) {
63+ return (
64+ KNOWN_HELPERS . includes ( name ) ||
65+ customHelpers . includes ( name ) ||
66+ Boolean ( helpers . find ( path => path . endsWith ( name ) ) )
67+ ) ;
68+ }
7369
74- if ( isBlockParam ) {
75- return false ;
70+ function isComponent ( name ) {
71+ return Boolean ( components . find ( path => path . endsWith ( name ) ) ) ;
7672 }
7773
78- let { computedProperties, getters, ownActions, ownProperties } = runtimeData ;
79- let isComputed = ( computedProperties || [ ] ) . includes ( token ) ;
80- let isAction = ( ownActions || [ ] ) . includes ( token ) ;
81- let isProperty = ( ownProperties || [ ] ) . includes ( token ) ;
82- let isGetter = ( getters || [ ] ) . includes ( token ) ;
74+ let inAttrNode = false ;
8375
84- let needsThis = isComputed || isAction || isProperty || isGetter ;
76+ return {
77+ Block : paramTracker ,
78+ ElementNode : paramTracker ,
8579
86- if ( needsThis ) {
87- return true ;
88- }
80+ AttrNode : {
81+ enter ( ) {
82+ inAttrNode = true ;
83+ } ,
84+ exit ( ) {
85+ inAttrNode = false ;
86+ } ,
87+ } ,
8988
90- // This is to support the ember-holy-futuristic-template-namespacing-batman syntax
91- // as well as support for Nested Invocations in Angle Bracket Syntax
92- // Ref: https://github.com/rwjblue/ember-holy-futuristic-template-namespacing-batman
93- if ( token . includes ( '$' ) ) {
94- token = token . split ( '$' ) [ 1 ] ;
95- }
96- if ( token . includes ( '::' ) ) {
97- token = token . replace ( / : : / g, '/' ) ;
98- }
89+ MustacheStatement ( node ) {
90+ let { path, params, hash } = node ;
9991
100- let isComponent = components . find ( path => path . endsWith ( token ) ) ;
92+ // {{foo BAR}}
93+ handleParams ( params ) ;
10194
102- if ( isComponent ) {
103- return false ;
104- }
95+ // {{foo bar=BAZ}}
96+ handleHash ( hash ) ;
10597
106- let isHelper = helpers . find ( path => path . endsWith ( token ) ) ;
98+ let hasParams = params . length !== 0 ;
99+ let hasHashPairs = hash . pairs . length !== 0 ;
107100
108- if ( isHelper ) {
109- return false ;
110- }
101+ // {{FOO}}
102+ if ( path . type === 'PathExpression' && ! hasParams && ! hasHashPairs ) {
103+ // {{FOO.bar}}
104+ if ( path . parts > 1 ) {
105+ handlePathExpression ( path ) ;
106+ return ;
107+ }
108+
109+ // skip ember-holy-futuristic-template-namespacing-batman component/helper invocations
110+ // (see https://github.com/rwjblue/ember-holy-futuristic-template-namespacing-batman)
111+ if ( path . original . includes ( '$' ) || path . original . includes ( '::' ) ) return ;
112+
113+ // skip helpers
114+ if ( isHelper ( path . original ) ) return ;
115+
116+ // skip components
117+ if ( ! inAttrNode && isComponent ( path . original ) ) return ;
118+
119+ handlePathExpression ( path ) ;
120+ }
121+ } ,
111122
112- return dontAssumeThis ? false : true ;
123+ BlockStatement ( node ) {
124+ // {{#foo BAR}}{{/foo}}
125+ handleParams ( node . params ) ;
126+
127+ // {{#foo bar=BAZ}}{{/foo}}
128+ handleHash ( node . hash ) ;
129+ } ,
130+
131+ SubExpression ( node ) {
132+ // (foo BAR)
133+ handleParams ( node . params ) ;
134+
135+ // (foo bar=BAZ)
136+ handleHash ( node . hash ) ;
137+ } ,
138+
139+ ElementModifierStatement ( node ) {
140+ // <div {{foo BAR}} />
141+ handleParams ( node . params ) ;
142+
143+ // <div {{foo bar=BAZ}} />
144+ handleHash ( node . hash ) ;
145+ } ,
146+ } ;
113147}
114148
115149function populateInvokeables ( ) {
0 commit comments