Repository: styled-components/babel-plugin-styled-components
Pull request #288 (2020-06-11 09:38:53)

Add topLevelImportPaths option
Related to issue #287 

The main purpose is to be able to transform styled-components wrappers like [xstyled](https://github.com/smooth-code/xstyled).

PS: Couldn't install packages with node v12.17.0 and the repository `yarn.lock`. Hence the updated `yarn.lock`.

probablyup: @salper could you pull from master and rerun yarn to fix the merge conflict?
salper: @probablyup done.

Patch:
diff --git a/src/utils/detectors.js b/src/utils/detectors.js
index 0909060..30c8df4 100644
--- a/src/utils/detectors.js
+++ b/src/utils/detectors.js
@@ -1,3 +1,5 @@
+import { useTopLevelImportPaths } from './options'
+
 const VALID_TOP_LEVEL_IMPORT_PATHS = [
   'styled-components',
   'styled-components/no-tags',
@@ -5,8 +7,10 @@ const VALID_TOP_LEVEL_IMPORT_PATHS = [
   'styled-components/primitives',
 ]
 
-export const isValidTopLevelImport = x =>
-  VALID_TOP_LEVEL_IMPORT_PATHS.includes(x)
+export const isValidTopLevelImport = (x, state) =>
+  [...VALID_TOP_LEVEL_IMPORT_PATHS, ...useTopLevelImportPaths(state)].includes(
+    x
+  )
 
 const localNameCache = {}
 
@@ -28,7 +32,7 @@ export const importLocalName = (name, state, bypassCache = false) => {
       exit(path) {
         const { node } = path
 
-        if (isValidTopLevelImport(node.source.value)) {
+        if (isValidTopLevelImport(node.source.value, state)) {
           for (const specifier of path.get('specifiers')) {
             if (specifier.isImportDefaultSpecifier()) {
               localName = specifier.node.local.name
@@ -107,7 +111,9 @@ export const isWithThemeHelper = t => (tag, state) =>
   t.isIdentifier(tag) && tag.name === importLocalName('withTheme', state)
 
 export const isHelper = t => (tag, state) =>
-  isCSSHelper(t)(tag, state) || isKeyframesHelper(t)(tag, state) || isWithThemeHelper(t)(tag, state)
+  isCSSHelper(t)(tag, state) ||
+  isKeyframesHelper(t)(tag, state) ||
+  isWithThemeHelper(t)(tag, state)
 
 export const isPureHelper = t => (tag, state) =>
   isCSSHelper(t)(tag, state) ||
diff --git a/src/utils/options.js b/src/utils/options.js
index f079618..1b52917 100644
--- a/src/utils/options.js
+++ b/src/utils/options.js
@@ -5,6 +5,8 @@ function getOption({ opts }, name, defaultValue = true) {
 }
 
 export const useDisplayName = state => getOption(state, 'displayName')
+export const useTopLevelImportPaths = state =>
+  getOption(state, 'topLevelImportPaths', [])
 export const useSSR = state => getOption(state, 'ssr', true)
 export const useFileName = state => getOption(state, 'fileName')
 export const useMinify = state => getOption(state, 'minify')
diff --git a/src/visitors/assignStyledRequired.js b/src/visitors/assignStyledRequired.js
index adc30d0..80c5413 100644
--- a/src/visitors/assignStyledRequired.js
+++ b/src/visitors/assignStyledRequired.js
@@ -8,7 +8,7 @@ export default t => (path, state) => {
     path.node.init.arguments &&
     path.node.init.arguments[0] &&
     t.isLiteral(path.node.init.arguments[0]) &&
-    isValidTopLevelImport(path.node.init.arguments[0].value)
+    isValidTopLevelImport(path.node.init.arguments[0].value, state)
   ) {
     state.styledRequired = path.node.id.name
   }


Test patch:
diff --git a/test/fixtures/add-identifier-with-top-level-import-paths/.babelrc b/test/fixtures/add-identifier-with-top-level-import-paths/.babelrc
new file mode 100644
index 0000000..ef8b91b
--- /dev/null
+++ b/test/fixtures/add-identifier-with-top-level-import-paths/.babelrc
@@ -0,0 +1,19 @@
+{
+  "plugins": [
+    [
+      "../../../src",
+      {
+        "displayName": false,
+        "fileName": false,
+        "ssr": true,
+        "topLevelImportPaths": [
+          "@xstyled/styled-components",
+          "@xstyled/styled-components/no-tags",
+          "@xstyled/styled-components/native",
+          "@xstyled/styled-components/primitives"
+        ],
+        "transpileTemplateLiterals": false
+      }
+    ]
+  ]
+}
diff --git a/test/fixtures/add-identifier-with-top-level-import-paths/code.js b/test/fixtures/add-identifier-with-top-level-import-paths/code.js
new file mode 100644
index 0000000..b03b6c1
--- /dev/null
+++ b/test/fixtures/add-identifier-with-top-level-import-paths/code.js
@@ -0,0 +1,10 @@
+import styled from '@xstyled/styled-components'
+
+const Test = styled.div`
+  width: 100%;
+`
+const Test2 = true ? styled.div`` : styled.div``
+const styles = { One: styled.div`` }
+let Component
+Component = styled.div``
+const WrappedComponent = styled(Inner)``
diff --git a/test/fixtures/add-identifier-with-top-level-import-paths/output.js b/test/fixtures/add-identifier-with-top-level-import-paths/output.js
new file mode 100644
index 0000000..7cdb572
--- /dev/null
+++ b/test/fixtures/add-identifier-with-top-level-import-paths/output.js
@@ -0,0 +1,21 @@
+import styled from '@xstyled/styled-components';
+const Test = styled.div.withConfig({
+  componentId: "sc-1mlyrvc-0"
+})`width:100%;`;
+const Test2 = true ? styled.div.withConfig({
+  componentId: "sc-1mlyrvc-1"
+})`` : styled.div.withConfig({
+  componentId: "sc-1mlyrvc-2"
+})``;
+const styles = {
+  One: styled.div.withConfig({
+    componentId: "sc-1mlyrvc-3"
+  })``
+};
+let Component;
+Component = styled.div.withConfig({
+  componentId: "sc-1mlyrvc-4"
+})``;
+const WrappedComponent = styled(Inner).withConfig({
+  componentId: "sc-1mlyrvc-5"
+})``;