Skip to content

Commit 0ea3e59

Browse files
committed
feat(wip): restructure the codemods directory
1 parent cf88c6d commit 0ea3e59

24 files changed

+208
-40
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import Vue from 'vue';
2+
import App from './App.vue';
3+
4+
new Vue({
5+
myOption: 'hello!',
6+
render: h => h(App),
7+
}).$mount('#app');
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { createApp, h } from 'vue';
2+
import App from './App.vue';
3+
4+
createApp({
5+
myOption: 'hello!',
6+
render: () => h(App),
7+
}).mount('#app');

generator/codemods/global-api/__testfixtures__/el.input.js

Whitespace-only changes.

generator/codemods/global-api/__testfixtures__/el.output.js

Whitespace-only changes.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import Vue from 'vue';
2+
import Vuex from 'vuex';
3+
import App from './App.vue';
4+
import vuexstore from './store';
5+
6+
Vue.use(Vuex)
7+
8+
new Vue({
9+
store: vuexstore,
10+
render: h => h(App),
11+
}).$mount('#app');

generator/codemods/global-api/__testfixtures__/vuex-basic-2.output.js

Whitespace-only changes.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import Vue from 'vue';
2+
import Vuex from 'vuex';
3+
4+
import App from './App.vue';
5+
import store from './store';
6+
7+
Vue.use(Vuex)
8+
9+
new Vue({
10+
store,
11+
render: h => h(App),
12+
}).$mount('#app');
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { createApp } from 'vue';
2+
import Vuex from 'vuex';
3+
4+
import App from './App.vue';
5+
import store from './store';
6+
7+
const app = createApp(App)
8+
app.use(store)
9+
app.mount('#app');
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Store } from 'vuex'
2+
3+
const store = new Store({
4+
state: {
5+
count: 0
6+
},
7+
mutations: {
8+
increment (state) {
9+
state.count++
10+
}
11+
}
12+
})
13+
14+
export default store
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { createStore } from 'vuex'
2+
3+
const store = createStore({
4+
state () {
5+
return {
6+
count: 1
7+
}
8+
}
9+
})
10+
11+
export default store
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
jest.autoMockOff()
2+
3+
const { defineTest } = require('jscodeshift/dist/testUtils')
4+
5+
defineTest(__dirname, 'index', null, 'basic')
6+
defineTest(__dirname, 'index', null, 'custom-root-option')
7+
// defineTest(__dirname, 'index', null, 'el')
8+
// defineTest(__dirname, 'index', null, 'vuex-basic')
9+
// defineTest(__dirname, 'index', null, 'vuex-basic-2')
10+
// defineTest(__dirname, 'index', null, 'vuex-store')

generator/codemods/rfc09-global-api/transformMount.js renamed to generator/codemods/global-api/create-app-mount.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
module.exports = function transformMount(j, root) {
1+
module.exports = function createAppMount(context) {
2+
const { j, root } = context
3+
24
// new Vue(...).$mount()
35
const mountCalls = root.find(j.CallExpression, n => {
46
return (
@@ -22,6 +24,17 @@ module.exports = function transformMount(j, root) {
2224
options.properties[0].value.body.type === 'CallExpression'
2325
) {
2426
options = options.properties[0].value.body.arguments[0]
27+
} else {
28+
// replace `render: h => h(App)` with `render: () => h(App)
29+
// and add an `h` import
30+
const renderFn = options.properties.find(p => p.key.name === 'render' && p.value.type === 'ArrowFunctionExpression')
31+
if (renderFn) {
32+
const addImport = require('./utilities/add-import')
33+
addImport(context, { imported: 'h' }, 'vue')
34+
35+
// remove the `h` parameter
36+
renderFn.value.params.shift()
37+
}
2538
}
2639

2740
return j.callExpression(
@@ -32,6 +45,4 @@ module.exports = function transformMount(j, root) {
3245
[el]
3346
)
3447
})
35-
36-
return root
3748
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
module.exports = function(fileInfo, api) {
2+
const j = api.jscodeshift
3+
const root = j(fileInfo.source)
4+
const context = { j, root }
5+
6+
const addImport = require('./utilities/add-import')
7+
addImport(context, { imported: 'createApp' }, 'vue')
8+
9+
require('./create-app-mount')(context)
10+
require('./remove-production-tip')(context)
11+
require('./remove-contextual-h')(context)
12+
require('./remove-trivial-render')(context)
13+
require('./vuex')(context)
14+
15+
// remove extraneous Vue import
16+
const localVueUsages = root.find(j.Identifier, { name: 'Vue' })
17+
if (localVueUsages.length === 1) {
18+
localVueUsages.closest(j.ImportDefaultSpecifier).remove()
19+
}
20+
21+
return root.toSource({ lineTerminator: '\n' })
22+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const addImport = require('./utilities/add-import')
2+
3+
// replace `render: h => h(App)` with `render: () => h(App)
4+
module.exports = function removeContextualH (context) {
5+
const { j, root } = context
6+
7+
const renderFns = (root.find(j.Property, {
8+
key: {
9+
name: 'render'
10+
},
11+
value: {
12+
type: 'ArrowFunctionExpression'
13+
}
14+
}))
15+
if (renderFns.length) {
16+
addImport(context, { imported: 'h' }, 'vue')
17+
renderFns.forEach(({ node }) => {
18+
node.value.params.shift()
19+
})
20+
}
21+
22+
// TODO: render methods
23+
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module.exports = function removeProductionTip(j, root) {
1+
module.exports = function removeProductionTip({ j, root }) {
22
const productionTipAssignment = root.find(
33
j.AssignmentExpression,
44
n =>
@@ -8,6 +8,4 @@ module.exports = function removeProductionTip(j, root) {
88
n.left.object.object.name === 'Vue'
99
)
1010
productionTipAssignment.remove()
11-
12-
return root
1311
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// It is expected to be run after the `createApp` transformataion
2+
module.exports = function removeTrivialRender({ j, root }) {
3+
// TODO:
4+
// const rootComponent =
5+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = function (context) {
2+
// TODO:
3+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// specifier should be in the form of `Vue` or `{ imported: 'h' }` or `{ imported: 'h', local: 'createElement' }`
2+
module.exports = function addImport(context, specifier, source) {
3+
const { j, root } = context
4+
5+
const isDefaultImport = typeof specifier === 'string'
6+
const localName = isDefaultImport
7+
? specifier
8+
: specifier.local || specifier.imported
9+
10+
const duplicate = root.find(j.ImportDeclaration, {
11+
specifiers: arr => arr.some(s => s.local.name === localName),
12+
source: {
13+
value: source
14+
}
15+
})
16+
if (duplicate.length) {
17+
return
18+
}
19+
20+
let newImportSpecifier
21+
if (isDefaultImport) {
22+
newImportSpecifier = j.importDefaultSpecifier(j.identifier(specifier))
23+
} else {
24+
newImportSpecifier = j.importSpecifier(
25+
j.identifier(specifier.imported),
26+
j.identifier(specifier.local || specifier.imported)
27+
)
28+
}
29+
30+
const matchedDecl = root.find(j.ImportDeclaration, {
31+
source: {
32+
value: source
33+
}
34+
})
35+
if (matchedDecl.length) {
36+
// add new specifier to the existing import declaration
37+
matchedDecl.get(0).node.specifiers.push(newImportSpecifier)
38+
} else {
39+
const newImportDecl = j.ImportDeclaration(
40+
[newImportSpecifier],
41+
j.stringLiteral(source)
42+
)
43+
44+
const lastImportDecl = root.find(j.ImportDeclaration).at(-1)
45+
if (lastImportDecl.length) {
46+
// add the new import declaration after all other import declarations
47+
lastImportDecl.insertAfter(newImportDecl)
48+
} else {
49+
// add new import declaration at the beginning of the file
50+
root.get().node.program.body.unshift(newImportDecl)
51+
}
52+
}
53+
54+
return root
55+
}

generator/codemods/global-api/vuex.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = function (context) {
2+
// TODO:
3+
}

generator/codemods/rfc09-global-api/__tests__/rfc09-test.js

Lines changed: 0 additions & 5 deletions
This file was deleted.

generator/codemods/rfc09-global-api/index.js

Lines changed: 0 additions & 28 deletions
This file was deleted.

generator/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,5 +93,5 @@ module.exports = (api) => {
9393
// * Partial support of per-component navigation guards. No `beforeRouteEnter`
9494
}
9595

96-
api.transformScript(api.entryFile, require('./codemods/rfc09-global-api'))
96+
api.transformScript(api.entryFile, require('./codemods/global-api'))
9797
}

0 commit comments

Comments
 (0)