@@ -241,5 +241,114 @@ module.exports = {
241
241
assert ( typeof name === 'string' )
242
242
243
243
return VOID_ELEMENT_NAMES . has ( name . toLowerCase ( ) )
244
+ } ,
245
+
246
+ /**
247
+ * Check whether the given node is a Vue component based
248
+ * on the filename and default export type
249
+ * export default {} in .vue || .jsx
250
+ * @param {ASTNode } node Node to check
251
+ * @param {string } path File name with extension
252
+ * @returns {boolean }
253
+ */
254
+ isVueComponentFile ( node , path ) {
255
+ const isVueFile = path . endsWith ( '.vue' ) || path . endsWith ( '.jsx' )
256
+ return isVueFile &&
257
+ node . type === 'ExportDefaultDeclaration' &&
258
+ node . declaration . type === 'ObjectExpression'
259
+ } ,
260
+
261
+ /**
262
+ * Check whether given node is Vue component
263
+ * Vue.component('xxx', {}) || component('xxx', {})
264
+ * @param {ASTNode } node Node to check
265
+ * @returns {boolean }
266
+ */
267
+ isVueComponent ( node ) {
268
+ const callee = node . callee
269
+
270
+ const isFullVueComponent = node . type === 'CallExpression' &&
271
+ callee . type === 'MemberExpression' &&
272
+ callee . object . type === 'Identifier' &&
273
+ callee . object . name === 'Vue' &&
274
+ callee . property . type === 'Identifier' &&
275
+ callee . property . name === 'component' &&
276
+ node . arguments . length &&
277
+ node . arguments . slice ( - 1 ) [ 0 ] . type === 'ObjectExpression'
278
+
279
+ const isDestructedVueComponent = callee . type === 'Identifier' &&
280
+ callee . name === 'component'
281
+
282
+ return isFullVueComponent || isDestructedVueComponent
283
+ } ,
284
+
285
+ /**
286
+ * Check whether given node is new Vue instance
287
+ * new Vue({})
288
+ * @param {ASTNode } node Node to check
289
+ * @returns {boolean }
290
+ */
291
+ isVueInstance ( node ) {
292
+ const callee = node . callee
293
+ return node . type === 'NewExpression' &&
294
+ callee . type === 'Identifier' &&
295
+ callee . name === 'Vue' &&
296
+ node . arguments . length &&
297
+ node . arguments [ 0 ] . type === 'ObjectExpression'
298
+ } ,
299
+
300
+ executeOnVueComponent ( context , cb ) {
301
+ const filePath = context . getFilename ( )
302
+ const _this = this
303
+
304
+ return {
305
+ 'ExportDefaultDeclaration:exit' ( node ) {
306
+ // export default {} in .vue || .jsx
307
+ if ( ! _this . isVueComponentFile ( node , filePath ) ) return
308
+ cb ( node . declaration . properties )
309
+ } ,
310
+ 'CallExpression:exit' ( node ) {
311
+ // Vue.component('xxx', {}) || component('xxx', {})
312
+ if ( ! _this . isVueComponent ( node ) ) return
313
+ cb ( node . arguments . slice ( - 1 ) [ 0 ] . properties )
314
+ } ,
315
+ 'NewExpression:exit' ( node ) {
316
+ // new Vue({})
317
+ if ( ! _this . isVueInstance ( node ) ) return
318
+ cb ( node . arguments [ 0 ] . properties )
319
+ }
320
+ }
321
+ } ,
322
+
323
+ getComputedProperties ( componentProperties ) {
324
+ const computedPropertiesNode = componentProperties
325
+ . filter ( p =>
326
+ p . key . type === 'Identifier' &&
327
+ p . key . name === 'computed' &&
328
+ p . value . type === 'ObjectExpression'
329
+ ) [ 0 ]
330
+
331
+ if ( ! computedPropertiesNode ) { return [ ] }
332
+
333
+ const computedProperties = computedPropertiesNode . value . properties
334
+
335
+ return computedProperties . map ( cp => {
336
+ const key = cp . key . name
337
+ let value
338
+
339
+ if ( cp . value . type === 'FunctionExpression' ) {
340
+ value = cp . value . body
341
+ } else if ( cp . value . type === 'ObjectExpression' ) {
342
+ value = cp . value . properties
343
+ . filter ( p =>
344
+ p . key . type === 'Identifier' &&
345
+ p . key . name === 'get' &&
346
+ p . value . type === 'FunctionExpression'
347
+ )
348
+ . map ( p => p . value . body ) [ 0 ]
349
+ }
350
+
351
+ return { key, value }
352
+ } )
244
353
}
245
354
}
0 commit comments