diff --git a/transformations/__tests__/global-filter.spec.ts b/transformations/__tests__/global-filter.spec.ts new file mode 100644 index 0000000..3653e4f --- /dev/null +++ b/transformations/__tests__/global-filter.spec.ts @@ -0,0 +1,37 @@ +import { defineInlineTest } from 'jscodeshift/src/testUtils' +const transform = require('../global-filter') + +defineInlineTest( + transform, + {}, + `const app = Vue.createApp(App) +Vue.filter('capitalize', function(value) { + return value +})`, + `const app = Vue.createApp(App) +app.config.globalProperties.$filters = { + capitalize(value) { + return value + } +};`, + 'transform global filter' +) + +defineInlineTest( + transform, + {}, + `const app = new Vue(App) +Vue.filter('capitalize', function(value) { + return value +})`, + `const app = new Vue(App) +Vue.filter('capitalize', function(value) { + return value +}) +`, + 'transform global filter(no effect and will warn)' +) + + + + diff --git a/transformations/global-filter.ts b/transformations/global-filter.ts new file mode 100644 index 0000000..183a161 --- /dev/null +++ b/transformations/global-filter.ts @@ -0,0 +1,91 @@ +import wrap from '../src/wrapAstTransformation' +import type { ASTTransformation } from '../src/wrapAstTransformation' + +export const transformAST: ASTTransformation = ({ root, j }) => { +// find the createApp() + const appDeclare = root.find(j.VariableDeclarator, { + id: { type: 'Identifier' }, + init: { + type: 'CallExpression', + callee: { + object: { + name: 'Vue' + }, + property: { + name: 'createApp' + } + } + } + }) + + if (!appDeclare.length) { + //dont transform new Vue(...) => Vue.createApp(...)? + const newVue = root.find(j.NewExpression, { + callee: { + type: 'Identifier', + name: 'Vue' + } + }) + + // need to transform global-filter first + if (newVue.length) { + console.warn('please transform new-global-api before transform global-filter!') + } + return + } + const appName = appDeclare.at(0).get().node.id.name + + // Vue.filter('filterName', function(value) {}) => + // app.config.globalProperties.$filters = { filterName(value) {} } + const filters = root.find(j.ExpressionStatement, { + expression: { + type: 'CallExpression', + callee: { + type: 'MemberExpression', + object: { type: 'Identifier', name: 'Vue' }, + property: { type: 'Identifier', name: 'filter' } + } + } + }) + if (!filters.length) { + return + } + + const methods = [] + for (let i = 0; i < filters.length; i++) { + const filter = filters.at(i) + const args = filter.get().node.expression.arguments + + methods.push( + j.objectMethod( + 'method', + j.identifier(args[0].value), + args[1].params, + args[1].body + ) + ) + } + + filters + .at(0) + .insertBefore( + j.expressionStatement( + j.assignmentExpression( + '=', + j.memberExpression( + j.identifier(appName), + j.identifier('config.globalProperties.$filters'), + false + ), + j.objectExpression(methods) + ) + ) + ) + + for (let i = 0; i < filters.length; i++) { + filters.at(i).remove() + } +} + +export default wrap(transformAST) +export const parser = 'babylon' diff --git a/transformations/index.ts b/transformations/index.ts index 8ec4e18..e2066bb 100644 --- a/transformations/index.ts +++ b/transformations/index.ts @@ -17,6 +17,7 @@ const transformationMap: { 'scoped-slots-to-slots': require('./scoped-slots-to-slots'), 'new-directive-api': require('./new-directive-api'), 'remove-vue-set-and-delete': require('./remove-vue-set-and-delete'), + 'global-filter': require('./global-filter'), // atomic ones 'remove-contextual-h-from-render': require('./remove-contextual-h-from-render'),