Repository: styleguidist/react-styleguidist (ts)

Issue:
Import rewrites
The idea is to make example’s code more real-life by allowing you to `import` components like the user would import them in their app, including all dependencies like React. For example:

```js
import React from 'react'
import Button from 'my-awesome-library/Button'
```

Technically it's not needed because both React and the current component are available in the example context by default, but it will make example easier to use, because users could copy code directly to their apps.

To make this possible we'll need to add a new config option like:

```js
rewriteRequire(module) {
  return module.replace('my-awesome-library', '../')
}
```

The only think I'm not sure about is what to do with relative path. 

Pull request description:
Import aliases
Closes #1076

Add new config option `moduleAliases` to define aliases for modules, that you can import in your examples, to make example code more realistic and copypastable:

```javascript
const path = require('path')
module.exports = {
  moduleAliases: {
    'rsg-example': path.resolve(__dirname, 'src')
  }
}
```

````jsx static
// ```jsx inside Markdown
import React from 'react'
import Button from 'rsg-example/components/Button'
import Placeholder from 'rsg-example/components/Placeholder'
````

![image 2018-09-19 at 1 29 23 pm](https://user-images.githubusercontent.com/70067/45750671-0e498d00-bc10-11e8-8ed0-4721f7559154.png)

Check out the [webpack resolve.alias documentation](https://webpack.js.org/configuration/resolve/#resolve-alias) for available syntax.

Patch:
diff --git a/docs/Configuration.md b/docs/Configuration.md
index 9becdf08..c2abcd03 100644
--- a/docs/Configuration.md
+++ b/docs/Configuration.md
@@ -271,9 +271,33 @@ module.exports = {
 }
 ```
 
+#### `moduleAliases`
+
+Type: `object`, optional
+
+Define aliases for modules, that you can import in your examples, to make example code more realistic and copypastable:
+
+```javascript
+const path = require('path')
+module.exports = {
+  moduleAliases: {
+    'rsg-example': path.resolve(__dirname, 'src')
+  }
+}
+```
+
+````jsx static
+// ```jsx inside Markdown
+import React from 'react'
+import Button from 'rsg-example/components/Button'
+import Placeholder from 'rsg-example/components/Placeholder'
+````
+
+Check out the [webpack resolve.alias documentation](https://webpack.js.org/configuration/resolve/#resolve-alias) for available syntax.
+
 #### `mountPointId`
 
-Type: `string`, defaults: `rsg-root`
+Type: `string`, default: `rsg-root`
 
 The ID of a DOM element where Styleguidist mounts.
 
diff --git a/docs/Documenting.md b/docs/Documenting.md
index 2e3a3a53..3b8232fd 100644
--- a/docs/Documenting.md
+++ b/docs/Documenting.md
@@ -251,6 +251,17 @@ import mockData from './mocks'
 ;<Message content={mockData.hello} />
 ````
 
+Or you can explicitly import all your example dependencies, to make examples easier to copy into your app code:
+
+````jsx static
+// ```jsx inside Markdown
+import React from 'react'
+import Button from 'rsg-example/components/Button'
+import Placeholder from 'rsg-example/components/Placeholder'
+````
+
+> **Note:** `rsg-example` module is an alias defined by the [moduleAliases](Configuration.md#modulealiases) config option.
+
 > **Note:** You can only use `import` by editing your Markdown files, not by editing the example code in the browser.
 
 Each example has its own state that you can access as `state` variable and change with `setState()` function. Default state is `{}` and can be set with `initialState`.
diff --git a/examples/basic/src/components/Button/Readme.md b/examples/basic/src/components/Button/Readme.md
index de5fce72..ffe585e7 100644
--- a/examples/basic/src/components/Button/Readme.md
+++ b/examples/basic/src/components/Button/Readme.md
@@ -53,17 +53,19 @@ import Placeholder from '../Placeholder'
 </Button>
 ```
 
-Or you can explicitly import everything:
+Or you can explicitly import everything, to make examples easier to copy into your app code:
 
 ```jsx
 import React from 'react'
-import Button from '../Button'
-import Placeholder from '../Placeholder'
+import Button from 'rsg-example/components/Button'
+import Placeholder from 'rsg-example/components/Placeholder'
 ;<Button>
   <Placeholder />
 </Button>
 ```
 
+_Note: `rsg-example` module is an alias defined by the [moduleAliases](https://react-styleguidist.js.org/docs/configuration.html#modulealiases) config option._
+
 Each example has its own state that you can access at the `state` variable and change with the `setState` function. Default state is `{}`:
 
 ```jsx
diff --git a/examples/basic/styleguide.config.js b/examples/basic/styleguide.config.js
index 143d0ccb..1e1cdcad 100644
--- a/examples/basic/styleguide.config.js
+++ b/examples/basic/styleguide.config.js
@@ -1,8 +1,12 @@
+const path = require('path');
 const { version } = require('./package');
 
 module.exports = {
 	components: 'src/components/**/[A-Z]*.js',
 	defaultExample: true,
+	moduleAliases: {
+		'rsg-example': path.resolve(__dirname, 'src'),
+	},
 	ribbon: {
 		url: 'https://github.com/styleguidist/react-styleguidist',
 	},
diff --git a/src/scripts/make-webpack-config.js b/src/scripts/make-webpack-config.js
index 6ab1af1a..aa39a11d 100644
--- a/src/scripts/make-webpack-config.js
+++ b/src/scripts/make-webpack-config.js
@@ -128,6 +128,13 @@ module.exports = function(config, env) {
 		webpackConfig = mergeWebpackConfig(webpackConfig, config.webpackConfig, env);
 	}
 
+	// Custom aliases
+	if (config.moduleAliases) {
+		webpackConfig = merge(webpackConfig, {
+			resolve: { alias: config.moduleAliases },
+		});
+	}
+
 	// Custom style guide components
 	if (config.styleguideComponents) {
 		forEach(config.styleguideComponents, (filepath, name) => {
diff --git a/src/scripts/schemas/config.js b/src/scripts/schemas/config.js
index f509afe0..19d0c5db 100644
--- a/src/scripts/schemas/config.js
+++ b/src/scripts/schemas/config.js
@@ -126,6 +126,9 @@ module.exports = {
 	logger: {
 		type: 'object',
 	},
+	moduleAliases: {
+		type: 'object',
+	},
 	mountPointId: {
 		type: 'string',
 		default: 'rsg-root',


Test patch:
diff --git a/src/scripts/__tests__/__snapshots__/make-webpack-config.spec.js.snap b/src/scripts/__tests__/__snapshots__/make-webpack-config.spec.js.snap
index 5760d66e..c66e19e8 100644
--- a/src/scripts/__tests__/__snapshots__/make-webpack-config.spec.js.snap
+++ b/src/scripts/__tests__/__snapshots__/make-webpack-config.spec.js.snap
@@ -53,3 +53,17 @@ Object {
   "rsg-components": "~/src/client/rsg-components",
 }
 `;
+
+exports[`should set aliases from moduleAliases option 1`] = `
+Object {
+  "foo": "bar",
+  "rsg-components": "~/src/client/rsg-components",
+}
+`;
+
+exports[`should set aliases from styleguideComponents option 1`] = `
+Object {
+  "rsg-components": "~/src/client/rsg-components",
+  "rsg-components/foo": "bar",
+}
+`;
diff --git a/src/scripts/__tests__/make-webpack-config.spec.js b/src/scripts/__tests__/make-webpack-config.spec.js
index 9cdaa10f..e46f69b2 100644
--- a/src/scripts/__tests__/make-webpack-config.spec.js
+++ b/src/scripts/__tests__/make-webpack-config.spec.js
@@ -70,6 +70,32 @@ it('should set aliases', () => {
 	expect(result.resolve.alias).toMatchSnapshot();
 });
 
+it('should set aliases from moduleAliases option', () => {
+	const result = makeWebpackConfig(
+		{
+			...styleguideConfig,
+			moduleAliases: {
+				foo: 'bar',
+			},
+		},
+		'development'
+	);
+	expect(result.resolve.alias).toMatchSnapshot();
+});
+
+it('should set aliases from styleguideComponents option', () => {
+	const result = makeWebpackConfig(
+		{
+			...styleguideConfig,
+			styleguideComponents: {
+				foo: 'bar',
+			},
+		},
+		'development'
+	);
+	expect(result.resolve.alias).toMatchSnapshot();
+});
+
 it('should prepend requires as webpack entries', () => {
 	const result = makeWebpackConfig(
 		{ ...styleguideConfig, require: ['a/b.js', 'c/d.css'] },
diff --git a/test/run.server.js b/test/run.server.js
index 23a830d8..70c5f18e 100644
--- a/test/run.server.js
+++ b/test/run.server.js
@@ -23,6 +23,9 @@ styleguidist({
 			],
 		},
 	},
+	moduleAliases: {
+		'rsg-example': dir,
+	},
 	logger: {
 		info: console.log,
 		warn: message => console.warn(`Warning: ${message}`),