auto-load all files from a folder by wepack's require.context without writing *.stories.js
MIT License
storybook-loader
storybook-loader is a package for storybook to automatically load ALL files in a folder.
storybook-loader analyze the webpack's require.context return value and load the analyzed results to storyies.
After finishing the configuration, you will be free from manually adding story, as storybook-loader will load it for you automatically.
storybook-loader is available as an npm package.
npm install --save--dev storybook-loader
Create xxx.stories.js under the target folder.
import { loadJSStories } from 'storybook-loader';
const req = require.context('./');
loadJSStories(req);
Create sub folder and add js files.
The following structure:
./rootPattern1.js
./folder1/pattern1.js
./folder1/pattern2.js
./folder2/pattern1.jsx
./folder2/pattern2.jsx
will display like this(rootPattern1 will be ignored):
folder1
|-pattern1
|-pattern2
folder2
|-pattern1
|-pattern2
Create xxx.stories.js under the target folder.
storybook 4.x
import { loadMDStories } from 'storybook-loader';
import { doc } from 'storybook-readme';
const req = require.context('./');
const options = {
// decorate md's content
contentFuncList: [
doc,
],
// [optional] hide AddOnPanel
storySubFuncList: [
[
'addParameters',
[{ options: { showAddonPanel: false } }],
],
],
}
loadMDStories(req, options);
storybook 5.x
import { loadMDStories } from 'storybook-loader';
import { doc } from 'storybook-readme';
const req = require.context('./');
const options = {
// decorate md's content
contentFuncList: [
doc,
],
// [optional] hide AddOnPanel
storySubFuncList: [
[
'addParameters',
[{ options: { showPanel: false } }],
],
],
}
loadMDStories(req, options);
Create sub folder and add md files.
The following structure:
./rootPattern1.md
./folder1/pattern1.md
./folder1/pattern2.md
./folder2/pattern1.md
./folder2/pattern2.md
will display like this(rootPattern1 will be ignored):
folder1
|-pattern1
|-pattern2
folder2
|-pattern1
|-pattern2
When you not only like to load js components, but also show notes in control panel.
Create xxx.stories.js under the target folder.
storybook 4.x
import { loadJSWithNotesStories } from 'storybook-loader';
import { withNotes } from '@storybook/addon-notes';
const req = require.context('./');
const options = {
// [optional] you can also addDecorator(withNotes) in config.js
storySubFuncList: [
[
'addDecorator',
[withNotes],
],
],
};
loadJSWithNotesStories(reqList, options);
storybook 5.x
import { loadJSWithNotesStories } from 'storybook-loader';
const req = require.context('./');
loadJSWithNotesStories(reqList);
Create sub folder and add md files.
The following structure:
./folder1/pattern1.js
./folder1/pattern1.md
./folder1/pattern2.js
./folder1/pattern2.md
./folder2/pattern1.jsx
./folder2/pattern1.md
./folder2/pattern2.jsx
will display like this
folder1
|-pattern1 (display folder1/pattern1.md in notes panel)
|-pattern2 (display folder1/pattern2.md in notes panel)
folder2
|-pattern1 (display folder2/pattern1.md in notes panel)
|-pattern2 (display nothing in notes panel)
No. | Parameter | Required | Type | Default | Description |
---|---|---|---|---|---|
1 | requireContext | 〇 | object / object list | instance of require.context OR an object return the same architecture to require.context | |
2 | options | object | { groupByFolder: true, folderNameWhenEmpty: 'ALL' } |
*see options below for more details | |
3 | thirdParamMakerOptions | object | { loader: mdLoader, formatter: formatWithNotesObject } |
*see options below for more details |
Default: []
Description: list of sub functions in storiesOf to call
Attention: parameters of sub function MUST be an array
Example:
-- NO.1 --------------------------------------------------------
storySubFuncList: [
'subFunc1',
[ 'addDecorator', [withNotes] ],
[ 'addParameters', [{ options: { showPanel: false } }] ],
]
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
stories.subFunc1();
stories.addDecorator(withNotes);
stories.addParameters({ options: { showPanel: false } });
Default: [ ramda.identity ]
Description: list of pure functions for decorating file's contents. It's useful when you want to apply hocs(High Order Component) or hofs(High Order Function) to your content like withMUITheme, withLayout...
Attention: functions will receive ONLY ONE parameter -- the contents (could be string or React.Component). If function has more than one parameters, you can use util.unaryFunc to apply the rest parameters and then pass it to contentFuncList.
Example:
-- NO.1 --------------------------------------------------------
function decPrefixMsg(content, msg) {
return `${msg}: ${content}`;
}
contentFuncList: [
util.unaryFunc(decPrefixMsg, ['MyMessage is']),
]
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
stories.add(fileName, decPrefixMsg(content, 'MyMessage is'));
-- NO.2 --------------------------------------------------------
contentFuncList: [
withMUITheme,
withLayout,
]
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
stories.add(fileName, withLayout(withMUITheme(content)));
Default: ''
Description: prefix of stories' name. If you've enabled hierarchyRootSeparator, xxx| will be the name of hierarchyRoot.
Example:
-- NO.1 --------------------------------------------------------
hierarchyRoot: 'Components|'
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
storiesOf('Components|' + folderName, module);
Default: true
Description: use folder name as the root stories' name.
Attention: If you set groupByFolder to false, all stories will be added to ONE root named by folderNameWhenEmpty(default is ALL).
Example:
-- NO.1 --------------------------------------------------------
groupByFolder: true
/Button/Pattern1.js
/Button/Pattern2.js
/TextField/Pattern1.js
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
Button
- Pattern1
- Pattern2
TextField
- Pattern1
-- NO.2 --------------------------------------------------------
groupByFolder: false
/Button/Pattern1.js
/Button/Pattern2.js
/TextField/Pattern1.js
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
ALL
- Pattern1 (the second Pattern1 will be ignored)
- Pattern2
Default: null
Description: function to make 3rd parameter of stories.add(xx, xx, 3rdParam). thirdParamMaker(instance of require.context, filePath).
Attention: this function is called after every single file is loaded.
Example: createMDThirdParamMaker
Default: true
Description: sort files by filename.
Default: (a, b) => a.localeCompare(b)
Description: sort function. sort by files asc as default.
Default: true
Description: display filename in menu without extention.
Example:
-- NO.1 --------------------------------------------------------
noExt: true
/Button/Pattern1.js
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
Button
- Pattern1
-- NO.2 --------------------------------------------------------
noExt: false
/Button/Pattern1.js
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
Button
- Pattern1.js
Default: null
Description: remove extention regexp.
Attention: if noExt is true, will use noExtRegExp > includeRegExp > regExpFromRequireContext.
Example: /\.md$/ to remove markdown's extention
Default: null
Description: regexp for include files by file's full path.
Attention: will use includeRegExp > regExpFromRequireContext.
Example: /\.md$/ to add *.md files only.
Default: null
Description: regexp for exclude files by file's full path.
Example: /\.stories.js$/ to exclude all *.stories.js.
Default: true
Description: ignore files under root folder (. folder)
Example: -- NO.1 -------------------------------------------------------- ignoreDotFolder: true
./Pattern1.js
/Button/Pattern1.js
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
Button
- Pattern1
-- NO.2 --------------------------------------------------------
ignoreDotFolder: false
./Pattern1.js
/Button/Pattern1.js
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
.
- Pattern1
Button
- Pattern1
Default: .
Description: used as folder name when it's a dot(.)
Example: -- NO.1 -------------------------------------------------------- ignoreDotFolder: false dotFolderName: 'RootFolder'
./Pattern1.js
/Button/Pattern1.js
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
RootFolder
- Pattern1
Button
- Pattern1
ONLY nessacerry when use loadJSWithNotesStories or loadJsonWithNotesStories. Both of them are using createMDThirdParamMaker to make 3rd parameter in stories.add(xx, xx, 3rd param).
Default: mdLoader
Description: loader to load files for making third param
Default: formatWithNotesObject() in createMDThirdParamMaker
Description: format the content
Example
function formatWithNotesObject(content) {
return {
notes: {
markdown: content,
},
};
}
This project is licensed under the terms of the MIT license.