Repository: styleguidist/react-styleguidist
Pull request #1380 (2019-06-05 21:42:06)

Fix named export for example components
iss: #1281

Updated examples-loader to import component with named export
Named export of Basic button is now working

I tried suggestion `const name = name$0[name] || name$0.default || name$0;`
CounterButton component is now falling with an error:
```
Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Check the render method of `FunctionComponentWrapper`.

```
<img width="1003" alt="CoutnerButtons is falling" src="https://user-images.githubusercontent.com/5443359/58992307-263f5c00-87f3-11e9-9f11-ac33d073987a.png">

Placeholder from my previous [report](https://github.com/styleguidist/react-styleguidist/issues/1281#issuecomment-498433301) is now working.


mendrew: Ok, I finally get the idea why with this fix we have problems with other components from example.
The reason is simple but I've been debugging a lot till I get it.

### First example: CounterButton. 
Markdown code for CounterButton looks like this 
```js
import Button from '../Button'
let ref
;<div>
  <CounterButton ref={r => (ref = r)} />
  <Button size="small" onClick={() => ref.set(0)}>
    Reset
  </Button>
</div>
```

The error is about this import `import Button from '../Button'`. Button is no longer has default export in my PR and Button should be imported using named import.

### Second example: was tricked by it 
```jsx
import React from 'react'
import Button from 'rsg-example/components/Button'
import Placeholder from 'rsg-example/components/Placeholder'
;<Button>
  <Placeholder />
</Button>
```

In this case I had error with `import Button from 'rsg-example/components/Button'`, I thought it is absolutely different button, but then I looked at the styleguidist config and found this
https://github.com/mendrew/react-styleguidist/blob/1ed431d693af196c8c4d8f84839c60ac06274f2b/examples/basic/styleguide.config.js#L8

It's **the same** button component, and we should import it in the same way with named import.


mendrew: I thinks that ast bulder code update `const name = name$0[name] || name$0.default || name$0;` is enough.

I'm going to remove WIP code and update tests.
mendrew: I've finally updated the PR. It's ready for review.

I'm wondering does it make sense to add named export to some basic example code, just to have this case in examples?

Patch:
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 00000000..68c7bbb6
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,1 @@
+open_collective: styleguidist
diff --git a/docs/Configuration.md b/docs/Configuration.md
index e93715b5..926b0e1b 100644
--- a/docs/Configuration.md
+++ b/docs/Configuration.md
@@ -59,7 +59,24 @@ Your application static assets folder, will be accessible as `/` in the style gu
 
 #### `compilerConfig`
 
-Type: `Object`, default: `{ objectAssign: 'Object.assign' }`
+Type: `Object`, default:
+
+```javascript
+{
+  // Don't include an Object.assign ponyfill, we have our own
+  objectAssign: 'Object.assign',
+  // Transpile only features needed for IE11
+  target: { ie: 11 },
+  transforms: {
+    // Don't throw on ESM imports, we transpile them ourselves
+    modules: false,
+    // Enable tagged template literals for styled-components
+    dangerousTaggedTemplateString: true,
+    // to make async/await work by default (no transformation)
+    asyncAwait: false,
+  },
+}
+```
 
 Styleguidist uses [Bublé](https://buble.surge.sh/guide/) to run ES6 code on the frontend. This config object will be added as the second argument for `buble.transform`.
 
diff --git a/examples/basic/src/components/RandomButton/RandomButton.js b/examples/basic/src/components/RandomButton/RandomButton.js
index 7abe4c19..65f7afbc 100644
--- a/examples/basic/src/components/RandomButton/RandomButton.js
+++ b/examples/basic/src/components/RandomButton/RandomButton.js
@@ -7,7 +7,8 @@ import './RandomButton.css';
 /**
  * Button that changes label on every click.
  */
-export default class RandomButton extends Component {
+// eslint-disable-next-line import/prefer-default-export
+export class RandomButton extends Component {
 	static propTypes = {
 		/**
 		 * List of possible labels.
diff --git a/examples/basic/src/components/RandomButton/Readme.md b/examples/basic/src/components/RandomButton/Readme.md
index 53b99eb2..f5502f38 100644
--- a/examples/basic/src/components/RandomButton/Readme.md
+++ b/examples/basic/src/components/RandomButton/Readme.md
@@ -2,5 +2,6 @@ You can `import` external files in your examples:
 
 ```jsx
 import { all } from 'dog-names'
+import { RandomButton } from '../RandomButton'
 ;<RandomButton variants={all} />
 ```
diff --git a/examples/basic/src/components/RandomButton/index.js b/examples/basic/src/components/RandomButton/index.js
index 081fd2ff..7be7e3f6 100644
--- a/examples/basic/src/components/RandomButton/index.js
+++ b/examples/basic/src/components/RandomButton/index.js
@@ -1,1 +1,2 @@
-export { default } from './RandomButton';
+// eslint-disable-next-line import/prefer-default-export
+export { RandomButton } from './RandomButton';
diff --git a/src/loaders/examples-loader.js b/src/loaders/examples-loader.js
index 54331c1d..36a1936e 100644
--- a/src/loaders/examples-loader.js
+++ b/src/loaders/examples-loader.js
@@ -78,11 +78,19 @@ export default function examplesLoader(source) {
 				b.variableDeclaration('const', [
 					b.variableDeclarator(b.identifier(`${name}$0`), requireIt(requireRequest).toAST()),
 				]),
-				// const name = name$0.default || name$0;
+				// const name = name$0[name] || name$0.default || name$0;
 				b.variableDeclaration('const', [
 					b.variableDeclarator(
 						b.identifier(name),
-						b.logicalExpression('||', b.identifier(`${name}$0.default`), b.identifier(`${name}$0`))
+						b.logicalExpression(
+							'||',
+							b.identifier(`${name}$0['${name}']`),
+							b.logicalExpression(
+								'||',
+								b.identifier(`${name}$0.default`),
+								b.identifier(`${name}$0`)
+							)
+						)
 					),
 				]),
 			])
diff --git a/src/scripts/schemas/config.js b/src/scripts/schemas/config.js
index c8acd49f..a7a8428c 100644
--- a/src/scripts/schemas/config.js
+++ b/src/scripts/schemas/config.js
@@ -41,6 +41,8 @@ module.exports = {
 				modules: false,
 				// Enable tagged template literals for styled-components
 				dangerousTaggedTemplateString: true,
+				// to make async/await work by default (no transformation)
+				asyncAwait: false,
 			},
 		},
 	},


Test patch:
diff --git a/src/client/utils/__tests__/compileCode.spec.js b/src/client/utils/__tests__/compileCode.spec.js
index e301a823..84c2f64a 100644
--- a/src/client/utils/__tests__/compileCode.spec.js
+++ b/src/client/utils/__tests__/compileCode.spec.js
@@ -20,6 +20,19 @@ const foo = bar$0.default || bar$0;"
 `);
 	});
 
+	test('transform async/await is not throw an error', () => {
+		const onError = jest.fn();
+		const result = compileCode(
+			`async function asyncFunction() { return await Promise.resolve(); }`,
+			compilerConfig,
+			onError
+		);
+		expect(onError).not.toHaveBeenCalled();
+		expect(result).toMatchInlineSnapshot(
+			`"async function asyncFunction() { return await Promise.resolve(); }"`
+		);
+	});
+
 	test('transform imports to require() in front of JSX', () => {
 		const result = compileCode(
 			`
diff --git a/src/loaders/__tests__/examples-loader.spec.js b/src/loaders/__tests__/examples-loader.spec.js
index b98324d1..98c750fe 100644
--- a/src/loaders/__tests__/examples-loader.spec.js
+++ b/src/loaders/__tests__/examples-loader.spec.js
@@ -181,7 +181,7 @@ it('should prepend example code with React require()', () => {
 	expect(result).toBeTruthy();
 	expect(() => new Function(result)).not.toThrowError(SyntaxError);
 	expect(result).toMatch(
-		`const React$0 = require('react');\\nconst React = React$0.default || React$0;`
+		`const React$0 = require('react');\\nconst React = React$0['React'] || (React$0.default || React$0);`
 	);
 });
 
@@ -198,7 +198,7 @@ it('should prepend example code with component require()', () => {
 	expect(result).toBeTruthy();
 	expect(() => new Function(result)).not.toThrowError(SyntaxError);
 	expect(result).toMatch(
-		`const FooComponent$0 = require('../foo.js');\\nconst FooComponent = FooComponent$0.default || FooComponent$0;`
+		`const FooComponent$0 = require('../foo.js');\\nconst FooComponent = FooComponent$0['FooComponent'] || (FooComponent$0.default || FooComponent$0);`
 	);
 });
 
@@ -218,10 +218,10 @@ it('should allow explicit import of React and component module', () => {
 	expect(result).toBeTruthy();
 	expect(() => new Function(result)).not.toThrowError(SyntaxError);
 	expect(result).toMatch(
-		`const React$0 = require('react');\\nconst React = React$0.default || React$0;`
+		`const React$0 = require('react');\\nconst React = React$0['React'] || (React$0.default || React$0);`
 	);
 	expect(result).toMatch(
-		`const FooComponent$0 = require('../foo.js');\\nconst FooComponent = FooComponent$0.default || FooComponent$0;`
+		`const FooComponent$0 = require('../foo.js');\\nconst FooComponent = FooComponent$0['FooComponent'] || (FooComponent$0.default || FooComponent$0);`
 	);
 });
 
@@ -241,7 +241,7 @@ it('should works for any Markdown file, without a current component', () => {
 	expect(result).toBeTruthy();
 	expect(() => new Function(result)).not.toThrowError(SyntaxError);
 	expect(result).toMatch(
-		`const React$0 = require('react');\\nconst React = React$0.default || React$0;`
+		`const React$0 = require('react');\\nconst React = React$0['React'] || (React$0.default || React$0);`
 	);
 	expect(result).not.toMatch('undefined');
 });