Skip to content

Commit 0d3a2ab

Browse files
committed
Implement tagless component skipping
1 parent 5a3c538 commit 0d3a2ab

3 files changed

Lines changed: 1743 additions & 17 deletions

File tree

lib/index.js

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
const fs = require('fs');
2+
const chalk = require('chalk');
13
const pkgDir = require('pkg-dir');
24
const globby = require('globby');
5+
const j = require('jscodeshift').withParser('ts');
36
const debug = require('debug')('tagless-ember-components-codemod');
47

58
async function run() {
69
let path = await pkgDir();
7-
await runForPath(path)
10+
await runForPath(path);
811
}
912

1013
async function runForPath(path, options = {}) {
@@ -19,7 +22,79 @@ async function runForPath(path, options = {}) {
1922
debug('componentPaths = %O', componentPaths);
2023

2124
for (let componentPath of componentPaths) {
22-
// TODO skip tagless components (silent)
25+
let dimPath = chalk.dim(componentPath);
26+
27+
let source = fs.readFileSync(componentPath, 'utf8');
28+
29+
let root = j(source);
30+
31+
// find `export default Component.extend({ ... });` AST node
32+
let exportDefaultDeclarations = root.find(j.ExportDefaultDeclaration, {
33+
declaration: {
34+
type: 'CallExpression',
35+
callee: {
36+
type: 'MemberExpression',
37+
object: { name: 'Component' },
38+
property: { name: 'extend' },
39+
},
40+
},
41+
});
42+
43+
if (exportDefaultDeclarations.length !== 1) {
44+
console.log(
45+
chalk.yellow(`${dimPath}: Could not find \`export default Component.extend({ ... });\``)
46+
);
47+
continue;
48+
}
49+
50+
let exportDefaultDeclaration = exportDefaultDeclarations.get();
51+
52+
// find first `{ ... }` inside `Component.extend()` arguments
53+
let extendObjectArgs = exportDefaultDeclaration
54+
.get('declaration', 'arguments')
55+
.filter(path => path.value.type === 'ObjectExpression');
56+
57+
let objectArg = extendObjectArgs[0];
58+
if (!objectArg) {
59+
console.log(
60+
chalk.yellow(
61+
`${dimPath}: Could not find object argument in \`export default Component.extend({ ... });\``
62+
)
63+
);
64+
continue;
65+
}
66+
67+
// find `tagName` property if it exists
68+
let properties = objectArg.get('properties');
69+
70+
let tagName = 'div';
71+
72+
let tagNameProperty = properties.filter(
73+
({ value: node }) =>
74+
node.type === 'ObjectProperty' &&
75+
node.key.type === 'Identifier' &&
76+
node.key.name === 'tagName'
77+
)[0];
78+
if (tagNameProperty) {
79+
let tagNamePath = tagNameProperty.get('value');
80+
if (tagNamePath.value.type !== 'StringLiteral') {
81+
console.log(
82+
chalk.yellow(`${dimPath}: Unexpected \`tagName\` value: ${j(tagNamePath).toSource()}`)
83+
);
84+
continue;
85+
}
86+
87+
tagName = tagNamePath.value.value;
88+
}
89+
90+
// skip tagless components (silent)
91+
if (tagName === '') {
92+
debug(`${componentPath}: tagName detected: %o -> skip`, tagName);
93+
continue;
94+
}
95+
96+
debug(`${componentPath}: tagName detected: %o`, tagName);
97+
2398
// TODO skip components that use `this.element` (warn)
2499
// TODO skip components that use `click()` etc. (warn)
25100

@@ -32,6 +107,8 @@ async function runForPath(path, options = {}) {
32107
// TODO set `tagName: ''` and remove `attributeBindings`, `classNames`, ...
33108
// TODO wrap existing template with root element
34109
}
110+
111+
debug('runForPath() finished');
35112
}
36113

37114
module.exports = { run };

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"chalk": "^2.4.2",
1818
"debug": "^4.1.1",
1919
"globby": "^10.0.1",
20+
"jscodeshift": "^0.6.4",
2021
"pkg-dir": "^4.2.0"
2122
},
2223
"devDependencies": {

0 commit comments

Comments
 (0)