@@ -15,7 +15,8 @@ var utils = require('./utils'),
1515 FILTERS_RE = / \| [ ^ \| ] + / g,
1616 FILTER_TOKEN_RE = / [ ^ \s ' ] + | ' [ ^ ' ] + ' | [ ^ \s " ] + | " [ ^ " ] + " / g,
1717 NESTING_RE = / ^ \$ ( p a r e n t | r o o t ) \. / ,
18- SINGLE_VAR_RE = / ^ [ \w \. $ ] + $ /
18+ SINGLE_VAR_RE = / ^ [ \w \. $ ] + $ / ,
19+ QUOTE_RE = / " / g
1920
2021/**
2122 * Directive class
@@ -57,28 +58,35 @@ function Directive (dirname, definition, expression, rawKey, compiler, node) {
5758 : expression
5859 ) . trim ( )
5960
60- parseKey ( this , rawKey )
61+ var parsed = Directive . parseArg ( rawKey )
62+ this . key = parsed . key
63+ this . arg = parsed . arg
6164
62- var filterExps = this . expression . slice ( rawKey . length ) . match ( FILTERS_RE )
63- if ( filterExps ) {
65+ var filters = Directive . parseFilters ( this . expression . slice ( rawKey . length ) ) ,
66+ filter , fn , i , l
67+ if ( filters ) {
6468 this . filters = [ ]
65- for ( var i = 0 , l = filterExps . length , filter ; i < l ; i ++ ) {
66- filter = parseFilter ( filterExps [ i ] , this . compiler )
67- if ( filter ) {
69+ for ( i = 0 , l = filters . length ; i < l ; i ++ ) {
70+ filter = filters [ i ]
71+ fn = this . compiler . getOption ( 'filters' , filter . name )
72+ if ( fn ) {
73+ filter . apply = fn
6874 this . filters . push ( filter )
69- if ( filter . apply . computed ) {
70- // some special filters, e.g. filterBy & orderBy,
71- // can involve VM properties and they often need to
72- // be computed.
75+ if ( fn . computed ) {
7376 this . computeFilters = true
7477 }
7578 }
7679 }
77- if ( ! this . filters . length ) this . filters = null
78- } else {
80+ }
81+
82+ if ( ! this . filters || ! this . filters . length ) {
7983 this . filters = null
8084 }
8185
86+ if ( this . computeFilters ) {
87+ this . key = Directive . inlineFilters ( this . key , this . filters )
88+ }
89+
8290 this . isExp =
8391 this . computeFilters ||
8492 ! SINGLE_VAR_RE . test ( this . key ) ||
@@ -88,47 +96,6 @@ function Directive (dirname, definition, expression, rawKey, compiler, node) {
8896
8997var DirProto = Directive . prototype
9098
91- /**
92- * parse a key, extract argument and nesting/root info
93- */
94- function parseKey ( dir , rawKey ) {
95- var key = rawKey
96- if ( rawKey . indexOf ( ':' ) > - 1 ) {
97- var argMatch = rawKey . match ( ARG_RE )
98- key = argMatch
99- ? argMatch [ 2 ] . trim ( )
100- : key
101- dir . arg = argMatch
102- ? argMatch [ 1 ] . trim ( )
103- : null
104- }
105- dir . key = key
106- }
107-
108- /**
109- * parse a filter expression
110- */
111- function parseFilter ( filter , compiler ) {
112-
113- var tokens = filter . slice ( 1 ) . match ( FILTER_TOKEN_RE )
114- if ( ! tokens ) return
115-
116- var name = tokens [ 0 ] ,
117- apply = compiler . getOption ( 'filters' , name )
118- if ( ! apply ) {
119- utils . warn ( 'Unknown filter: ' + name )
120- return
121- }
122-
123- return {
124- name : name ,
125- apply : apply ,
126- args : tokens . length > 1
127- ? tokens . slice ( 1 )
128- : null
129- }
130- }
131-
13299/**
133100 * called when a new value is set
134101 * for computed properties, this will only be called once
@@ -170,7 +137,7 @@ DirProto.unbind = function () {
170137 this . vm = this . el = this . binding = this . compiler = null
171138}
172139
173- // exposed methods ------- -----------------------------------------------------
140+ // Exposed static methods -----------------------------------------------------
174141
175142/**
176143 * split a unquoted-comma separated expression into
@@ -183,27 +150,104 @@ Directive.split = function (exp) {
183150}
184151
185152/**
186- * make sure the directive and expression is valid
187- * before we create an instance
153+ * parse a key, extract argument
188154 */
189- Directive . parse = function ( dirname , expression , compiler , node ) {
155+ Directive . parseArg = function ( rawKey ) {
156+ var key = rawKey ,
157+ arg = null
158+ if ( rawKey . indexOf ( ':' ) > - 1 ) {
159+ var argMatch = rawKey . match ( ARG_RE )
160+ key = argMatch
161+ ? argMatch [ 2 ] . trim ( )
162+ : key
163+ arg = argMatch
164+ ? argMatch [ 1 ] . trim ( )
165+ : arg
166+ }
167+ return {
168+ key : key ,
169+ arg : arg
170+ }
171+ }
190172
191- var dir = compiler . getOption ( 'directives' , dirname ) || directives [ dirname ]
192- if ( ! dir ) {
193- utils . warn ( 'Unknown directive: ' + dirname )
194- return
173+ /**
174+ * parse a the filters
175+ */
176+ Directive . parseFilters = function ( exp ) {
177+ if ( ! exp . indexOf ( '|' ) < 0 ) return
178+ var filters = exp . match ( FILTERS_RE ) ,
179+ res , i , l , tokens
180+ if ( filters ) {
181+ res = [ ]
182+ for ( i = 0 , l = filters . length ; i < l ; i ++ ) {
183+ tokens = filters [ i ] . slice ( 1 ) . match ( FILTER_TOKEN_RE )
184+ if ( tokens ) {
185+ res . push ( {
186+ name : tokens [ 0 ] ,
187+ args : tokens . length > 1
188+ ? tokens . slice ( 1 )
189+ : null
190+ } )
191+ }
192+ }
193+ }
194+ return res
195+ }
196+
197+ /**
198+ * Inline computed filters so they become part
199+ * of the expression
200+ */
201+ Directive . inlineFilters = function ( key , filters ) {
202+ var args , filter
203+ for ( var i = 0 , l = filters . length ; i < l ; i ++ ) {
204+ filter = filters [ i ]
205+ args = filter . args
206+ ? ',"' + filter . args . map ( escapeQuote ) . join ( '","' ) + '"'
207+ : ''
208+ key = 'this.$compiler.getOption("filters", "' +
209+ filter . name +
210+ '").call(this,' +
211+ key + args +
212+ ')'
195213 }
214+ return key
215+ }
216+
217+ /**
218+ * Convert double quotes to single quotes
219+ * so they don't mess up the generated function body
220+ */
221+ function escapeQuote ( v ) {
222+ return v . indexOf ( '"' ) > - 1
223+ ? v . replace ( QUOTE_RE , '\'' )
224+ : v
225+ }
196226
197- var rawKey
227+ /**
228+ * Parse the key from a directive raw expression
229+ */
230+ Directive . parseKey = function ( expression ) {
198231 if ( expression . indexOf ( '|' ) > - 1 ) {
199232 var keyMatch = expression . match ( KEY_RE )
200233 if ( keyMatch ) {
201- rawKey = keyMatch [ 0 ] . trim ( )
234+ return keyMatch [ 0 ] . trim ( )
202235 }
203236 } else {
204- rawKey = expression . trim ( )
237+ return expression . trim ( )
205238 }
206-
239+ }
240+
241+ /**
242+ * make sure the directive and expression is valid
243+ * before we create an instance
244+ */
245+ Directive . build = function ( dirname , expression , compiler , node ) {
246+
247+ var dir = compiler . getOption ( 'directives' , dirname )
248+ if ( ! dir ) return
249+
250+ var rawKey = Directive . parseKey ( expression )
207251 // have a valid raw key, or be an empty directive
208252 if ( rawKey || expression === '' ) {
209253 return new Directive ( dirname , dir , expression , rawKey , compiler , node )
0 commit comments