Repository: ember-codemods/ember-angle-brackets-codemod
Pull request #437 (2021-03-24 18:33:27)

[Feature]: Add ability to convert only specific component invocations with each run
Solves issue: https://github.com/ember-codemods/ember-angle-brackets-codemod/issues/436

This is my second-ever open-source PR - please provide feedback and suggestions on how to improve, I'd be happy to make the edits. ✏️ 

tylerturdenpants: LGTM. I'll cut a release tomorrow.  Thank you!
kcarmonamurphy: hey @tylerturdenpants just wondering if you still plan on merging this PR into the codebase? We've been using the forked version in our org and it's been working fine for us.

Patch:
diff --git a/README.md b/README.md
index 99ecf81..eda2281 100644
--- a/README.md
+++ b/README.md
@@ -179,6 +179,18 @@ Output:
   <SomeComponent data-test-foo={{true}} aria-label="bar" @foo={{true}} />
 ```
 
+### Converting specific components only
+
+If you would like to only convert certain component invocations to use the angle brackets syntax, use the `components` configuration setting and specify component names. For example, with the configuration below, only the `{{baz}}` and `{{bat}}` components will be converted, leaving everything else intact.
+
+**config/anglebrackets-codemod-config.json**
+
+```js
+{
+  "components": ["baz", "bat"]
+}
+```
+
 ## Debugging Workflow
 
 Oftentimes, you want to debug the codemod or the transform to identify issues with the code or to understand
diff --git a/transforms/angle-brackets/index.js b/transforms/angle-brackets/index.js
index 3763115..293a865 100755
--- a/transforms/angle-brackets/index.js
+++ b/transforms/angle-brackets/index.js
@@ -17,6 +17,10 @@ function getOptions() {
       options.helpers = config.helpers;
     }
 
+    if (config.components) {
+      options.components = config.components;
+    }
+
     if (config.skipAttributesThatMatchRegex) {
       options.skipAttributesThatMatchRegex = config.skipAttributesThatMatchRegex;
     }
diff --git a/transforms/angle-brackets/transform.js b/transforms/angle-brackets/transform.js
index 8e4e8a9..bab4559 100755
--- a/transforms/angle-brackets/transform.js
+++ b/transforms/angle-brackets/transform.js
@@ -445,6 +445,9 @@ function transformToAngleBracket(fileInfo, config, invokableData) {
   return {
     MustacheStatement(node) {
       const tagName = `${node.path && node.path.original}`;
+
+      if (config.components && !config.components.includes(tagName)) return;
+
       // Don't change attribute statements
       const isValidMustache =
         node.loc.source !== '(synthetic)' &&
@@ -460,6 +463,9 @@ function transformToAngleBracket(fileInfo, config, invokableData) {
     },
     BlockStatement(node) {
       let tagName = `${node.path.original}`;
+
+      if (config.components && !config.components.includes(tagName)) return;
+
       if (
         !shouldIgnoreMustacheStatement(node.path.original, config, invokableData) ||
         isWallStreet(tagName)


Test patch:
diff --git a/transforms/angle-brackets/transform.test.js b/transforms/angle-brackets/transform.test.js
index 5a155c6..45eef9b 100644
--- a/transforms/angle-brackets/transform.test.js
+++ b/transforms/angle-brackets/transform.test.js
@@ -1050,6 +1050,32 @@ test('custom-options', () => {
   `);
 });
 
+test('specific-components', () => {
+  let input = `
+    {{some-component foo=true}}
+    {{my-component foo=true}}
+    {{x-foo foo=true}}
+    {{#my-card as |card|}}
+      {{card.title title="My Card Title"}}
+    {{/my-card}}
+  `;
+
+  let options = {
+    components: ['some-component', 'x-foo', 'my-card'],
+  };
+
+  expect(runTest('specific-components.hbs', input, options)).toMatchInlineSnapshot(`
+    "
+        <SomeComponent @foo={{true}} />
+        {{my-component foo=true}}
+        <XFoo @foo={{true}} />
+        <MyCard as |card|>
+          {{card.title title=\\"My Card Title\\"}}
+        </MyCard>
+      "
+  `);
+});
+
 test('skip-attributes', () => {
   let input = `
     {{some-component data-test-foo=true aria-label="bar" foo=true}}