mirror of
https://github.com/storybookjs/storybook.git
synced 2025-04-02 05:03:44 +08:00
Merge branch 'refactoring/remove-mantra' into refactoring/remove-mantra-ui-overhaul
This commit is contained in:
commit
d2fb2eca92
@ -39,6 +39,7 @@ jobs:
|
||||
- examples/official-storybook/node_modules
|
||||
- examples/polymer-cli/node_modules
|
||||
- examples/vue-kitchen-sink/node_modules
|
||||
- examples/svelte-kitchen-sink/node_modules
|
||||
- examples/marko-cli/node_modules
|
||||
- save_cache:
|
||||
name: "Cache core dist"
|
||||
@ -72,6 +73,11 @@ jobs:
|
||||
command: |
|
||||
cd examples/vue-kitchen-sink
|
||||
yarn build-storybook
|
||||
- run:
|
||||
name: "Build svelte kitchen-sink"
|
||||
command: |
|
||||
cd examples/svelte-kitchen-sink
|
||||
yarn build-storybook
|
||||
- run:
|
||||
name: "Build angular-cli"
|
||||
command: |
|
||||
@ -126,6 +132,11 @@ jobs:
|
||||
command: |
|
||||
cd examples/vue-kitchen-sink
|
||||
yarn storybook --smoke-test
|
||||
- run:
|
||||
name: "Run svelte kitchen-sink (smoke test)"
|
||||
command: |
|
||||
cd examples/svelte-kitchen-sink
|
||||
yarn storybook --smoke-test
|
||||
- run:
|
||||
name: "Run angular-cli (smoke test)"
|
||||
command: |
|
||||
|
@ -3,6 +3,6 @@ root = true
|
||||
[*]
|
||||
end_of_line = lf
|
||||
|
||||
[*.{js,json,ts,vue,html}]
|
||||
[*.{js,json,ts,vue,svelte,html}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
6
.github/CODEOWNERS
vendored
6
.github/CODEOWNERS
vendored
@ -13,7 +13,7 @@
|
||||
/addons/links/ @hypnosphi @ndelangen
|
||||
/addons/notes/ @alexandrebodin
|
||||
/addons/options/ @danielduan @UsulPro
|
||||
/addons/storyshots/ @igor-dv @thomasbertet @hypnosphi
|
||||
/addons/storyshots/ @igor-dv @thomasbertet @hypnosphi
|
||||
/addons/storysource/ @igor-dv
|
||||
/addons/viewport/ @saponifi3d
|
||||
|
||||
@ -22,16 +22,18 @@
|
||||
/app/react/ @xavcz @shilman @thomasbertet
|
||||
/app/react-native/ @rmevans9 @danielduan @Gongreg @tmeasday
|
||||
/app/vue/ @thomasbertet @kazupon
|
||||
/app/svelte/ @plumpNation
|
||||
|
||||
/docs/ @ndelangen @shilman @hypnosphi
|
||||
|
||||
/examples/angular-cli/ @igor-dv @alterx
|
||||
/examples/cra-kitchen-sink/ @ndelangen @UsulPro @hypnosphi
|
||||
/examples/cra-kitchen-sink/ @ndelangen @UsulPro @hypnosphi
|
||||
/examples/crna-kitchen-sink/ @Gongreg @danielduan
|
||||
/examples/official-storybook/ @hypnosphi @danielduan @UsulPro
|
||||
/examples/polymer-cli/ @naipath @igor-dv
|
||||
/examples/react-native-vanilla/ @tmeasday @danielduan
|
||||
/examples/vue-kitchen-sink/ @igor-dv @alexandrebodin
|
||||
/examples/svelte-kitchen-sink/ @plumpNation
|
||||
|
||||
/lib/addons/ @ndelangen @theinterned
|
||||
/lib/channel-postmessage/ @mnmtanish @ndelangen
|
||||
|
1
.github/autolabeler.yml
vendored
1
.github/autolabeler.yml
vendored
@ -17,6 +17,7 @@
|
||||
'app: react-native': ["app/react-native/**"]
|
||||
'app: react': ["app/react/**"]
|
||||
'app: vue': ["app/vue/**"]
|
||||
'app: svelte': ["app/svelte/**"]
|
||||
'app: mithril': ["app/mithril/**"]
|
||||
'babel / webpack': ["webpack", "babel"]
|
||||
'cli': ["lib/cli/**"]
|
||||
|
@ -15,7 +15,7 @@ enum class StorybookApp(val appName: String, val exampleDir: String, val merged:
|
||||
HTML("HTML", "html-kitchen-sink"),
|
||||
MARKO("Marko", "marko-cli"),
|
||||
HYPERAPP("Hyperapp", "hyperapp-kitchen-sink", false),
|
||||
SVELTE("Svelte", "svelte-kitchen-sink", false);
|
||||
SVELTE("Svelte", "svelte-kitchen-sink");
|
||||
|
||||
val lowerName = appName.toLowerCase()
|
||||
|
||||
|
@ -1,19 +1,19 @@
|
||||
## Addon / Framework Support Table
|
||||
|
||||
| |[React](app/react)|[React Native](app/react-native)|[Vue](app/vue)|[Angular](app/angular)| [Polymer](app/polymer)| [Mithril](app/mithril)| [HTML](app/html)| [Marko](app/marko)|
|
||||
| ----------- |:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|
|
||||
|[a11y](addons/a11y) |+| |+|+|+|+|+|+|
|
||||
|[actions](addons/actions) |+|+|+|+|+|+|+|+|
|
||||
|[backgrounds](addons/backgrounds) |+| |+|+|+|+|+|+|
|
||||
|[centered](addons/centered) |+| |+|+| |+|+| |
|
||||
|[events](addons/events) |+| |+|+|+|+|+|+|
|
||||
|[graphql](addons/graphql) |+| | | | | | | |
|
||||
|[info](addons/info) |+| | | | | | | |
|
||||
|[jest](addons/jest) |+| | |+| | |+| |
|
||||
|[knobs](addons/knobs) |+|+|+|+|+|+|+|+|
|
||||
|[links](addons/links) |+|+|+|+|+|+|+| |
|
||||
|[notes](addons/notes) |+| |+|+|+|+|+| |
|
||||
|[options](addons/options) |+|+|+|+|+|+|+| |
|
||||
|[storyshots](addons/storyshots) |+|+|+|+| | |+| |
|
||||
|[storysource](addons/storysource)|+| |+|+|+|+|+|+|
|
||||
|[viewport](addons/viewport) |+| |+|+|+|+|+|+|
|
||||
| |[React](app/react)|[React Native](app/react-native)|[Vue](app/vue)|[Angular](app/angular)| [Polymer](app/polymer)| [Mithril](app/mithril)| [HTML](app/html)| [Marko](app/marko)| [Svelte](app/svelte)|
|
||||
| ----------- |:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|
|
||||
|[a11y](addons/a11y) |+| |+|+|+|+|+|+| |
|
||||
|[actions](addons/actions) |+|+|+|+|+|+|+|+|+|
|
||||
|[backgrounds](addons/backgrounds) |+| |+|+|+|+|+|+|+|
|
||||
|[centered](addons/centered) |+| |+|+| |+|+| |+|
|
||||
|[events](addons/events) |+| |+|+|+|+|+|+| |
|
||||
|[graphql](addons/graphql) |+| | | | | | | | |
|
||||
|[info](addons/info) |+| | | | | | | | |
|
||||
|[jest](addons/jest) |+| | |+| | |+| | |
|
||||
|[knobs](addons/knobs) |+|+|+|+|+|+|+|+|+|
|
||||
|[links](addons/links) |+|+|+|+|+|+|+| |+|
|
||||
|[notes](addons/notes) |+| |+|+|+|+|+| |+|
|
||||
|[options](addons/options) |+|+|+|+|+|+|+| |+|
|
||||
|[storyshots](addons/storyshots) |+|+|+|+| | |+| |+|
|
||||
|[storysource](addons/storysource)|+| |+|+|+|+|+|+|+|
|
||||
|[viewport](addons/viewport) |+| |+|+|+|+|+|+|+|
|
||||
|
@ -53,7 +53,7 @@ You can use the `--update` flag to update snapshots or screenshots as needed.
|
||||
|
||||
You can also pick suites from CLI. Suites available are listed below.
|
||||
|
||||
##### Core & React & Vue Tests
|
||||
##### Core & React & Vue & Svelte Tests
|
||||
|
||||
`yarn test --core`
|
||||
|
||||
@ -72,7 +72,7 @@ Before these tests are ran, the project must be bootstrapped with the React Nati
|
||||
`yarn test --image`
|
||||
|
||||
This option executes tests from `<rootdir>/examples/official-storybook`
|
||||
In order for the image snapshots to be correctly generated, you must have static build of the storybook up-to-date :
|
||||
In order for the image snapshots to be correctly generated, you must have static build of the storybook up-to-date :
|
||||
|
||||
```javascript
|
||||
cd examples/official-storybook
|
||||
|
@ -77,6 +77,7 @@ For additional help, join us [in our Slack](https://now-examples-slackin-rrirkqo
|
||||
- [Mithril](app/mithril) <sup>alpha</sup>
|
||||
- [Marko](app/marko) <sup>alpha</sup>
|
||||
- [HTML](app/html) <sup>alpha</sup>
|
||||
- [Svelte](app/svelte) <sup>alpha</sup>
|
||||
|
||||
### Sub Projects
|
||||
|
||||
@ -115,6 +116,7 @@ See [Addon / Framework Support Table](ADDONS_SUPPORT.md)
|
||||
- [Mithril](https://storybooks-mithril.netlify.com/)
|
||||
- [Marko](https://storybooks-marko.netlify.com/)
|
||||
- [HTML](https://storybooks-html.netlify.com/)
|
||||
- [Svelte](https://storybooks-svelte.netlify.com/)
|
||||
|
||||
### 3.4
|
||||
- [React Official](https://release-3-4--storybooks-official.netlify.com)
|
||||
|
@ -2,7 +2,7 @@ import addons, { makeDecorator } from '@storybook/addons';
|
||||
import CoreEvents from '@storybook/core-events';
|
||||
import deprecate from 'util-deprecate';
|
||||
|
||||
import Events, { ADDON_ID } from './constants';
|
||||
import Events from './constants';
|
||||
|
||||
let prevBackgrounds;
|
||||
|
||||
@ -12,7 +12,7 @@ const subscription = () => () => {
|
||||
};
|
||||
|
||||
export const withBackgrounds = makeDecorator({
|
||||
name: ADDON_ID,
|
||||
name: 'withBackgrounds',
|
||||
parameterName: 'backgrounds',
|
||||
skipIfNoParametersOrOptions: true,
|
||||
allowDeprecatedUsage: true,
|
||||
|
@ -47,6 +47,25 @@ storiesOf('MyComponent', module)
|
||||
}));
|
||||
```
|
||||
|
||||
example for Svelte:
|
||||
|
||||
```js
|
||||
import { storiesOf } from '@storybook/svelte';
|
||||
import Centered from '@storybook/addon-centered/svelte';
|
||||
|
||||
import Component from '../Component.svelte';
|
||||
|
||||
storiesOf('Addon|Centered', module)
|
||||
.addDecorator(Centered)
|
||||
.add('rounded', () => ({
|
||||
Component,
|
||||
data: {
|
||||
rounded: true,
|
||||
text: "Look, I'm centered!",
|
||||
},
|
||||
}))
|
||||
```
|
||||
|
||||
example for Mithril:
|
||||
|
||||
```js
|
||||
@ -96,7 +115,7 @@ storiesOf('Addon|Centered', module)
|
||||
)
|
||||
.addDecorator(centered)
|
||||
.add('centered template', () => ({
|
||||
template: `<storybook-button-component
|
||||
template: `<storybook-button-component
|
||||
[text]="text" (onClick)="onClick($event)">
|
||||
</storybook-button-component>`,
|
||||
props: {
|
||||
@ -137,6 +156,19 @@ configure(function () {
|
||||
}, module);
|
||||
```
|
||||
|
||||
example for Svelte:
|
||||
|
||||
```js
|
||||
import { configure, addDecorator } from '@storybook/svelte';
|
||||
import Centered from '@storybook/addon-centered/svelte';
|
||||
|
||||
addDecorator(Centered);
|
||||
|
||||
configure(function () {
|
||||
//...
|
||||
}, module);
|
||||
```
|
||||
|
||||
example for Mithril:
|
||||
|
||||
```js
|
||||
|
16
addons/centered/src/components/Centered.svelte
Normal file
16
addons/centered/src/components/Centered.svelte
Normal file
@ -0,0 +1,16 @@
|
||||
<div class="svelte-centered-wrapper" style="{style}">
|
||||
<div class="svelte-centered-container" style="{innerStyle}">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
style: '',
|
||||
innerStyle: ''
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
21
addons/centered/src/helpers/json2CSS.js
Normal file
21
addons/centered/src/helpers/json2CSS.js
Normal file
@ -0,0 +1,21 @@
|
||||
import { document } from 'global';
|
||||
|
||||
/**
|
||||
* Not all frameworks support an object for the style attribute but we want all to
|
||||
* consume `styles.json`. Since `styles.json` uses standard style properties for keys,
|
||||
* we can just set them on an element and then get the string result of that element's
|
||||
* `style` attribute. This also means that invalid styles are filtered out.
|
||||
*
|
||||
* @param {Object} jsonStyles
|
||||
* @returns {string}
|
||||
* @see https://stackoverflow.com/questions/38533544/jsx-css-to-inline-styles
|
||||
*/
|
||||
export default function jsonToCss(jsonStyles) {
|
||||
const frag = document.createElement('div');
|
||||
|
||||
Object.keys(jsonStyles).forEach(key => {
|
||||
frag.style[key] = jsonStyles[key];
|
||||
});
|
||||
|
||||
return frag.getAttribute('style');
|
||||
}
|
25
addons/centered/src/svelte.js
Normal file
25
addons/centered/src/svelte.js
Normal file
@ -0,0 +1,25 @@
|
||||
import Centered from './components/Centered.svelte';
|
||||
import styles from './styles';
|
||||
import json2CSS from './helpers/json2CSS';
|
||||
|
||||
const centeredStyles = {
|
||||
/** @type {string} */
|
||||
style: json2CSS(styles.style),
|
||||
/** @type {string} */
|
||||
innerStyle: json2CSS(styles.innerStyle),
|
||||
};
|
||||
|
||||
/**
|
||||
* This functionality works by passing the svelte story component into another
|
||||
* svelte component that has the single purpose of centering the story component
|
||||
* using a wrapper and container.
|
||||
*
|
||||
* We use the special element <svelte:component /> to achieve this.
|
||||
*
|
||||
* @see https://svelte.technology/guide#svelte-component
|
||||
*/
|
||||
export default function(storyFn) {
|
||||
const { Component: OriginalComponent, data, on } = storyFn();
|
||||
|
||||
return { Component: OriginalComponent, data, on, Wrapper: Centered, WrapperData: centeredStyles };
|
||||
}
|
1
addons/centered/svelte.js
Normal file
1
addons/centered/svelte.js
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require('./dist/svelte');
|
@ -6,6 +6,7 @@ module.exports = {
|
||||
'@storybook/react',
|
||||
'@storybook/react-native',
|
||||
'@storybook/vue',
|
||||
'@storybook/svelte',
|
||||
'enzyme',
|
||||
],
|
||||
},
|
||||
|
@ -0,0 +1,32 @@
|
||||
import global from 'global';
|
||||
import hasDependency from '../hasDependency';
|
||||
import configure from '../configure';
|
||||
|
||||
function test(options) {
|
||||
return (
|
||||
options.framework === 'svelte' || (!options.framework && hasDependency('@storybook/svelte'))
|
||||
);
|
||||
}
|
||||
|
||||
function load(options) {
|
||||
global.STORYBOOK_ENV = 'svelte';
|
||||
|
||||
const { configPath, config } = options;
|
||||
const storybook = require.requireActual('@storybook/svelte');
|
||||
|
||||
configure({ configPath, config, storybook });
|
||||
|
||||
return {
|
||||
framework: 'svelte',
|
||||
renderTree: require.requireActual('./renderTree').default,
|
||||
renderShallowTree: () => {
|
||||
throw new Error('Shallow renderer is not supported for svelte');
|
||||
},
|
||||
storybook,
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
load,
|
||||
test,
|
||||
};
|
@ -0,0 +1,29 @@
|
||||
import { document } from 'global';
|
||||
|
||||
/**
|
||||
* Provides functionality to convert your raw story to the resulting markup.
|
||||
*
|
||||
* Storybook snapshots need the rendered markup that svelte outputs,
|
||||
* but since we only have the story config data ({ Component, data }) in
|
||||
* the Svelte stories, we need to mount the component, and then return the
|
||||
* resulting HTML.
|
||||
*
|
||||
* If we don't render to HTML, we will get a snapshot of the raw story
|
||||
* i.e. ({ Component, data }).
|
||||
*/
|
||||
function getRenderedTree(story, context) {
|
||||
const { Component, data } = story.render(context);
|
||||
|
||||
// We need to create a target to mount onto.
|
||||
const target = document.createElement('section');
|
||||
|
||||
new Component({ target, data }); // eslint-disable-line
|
||||
|
||||
// Classify the target so that it is clear where the markup
|
||||
// originates from, and that it is specific for snapshot tests.
|
||||
target.className = 'storybook-snapshot-container';
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
export default getRenderedTree;
|
@ -19,6 +19,6 @@
|
||||
"puppeteer": "^1.6.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@storybook/addon-storyshots": "4.0.0-alpha.9"
|
||||
"@storybook/addon-storyshots": "4.0.0-alpha.16"
|
||||
}
|
||||
}
|
||||
|
4
app/angular/src/server/angular-cli_config.js
vendored
4
app/angular/src/server/angular-cli_config.js
vendored
@ -80,7 +80,9 @@ export function applyAngularCliWebpackConfig(baseConfig, cliWebpackConfigOptions
|
||||
// cliStyleConfig.entry adds global style files to the webpack context
|
||||
const entry = {
|
||||
...baseConfig.entry,
|
||||
...cliStyleConfig.entry,
|
||||
iframe: []
|
||||
.concat(baseConfig.entry.iframe)
|
||||
.concat(Object.values(cliStyleConfig.entry).reduce((acc, item) => acc.concat(item), [])),
|
||||
};
|
||||
|
||||
const mod = {
|
||||
|
@ -47,10 +47,11 @@
|
||||
"case-sensitive-paths-webpack-plugin": "^2.1.2",
|
||||
"commander": "^2.17.0",
|
||||
"dotenv-webpack": "^1.5.7",
|
||||
"ejs": "^2.6.1",
|
||||
"express": "^4.16.3",
|
||||
"find-cache-dir": "^2.0.0",
|
||||
"generate-page-webpack-plugin": "^1.0.0",
|
||||
"global": "^4.3.2",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"json5": "^1.0.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"raw-loader": "^0.5.1",
|
||||
|
2
app/react-native/src/server/config.js
vendored
2
app/react-native/src/server/config.js
vendored
@ -116,7 +116,7 @@ export default function(configType, baseConfig, projectDir, configDir) {
|
||||
|
||||
if (typeof customConfig === 'function') {
|
||||
logger.info('=> Loading custom webpack config (full-control mode).');
|
||||
return customConfig(config, configType, defaultConfig);
|
||||
return customConfig(config, configType, defaultConfig, configDir);
|
||||
}
|
||||
|
||||
logger.info('=> Loading custom webpack config.');
|
||||
|
@ -4,54 +4,73 @@ import { getEnvironment } from 'universal-dotenv';
|
||||
import Dotenv from 'dotenv-webpack';
|
||||
import WatchMissingNodeModulesPlugin from 'react-dev-utils/WatchMissingNodeModulesPlugin';
|
||||
import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin';
|
||||
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||
import { indexHtmlPath } from '@storybook/core/server';
|
||||
import { version } from '../../../package.json';
|
||||
import { includePaths, excludePaths, nodeModulesPaths } from './utils';
|
||||
|
||||
const getConfig = options => ({
|
||||
mode: 'development',
|
||||
devtool: '#cheap-module-eval-source-map',
|
||||
entry: {
|
||||
manager: [require.resolve('../../manager')],
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, 'dist'),
|
||||
filename: 'static/[name].bundle.js',
|
||||
publicPath: '/',
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
data: {
|
||||
version,
|
||||
},
|
||||
template: indexHtmlPath,
|
||||
}),
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new CaseSensitivePathsPlugin(),
|
||||
new WatchMissingNodeModulesPlugin(nodeModulesPaths),
|
||||
new webpack.DefinePlugin(getEnvironment().webpack),
|
||||
new Dotenv({ silent: true }),
|
||||
new webpack.DefinePlugin({
|
||||
storybookOptions: JSON.stringify(options),
|
||||
}),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.jsx?$/,
|
||||
loader: require.resolve('babel-loader'),
|
||||
query: require('./babel.js'), // eslint-disable-line
|
||||
include: includePaths,
|
||||
exclude: excludePaths,
|
||||
},
|
||||
{
|
||||
test: /\.md$/,
|
||||
loader: require.resolve('raw-loader'),
|
||||
},
|
||||
import GeneratePagePlugin from 'generate-page-webpack-plugin';
|
||||
|
||||
import { getManagerHeadHtml } from '@storybook/core/server';
|
||||
|
||||
import { includePaths, excludePaths, nodeModulesPaths } from './utils';
|
||||
import { version } from '../../../package.json';
|
||||
|
||||
const getConfig = options => {
|
||||
const entriesMeta = {
|
||||
manager: {
|
||||
headHtmlSnippet: getManagerHeadHtml(options.configDir, process.env),
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
mode: 'development',
|
||||
devtool: '#cheap-module-eval-source-map',
|
||||
entry: {
|
||||
manager: [require.resolve('../../manager')],
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, 'dist'),
|
||||
filename: 'static/[name].bundle.js',
|
||||
publicPath: '/',
|
||||
},
|
||||
plugins: [
|
||||
new GeneratePagePlugin(
|
||||
{
|
||||
template: require.resolve('@storybook/core/dist/server/templates/index.html.ejs'),
|
||||
// eslint-disable-next-line global-require
|
||||
parser: require('ejs'),
|
||||
filename: entry => (entry === 'manager' ? 'index' : entry),
|
||||
},
|
||||
{
|
||||
data: { version },
|
||||
headHtmlSnippet: entry =>
|
||||
entriesMeta[entry] ? entriesMeta[entry].headHtmlSnippet : null,
|
||||
bodyHtmlSnippet: entry =>
|
||||
entriesMeta[entry] ? entriesMeta[entry].bodyHtmlSnippet : null,
|
||||
}
|
||||
),
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new CaseSensitivePathsPlugin(),
|
||||
new WatchMissingNodeModulesPlugin(nodeModulesPaths),
|
||||
new webpack.DefinePlugin(getEnvironment().webpack),
|
||||
new Dotenv({ silent: true }),
|
||||
new webpack.DefinePlugin({
|
||||
storybookOptions: JSON.stringify(options),
|
||||
}),
|
||||
],
|
||||
},
|
||||
});
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.jsx?$/,
|
||||
loader: require.resolve('babel-loader'),
|
||||
query: require('./babel.js'), // eslint-disable-line
|
||||
include: includePaths,
|
||||
exclude: excludePaths,
|
||||
},
|
||||
{
|
||||
test: /\.md$/,
|
||||
loader: require.resolve('raw-loader'),
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default getConfig;
|
||||
|
@ -2,8 +2,9 @@ import path from 'path';
|
||||
import webpack from 'webpack';
|
||||
import { getEnvironment } from 'universal-dotenv';
|
||||
import Dotenv from 'dotenv-webpack';
|
||||
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||
import { indexHtmlPath } from '@storybook/core/server';
|
||||
import GeneratePagePlugin from 'generate-page-webpack-plugin';
|
||||
|
||||
import { getManagerHeadHtml } from '@storybook/core/dist/server/utils';
|
||||
import { version } from '../../../package.json';
|
||||
import { includePaths, excludePaths } from './utils';
|
||||
|
||||
@ -26,13 +27,18 @@ const getConfig = options => {
|
||||
publicPath: '/',
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
data: {
|
||||
version,
|
||||
new GeneratePagePlugin(
|
||||
{
|
||||
template: require.resolve('@storybook/core/dist/server/templates/index.html.ejs'),
|
||||
// eslint-disable-next-line global-require
|
||||
parser: require('ejs'),
|
||||
filename: entry => (entry === 'manager' ? 'index' : entry),
|
||||
},
|
||||
template: indexHtmlPath,
|
||||
}),
|
||||
{
|
||||
data: { version },
|
||||
headHtmlSnippet: getManagerHeadHtml(options.configDir, process.env),
|
||||
}
|
||||
),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': '"production"',
|
||||
storybookOptions: JSON.stringify(options),
|
||||
|
3
app/react-native/src/server/middleware.js
vendored
3
app/react-native/src/server/middleware.js
vendored
@ -20,7 +20,8 @@ function getMiddleware(configDir) {
|
||||
return () => {};
|
||||
}
|
||||
|
||||
export default function({ projectDir, configDir, ...options }) {
|
||||
export default function(options) {
|
||||
const { projectDir, configDir } = options;
|
||||
// Build the webpack configuration using the `baseConfig`
|
||||
// custom `.babelrc` file and `webpack.config.js` files
|
||||
const environment = options.environment || 'DEVELOPMENT';
|
||||
|
2
app/svelte/.npmignore
Normal file
2
app/svelte/.npmignore
Normal file
@ -0,0 +1,2 @@
|
||||
docs
|
||||
.babelrc
|
33
app/svelte/README.md
Normal file
33
app/svelte/README.md
Normal file
@ -0,0 +1,33 @@
|
||||
# Storybook for Svelte
|
||||
|
||||
Storybook for Svelte is a UI development environment for your Svelte components.
|
||||
With it, you can visualize different states of your UI components and develop them interactively.
|
||||
|
||||

|
||||
|
||||
Storybook runs outside of your app.
|
||||
So you can develop UI components in isolation without worrying about app specific dependencies and requirements.
|
||||
|
||||
## Getting Started
|
||||
|
||||
```sh
|
||||
npm i -g @storybook/cli
|
||||
cd my-svelte-app
|
||||
getstorybook
|
||||
```
|
||||
|
||||
For more information visit: [storybook.js.org](https://storybook.js.org)
|
||||
|
||||
* * *
|
||||
|
||||
Storybook also comes with a lot of [addons](https://storybook.js.org/addons/introduction) and a great API to customize as you wish.
|
||||
You can also build a [static version](https://storybook.js.org/basics/exporting-storybook) of your storybook and deploy it anywhere you want.
|
||||
|
||||
## TODOs
|
||||
|
||||
- [ ] Support `addon-info`
|
||||
- [ ] Support Svelte markup directly in stories
|
||||
- [ ] Add Svelte storybook generator
|
||||
- [ ] Provide stories that show advanced Svelte use cases
|
||||
- [ ] Hydratable
|
||||
- [ ] Advanced mount options
|
5
app/svelte/bin/build.js
Executable file
5
app/svelte/bin/build.js
Executable file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
process.env.NODE_ENV = process.env.NODE_ENV || 'production';
|
||||
|
||||
require('../dist/server/build');
|
3
app/svelte/bin/index.js
Executable file
3
app/svelte/bin/index.js
Executable file
@ -0,0 +1,3 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
require('../dist/server');
|
35
app/svelte/package.json
Normal file
35
app/svelte/package.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "@storybook/svelte",
|
||||
"version": "4.0.0-alpha.16",
|
||||
"description": "Storybook for Svelte: Develop Svelte Component in isolation with Hot Reloading.",
|
||||
"homepage": "https://github.com/storybooks/storybook/tree/master/apps/svelte",
|
||||
"bugs": {
|
||||
"url": "https://github.com/storybooks/storybook/issues"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/storybooks/storybook.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"main": "dist/client/index.js",
|
||||
"jsnext:main": "src/client/index.js",
|
||||
"bin": {
|
||||
"build-storybook": "./bin/build.js",
|
||||
"start-storybook": "./bin/index.js",
|
||||
"storybook-server": "./bin/index.js"
|
||||
},
|
||||
"scripts": {
|
||||
"prepare": "node ../../scripts/prepare.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@storybook/core": "4.0.0-alpha.16",
|
||||
"common-tags": "^1.8.0",
|
||||
"global": "^4.3.2",
|
||||
"react": "^16.4.0",
|
||||
"react-dom": "^16.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"svelte": "^2.7.2",
|
||||
"svelte-loader": "^2.9.1"
|
||||
}
|
||||
}
|
9
app/svelte/src/client/index.js
Normal file
9
app/svelte/src/client/index.js
Normal file
@ -0,0 +1,9 @@
|
||||
export {
|
||||
storiesOf,
|
||||
setAddon,
|
||||
addDecorator,
|
||||
addParameters,
|
||||
configure,
|
||||
getStorybook,
|
||||
forceReRender,
|
||||
} from './preview';
|
3
app/svelte/src/client/preview/globals.js
Normal file
3
app/svelte/src/client/preview/globals.js
Normal file
@ -0,0 +1,3 @@
|
||||
import { window } from 'global';
|
||||
|
||||
window.STORYBOOK_ENV = 'svelte';
|
18
app/svelte/src/client/preview/index.js
Normal file
18
app/svelte/src/client/preview/index.js
Normal file
@ -0,0 +1,18 @@
|
||||
import { start } from '@storybook/core/client';
|
||||
|
||||
import './globals';
|
||||
import render from './render';
|
||||
|
||||
const { clientApi, configApi, forceReRender } = start(render);
|
||||
|
||||
export const {
|
||||
storiesOf,
|
||||
setAddon,
|
||||
addDecorator,
|
||||
addParameters,
|
||||
clearDecorators,
|
||||
getStorybook,
|
||||
} = clientApi;
|
||||
|
||||
export const { configure } = configApi;
|
||||
export { forceReRender };
|
85
app/svelte/src/client/preview/render.js
Normal file
85
app/svelte/src/client/preview/render.js
Normal file
@ -0,0 +1,85 @@
|
||||
import { document } from 'global';
|
||||
import { stripIndents } from 'common-tags';
|
||||
|
||||
let previousComponent = null;
|
||||
|
||||
function cleanUpPreviousStory() {
|
||||
if (!previousComponent) {
|
||||
return;
|
||||
}
|
||||
|
||||
previousComponent.destroy();
|
||||
previousComponent = null;
|
||||
}
|
||||
|
||||
function mountView({ Component, target, data, on, Wrapper, WrapperData }) {
|
||||
let component;
|
||||
|
||||
if (Wrapper) {
|
||||
const fragment = document.createDocumentFragment();
|
||||
component = new Component({ target: fragment, data });
|
||||
|
||||
const wrapper = new Wrapper({
|
||||
target,
|
||||
slots: { default: fragment },
|
||||
data: WrapperData || {},
|
||||
});
|
||||
component.on('destroy', () => {
|
||||
wrapper.destroy(true);
|
||||
});
|
||||
} else {
|
||||
component = new Component({ target, data });
|
||||
}
|
||||
|
||||
if (on) {
|
||||
// Attach svelte event listeners.
|
||||
Object.keys(on).forEach(eventName => {
|
||||
component.on(eventName, on[eventName]);
|
||||
});
|
||||
}
|
||||
|
||||
previousComponent = component;
|
||||
}
|
||||
|
||||
export default function render({
|
||||
story,
|
||||
selectedKind,
|
||||
selectedStory,
|
||||
showMain,
|
||||
showError,
|
||||
// showException,
|
||||
}) {
|
||||
const {
|
||||
/** @type {SvelteComponent} */
|
||||
Component,
|
||||
/** @type {any} */
|
||||
data,
|
||||
/** @type {{[string]: () => {}}} Attach svelte event handlers */
|
||||
on,
|
||||
Wrapper,
|
||||
WrapperData,
|
||||
} = story();
|
||||
|
||||
cleanUpPreviousStory();
|
||||
|
||||
if (!Component) {
|
||||
showError({
|
||||
title: `Expecting a Svelte component from the story: "${selectedStory}" of "${selectedKind}".`,
|
||||
description: stripIndents`
|
||||
Did you forget to return the Svelte component configuration from the story?
|
||||
Use "() => ({ Component: YourComponent, data: {} })"
|
||||
when defining the story.
|
||||
`,
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const target = document.getElementById('root');
|
||||
|
||||
target.innerHTML = '';
|
||||
|
||||
mountView({ Component, target, data, on, Wrapper, WrapperData });
|
||||
|
||||
showMain();
|
||||
}
|
5
app/svelte/src/server/build.js
Executable file
5
app/svelte/src/server/build.js
Executable file
@ -0,0 +1,5 @@
|
||||
import { buildStatic } from '@storybook/core/server';
|
||||
|
||||
import options from './options';
|
||||
|
||||
buildStatic(options);
|
5
app/svelte/src/server/index.js
Executable file
5
app/svelte/src/server/index.js
Executable file
@ -0,0 +1,5 @@
|
||||
import { buildDev } from '@storybook/core/server';
|
||||
|
||||
import options from './options';
|
||||
|
||||
buildDev(options);
|
8
app/svelte/src/server/options.js
Normal file
8
app/svelte/src/server/options.js
Normal file
@ -0,0 +1,8 @@
|
||||
import packageJson from '../../package.json';
|
||||
|
||||
import wrapInitialConfig from './wrapInitialConfig';
|
||||
|
||||
export default {
|
||||
packageJson,
|
||||
wrapInitialConfig,
|
||||
};
|
19
app/svelte/src/server/wrapInitialConfig.js
Normal file
19
app/svelte/src/server/wrapInitialConfig.js
Normal file
@ -0,0 +1,19 @@
|
||||
export default config => ({
|
||||
...config,
|
||||
module: {
|
||||
...config.module,
|
||||
rules: [
|
||||
...config.module.rules,
|
||||
{
|
||||
test: /\.(svelte|html)$/,
|
||||
loader: require.resolve('svelte-loader'),
|
||||
options: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
...config.resolve,
|
||||
extensions: [...config.resolve.extensions, '.svelte'],
|
||||
alias: config.resolve.alias,
|
||||
},
|
||||
});
|
158
docs/src/pages/basics/guide-svelte/index.md
Normal file
158
docs/src/pages/basics/guide-svelte/index.md
Normal file
@ -0,0 +1,158 @@
|
||||
---
|
||||
id: 'guide-svelte'
|
||||
title: 'Storybook for Svelte'
|
||||
---
|
||||
|
||||
You may have tried to use our quick start guide to setup your project for Storybook. If you want to set up Storybook manually, this is the guide for you.
|
||||
|
||||
> This will also help you understand how Storybook works.
|
||||
|
||||
## Starter Guide Svelte
|
||||
|
||||
Storybook has its own Webpack setup and a dev server.
|
||||
|
||||
The Webpack setup is very similar to [Svelte CLI's](https://github.com/sveltejs/svelte-cli), but allows you to [configure it however you want](/configurations/custom-webpack-config/).
|
||||
|
||||
In this guide, we are trying to set up Storybook for your Svelte project.
|
||||
|
||||
> It is very important to remember that Svelte components are precompiled from
|
||||
.svelte or .html files to vanilla javascript, so there is no 'runtime'.
|
||||
|
||||
## Table of contents
|
||||
|
||||
- [Add @storybook/svelte](#add-storybooksvelte)
|
||||
- [Create the NPM script](#create-the-npm-script)
|
||||
- [Create the config file](#create-the-config-file)
|
||||
- [Write your stories](#write-your-stories)
|
||||
- [Run your Storybook](#run-your-storybook)
|
||||
|
||||
## Add @storybook/svelte
|
||||
|
||||
First of all, you need to add `@storybook/svelte` to your project. To do that, simply run:
|
||||
|
||||
```sh
|
||||
yarn add @storybook/svelte --dev
|
||||
```
|
||||
|
||||
## Create the NPM script
|
||||
|
||||
Add the following NPM script to your `package.json` in order to start the storybook later in this guide:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"storybook": "start-storybook -p 9001 -c .storybook"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Those flags mean port (-p) 9001 and configuration (-c) located in the .storybook directory.
|
||||
|
||||
## Create the config file
|
||||
|
||||
Storybook can be configured in several different ways.
|
||||
|
||||
That’s why we need a config directory. We've added a `-c` option to the above NPM script mentioning `.storybook` as the config directory.
|
||||
|
||||
Here's an example `.storybook/config.js` to get you started:
|
||||
|
||||
```js
|
||||
import { configure } from '@storybook/svelte';
|
||||
|
||||
function loadStories() {
|
||||
// You can require as many stories as you need.
|
||||
require('../src/stories');
|
||||
}
|
||||
|
||||
configure(loadStories, module);
|
||||
```
|
||||
|
||||
> This stories folder is just an example, you can load stories from wherever you want to.
|
||||
> We think stories are best located close to the source files.
|
||||
|
||||
## Write your stories
|
||||
|
||||
Now you can write some stories inside the `../stories/index.js` file, like this:
|
||||
|
||||
```js
|
||||
// Story about MyButton
|
||||
import { storiesOf } from '@storybook/svelte';
|
||||
|
||||
import MyButton from '../components/MyButton.svelte';
|
||||
|
||||
storiesOf('MyButton', module)
|
||||
.add('simple component example', () => ({
|
||||
Component: MyButton,
|
||||
|
||||
data: {
|
||||
rounded: true
|
||||
},
|
||||
|
||||
on: {
|
||||
click: event => {
|
||||
console.log('clicked', event);
|
||||
}
|
||||
}
|
||||
}));
|
||||
```
|
||||
|
||||
Svelte storybooks don't support using templates in a story yet. Instead,
|
||||
you can create a .svelte file to compose components together, or simply to access
|
||||
all normal Svelte functionality, like slots.
|
||||
|
||||
So you can create a story "view" file, essentially just a .svelte file to load
|
||||
your components into to test.
|
||||
|
||||
```html
|
||||
<!-- MyButtonView -->
|
||||
<MyButton rounded="{rounded}" on:click>
|
||||
{buttonText}
|
||||
</Button>
|
||||
```
|
||||
|
||||
In this example, the `on:click` that is heard on the `MyButton` component is
|
||||
simply passed up to the containing component `MyButtonView` using the svelte
|
||||
shorthand. It's the equivalent to `on:click="fire('click', event)"`, but it's
|
||||
worth knowing about especially in this "component wrapper" scenario.
|
||||
|
||||
> If your component doesn't use slots, you don't need to do this, but if it does
|
||||
or some other svelte functionality that requires the component to exist in a svelte
|
||||
view, then this is how to do that.
|
||||
|
||||
You would then write a story for this "view" the exact same way you did with a component.
|
||||
|
||||
```js
|
||||
// MyButtonView
|
||||
import { storiesOf } from '@storybook/svelte';
|
||||
|
||||
import MyButtonView from '../views/MyButtonView.svelte';
|
||||
|
||||
storiesOf('MyButtonView', module)
|
||||
.add('wrapped component(s) example', () => ({
|
||||
Components: MyButtonView,
|
||||
|
||||
data: {
|
||||
buttonText: 'Some button text',
|
||||
rounded: true
|
||||
},
|
||||
|
||||
on: {
|
||||
click: (event) => {
|
||||
console.log('clicked', event);
|
||||
}
|
||||
}
|
||||
}));
|
||||
```
|
||||
|
||||
Each story represents a single state of your component.
|
||||
|
||||
## Run your Storybook
|
||||
|
||||
Now everything is ready. Simply run your storybook with:
|
||||
|
||||
```sh
|
||||
yarn storybook
|
||||
```
|
||||
|
||||
Now you can change components and write stories whenever you need to.
|
||||
You'll get those changes into Storybook in a snap with the help of Webpack's HMR API.
|
@ -13,6 +13,7 @@ title: 'Live Examples'
|
||||
- [Mithril](https://storybooks-mithril.netlify.com/)
|
||||
- [Marko](https://storybooks-marko.netlify.com/)
|
||||
- [HTML](https://storybooks-html.netlify.com/)
|
||||
- [Svelte](https://storybooks-svelte.netlify.com/)
|
||||
|
||||
### 3.4
|
||||
- [React Official](https://release-3-4--storybooks-official.netlify.com)
|
||||
|
@ -4,7 +4,7 @@ title: 'Quick Start Guide'
|
||||
---
|
||||
|
||||
Storybook supports many different frontend frameworks with more coming!
|
||||
React, Vue, Angular, Mithril, Marko, and HTML are currently supported. Follow these steps to get started with Storybook.
|
||||
React, Vue, Angular, Mithril, Marko, HTML and Svelte are currently supported. Follow these steps to get started with Storybook.
|
||||
|
||||
Get started using the automated command line tool. This command adds a set of boilerplate files for Storybook in your project:
|
||||
```sh
|
||||
@ -19,6 +19,7 @@ To install storybook for HTML, add `--html` argument:
|
||||
getstorybook --html
|
||||
```
|
||||
|
||||
|
||||
Start Storybook with:
|
||||
```sh
|
||||
npm run storybook
|
||||
@ -35,6 +36,6 @@ To learn more about what `getstorybook` command does, have a look at the slow st
|
||||
* [Mithril](/basics/guide-mithril/)
|
||||
* [Marko](/basics/guide-marko/)
|
||||
* [HTML](/basics/guide-html/)
|
||||
|
||||
* [Svelte](/basics/guide-svelte/)
|
||||
|
||||
A tutorial is also available at [Learn Storybook](https://www.learnstorybook.com) for a step-by-step guide (only available for React).
|
||||
|
@ -11,3 +11,4 @@ Storybook supports multiple UI libraries. The manual setup for each framework is
|
||||
- [Storybook for Mithril](/basics/guide-mithril/)
|
||||
- [Storybook for Marko](/basics/guide-marko/)
|
||||
- [Storybook for HTML](/basics/guide-html/)
|
||||
- [Storybook for Svelte](/basics/guide-svelte/)
|
||||
|
@ -5,9 +5,8 @@ title: 'Custom Webpack Config'
|
||||
|
||||
## Default mode
|
||||
|
||||
The default Webpack config of Storybook is balanced for a medium-size project (specially created with [Create React App](https://github.com/facebookincubator/create-react-app)) or a library. But if you already have your own Webpack setup, that's not useable.
|
||||
|
||||
That's why we allow you to customize our Webpack setup by providing a `webpack.config.js` file exporting a **webpack 2** compatible config exported as a **commonjs module**.
|
||||
That's why we allow you to customize our webpack setup by providing a `webpack.config.js` file exporting a **webpack 2** compatible config exported as a **commonjs module**.
|
||||
|
||||
There are a few ways to do it:
|
||||
|
||||
@ -38,11 +37,11 @@ Since this config file stays in the Storybook directory, you need to set the inc
|
||||
|
||||
You also need to install the loaders (style, css, sass, as well as node-sass) used in above config manually.
|
||||
|
||||
> Once you create this `webpack.config.js` file, Storybook won't load the [default Webpack config](/configurations/default-config/) other than loading JS files with the Babel loader. This will disable included functionality like svg loading. Read on to learn how to [retain defaults](#full-control-mode--default).
|
||||
> Once you create this `webpack.config.js` file, Storybook won't load the [default webpack config](/configurations/default-config/) other than loading JS files with the Babel loader. This will disable included functionality like svg loading. Read on to learn how to [retain defaults](#full-control-mode--default).
|
||||
|
||||
### Supported Webpack Options
|
||||
|
||||
You can add any kind of Webpack configuration options with the above config, whether they are plugins, loaders, or aliases.
|
||||
You can add any kind of webpack configuration options with the above config, whether they are plugins, loaders, or aliases.
|
||||
But you won't be able to change the following config options:
|
||||
|
||||
* entry
|
||||
@ -117,9 +116,9 @@ For full instructions on Typescript setup, check [our dedicated Typescript page]
|
||||
|
||||
## Using Your Existing Config
|
||||
|
||||
You may have an existing Webpack config for your project. So, you may need to copy and paste some config items into Storybook's custom Webpack config file.
|
||||
You may have an existing webpack config for your project. So, you may need to copy and paste some config items into Storybook's custom webpack config file.
|
||||
|
||||
But you don't need to. There are a few options:
|
||||
|
||||
* Import your main Webpack config into Storybook's `webpack.config.js` and use the loaders and plugins used in that.
|
||||
* Create a new file with common Webpack options and use it in both inside the main Webpack config and inside Storybook's `webpack.config.js`.
|
||||
* Import your main webpack config into Storybook's `webpack.config.js` and use the loaders and plugins used in that.
|
||||
* Create a new file with common webpack options and use it in both inside the main webpack config and inside Storybook's `webpack.config.js`.
|
||||
|
1
examples/official-storybook/built-storybooks/svelte-kitchen-sink
Symbolic link
1
examples/official-storybook/built-storybooks/svelte-kitchen-sink
Symbolic link
@ -0,0 +1 @@
|
||||
../../svelte-kitchen-sink/storybook-static
|
@ -47,3 +47,11 @@ exports[`Storyshots App|acceptance vue-kitchen-sink 1`] = `
|
||||
title="vue-kitchen-sink"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`Storyshots App|acceptance svelte-kitchen-sink 1`] = `
|
||||
<iframe
|
||||
src="svelte-kitchen-sink/index.html"
|
||||
style="border:0;position:absolute;top:0;left:0;width:100vw;height:100vh"
|
||||
title="svelte-kitchen-sink"
|
||||
/>
|
||||
`;
|
||||
|
@ -19,6 +19,7 @@ const style = {
|
||||
[
|
||||
'cra-kitchen-sink',
|
||||
'vue-kitchen-sink',
|
||||
'svelte-kitchen-sink',
|
||||
'angular-cli',
|
||||
'polymer-cli',
|
||||
'mithril-kitchen-sink',
|
||||
|
16
examples/svelte-kitchen-sink/.gitignore
vendored
Normal file
16
examples/svelte-kitchen-sink/.gitignore
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
node_modules
|
||||
|
||||
# testing
|
||||
coverage
|
||||
|
||||
# production
|
||||
build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env
|
||||
npm-debug.log
|
||||
yarn-error.log
|
8
examples/svelte-kitchen-sink/.storybook/addons.js
Normal file
8
examples/svelte-kitchen-sink/.storybook/addons.js
Normal file
@ -0,0 +1,8 @@
|
||||
import '@storybook/addon-storysource/register';
|
||||
import '@storybook/addon-actions/register';
|
||||
import '@storybook/addon-links/register';
|
||||
import '@storybook/addon-notes/register';
|
||||
import '@storybook/addon-knobs/register';
|
||||
import '@storybook/addon-backgrounds/register';
|
||||
import '@storybook/addon-viewport/register';
|
||||
import '@storybook/addon-options/register';
|
15
examples/svelte-kitchen-sink/.storybook/config.js
Normal file
15
examples/svelte-kitchen-sink/.storybook/config.js
Normal file
@ -0,0 +1,15 @@
|
||||
import { configure } from '@storybook/svelte';
|
||||
import { setOptions } from '@storybook/addon-options';
|
||||
|
||||
// Used with @storybook/addon-options/register
|
||||
setOptions({ hierarchyRootSeparator: /\|/ });
|
||||
|
||||
function loadStories() {
|
||||
require('../src/stories');
|
||||
|
||||
const req = require.context('../src/stories', true, /\.stories\.js$/);
|
||||
|
||||
req.keys().forEach(filename => req(filename));
|
||||
}
|
||||
|
||||
configure(loadStories, module);
|
12
examples/svelte-kitchen-sink/.storybook/webpack.config.js
Normal file
12
examples/svelte-kitchen-sink/.storybook/webpack.config.js
Normal file
@ -0,0 +1,12 @@
|
||||
const path = require('path');
|
||||
|
||||
module.exports = (storybookBaseConfig, configType, defaultConfig) => {
|
||||
defaultConfig.module.rules.push({
|
||||
test: [/\.stories\.js$/, /index\.js$/],
|
||||
loaders: [require.resolve('@storybook/addon-storysource/loader')],
|
||||
include: [path.resolve(__dirname, '../src')],
|
||||
enforce: 'pre',
|
||||
});
|
||||
|
||||
return defaultConfig;
|
||||
};
|
5
examples/svelte-kitchen-sink/README.md
Normal file
5
examples/svelte-kitchen-sink/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Storybook Svelte Demo
|
||||
|
||||
This example directory represents the application you wish to integrate storybook into.
|
||||
|
||||
Run `yarn install` to sync Storybook module with the source code and run `yarn storybook` to start the Storybook.
|
26
examples/svelte-kitchen-sink/package.json
Normal file
26
examples/svelte-kitchen-sink/package.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "svelte-example",
|
||||
"version": "4.0.0-alpha.16",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build-storybook": "build-storybook -s public",
|
||||
"storybook": "start-storybook -p 9009 -s public"
|
||||
},
|
||||
"dependencies": {
|
||||
"global": "^4.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/addon-actions": "4.0.0-alpha.16",
|
||||
"@storybook/addon-backgrounds": "4.0.0-alpha.16",
|
||||
"@storybook/addon-centered": "4.0.0-alpha.16",
|
||||
"@storybook/addon-knobs": "4.0.0-alpha.16",
|
||||
"@storybook/addon-links": "4.0.0-alpha.16",
|
||||
"@storybook/addon-notes": "4.0.0-alpha.16",
|
||||
"@storybook/addon-options": "4.0.0-alpha.16",
|
||||
"@storybook/addon-storyshots": "4.0.0-alpha.16",
|
||||
"@storybook/addon-storysource": "4.0.0-alpha.16",
|
||||
"@storybook/addon-viewport": "4.0.0-alpha.16",
|
||||
"@storybook/addons": "4.0.0-alpha.16",
|
||||
"@storybook/svelte": "4.0.0-alpha.16"
|
||||
}
|
||||
}
|
BIN
examples/svelte-kitchen-sink/public/favicon.ico
Normal file
BIN
examples/svelte-kitchen-sink/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 87 KiB |
31
examples/svelte-kitchen-sink/public/index.html
Normal file
31
examples/svelte-kitchen-sink/public/index.html
Normal file
@ -0,0 +1,31 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tag above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `yarn build`.
|
||||
-->
|
||||
<title>Svelte App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `yarn storybook`.
|
||||
To create a production bundle, use `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
</html>
|
48
examples/svelte-kitchen-sink/src/components/Button.svelte
Normal file
48
examples/svelte-kitchen-sink/src/components/Button.svelte
Normal file
@ -0,0 +1,48 @@
|
||||
<button
|
||||
class="button {roundedClass}"
|
||||
on:click="onClick(event)">
|
||||
<strong>{rounded ? 'Round' : 'Square'} corners</strong><br>
|
||||
{text}
|
||||
<slot></slot>
|
||||
</button>
|
||||
|
||||
<style>
|
||||
.rounded {
|
||||
border-radius: 35px;
|
||||
}
|
||||
|
||||
.button {
|
||||
border: 3px solid;
|
||||
padding: 10px 20px;
|
||||
background-color: white;
|
||||
outline: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
count: 0,
|
||||
text: '', // component supports both <slot> and text prop.
|
||||
rounded: true
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
roundedClass({ rounded }) {
|
||||
return rounded ? 'rounded' : ''
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onClick(event) {
|
||||
const {rounded} = this.get();
|
||||
|
||||
this.set({rounded: !rounded});
|
||||
|
||||
this.fire('click', event)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
24
examples/svelte-kitchen-sink/src/components/Button.test.js
Normal file
24
examples/svelte-kitchen-sink/src/components/Button.test.js
Normal file
@ -0,0 +1,24 @@
|
||||
import { document } from 'global';
|
||||
import Button from './Button.svelte';
|
||||
|
||||
let target;
|
||||
let component;
|
||||
|
||||
describe('Button Component', () => {
|
||||
beforeEach(() => {
|
||||
target = document.createElement('div');
|
||||
|
||||
component = new Button({ target });
|
||||
});
|
||||
|
||||
it('should render `text` property', () => {
|
||||
const text = 'Hello world';
|
||||
const expected = `Round corners\n ${text}`;
|
||||
|
||||
component.set({ text });
|
||||
|
||||
const componentText = target.firstChild.textContent.trim();
|
||||
|
||||
expect(componentText).toEqual(expected);
|
||||
});
|
||||
});
|
BIN
examples/svelte-kitchen-sink/src/logo.png
Normal file
BIN
examples/svelte-kitchen-sink/src/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.2 KiB |
@ -0,0 +1,72 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Storyshots Addon|Actions Action on component method 1`] = `
|
||||
<section
|
||||
class="storybook-snapshot-container"
|
||||
>
|
||||
<button
|
||||
class="button rounded svelte-n2tx93"
|
||||
>
|
||||
<strong>
|
||||
Round
|
||||
corners
|
||||
</strong>
|
||||
<br />
|
||||
|
||||
|
||||
Custom text
|
||||
|
||||
|
||||
</button>
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`Storyshots Addon|Actions Action on view method 1`] = `
|
||||
<section
|
||||
class="storybook-snapshot-container"
|
||||
>
|
||||
<h1>
|
||||
Button view
|
||||
</h1>
|
||||
|
||||
|
||||
<button
|
||||
class="button svelte-n2tx93"
|
||||
>
|
||||
<strong>
|
||||
Square
|
||||
corners
|
||||
</strong>
|
||||
<br />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!---->
|
||||
You clicked
|
||||
:
|
||||
0
|
||||
</button>
|
||||
|
||||
|
||||
<p>
|
||||
A little text to show this is a view.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
If we need to test components in a Svelte environment, for instance to test slot behaviour,
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
then wrapping the component up in a view
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
made just for the story is the simplest way to achieve this.
|
||||
</p>
|
||||
</section>
|
||||
`;
|
@ -0,0 +1,51 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Storyshots Addon|Backgrounds story 1 1`] = `
|
||||
<section
|
||||
class="storybook-snapshot-container"
|
||||
>
|
||||
<h1>
|
||||
Button view
|
||||
</h1>
|
||||
|
||||
|
||||
<button
|
||||
class="button svelte-n2tx93"
|
||||
>
|
||||
<strong>
|
||||
Square
|
||||
corners
|
||||
</strong>
|
||||
<br />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!---->
|
||||
You clicked
|
||||
:
|
||||
0
|
||||
</button>
|
||||
|
||||
|
||||
<p>
|
||||
A little text to show this is a view.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
If we need to test components in a Svelte environment, for instance to test slot behaviour,
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
then wrapping the component up in a view
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
made just for the story is the simplest way to achieve this.
|
||||
</p>
|
||||
</section>
|
||||
`;
|
@ -0,0 +1,43 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Storyshots Addon|Centered rounded 1`] = `
|
||||
<section
|
||||
class="storybook-snapshot-container"
|
||||
>
|
||||
<button
|
||||
class="button rounded svelte-n2tx93"
|
||||
>
|
||||
<strong>
|
||||
Round
|
||||
corners
|
||||
</strong>
|
||||
<br />
|
||||
|
||||
|
||||
Look, I'm centered!
|
||||
|
||||
|
||||
</button>
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`Storyshots Addon|Centered with action 1`] = `
|
||||
<section
|
||||
class="storybook-snapshot-container"
|
||||
>
|
||||
<button
|
||||
class="button rounded svelte-n2tx93"
|
||||
>
|
||||
<strong>
|
||||
Round
|
||||
corners
|
||||
</strong>
|
||||
<br />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</button>
|
||||
</section>
|
||||
`;
|
@ -0,0 +1,15 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Storyshots Addon|Knobs Simple 1`] = `
|
||||
<section
|
||||
class="storybook-snapshot-container"
|
||||
>
|
||||
<div
|
||||
style="width: 200px; height: 200px; background-color: green;"
|
||||
>
|
||||
<p>
|
||||
I am interactive
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
`;
|
@ -0,0 +1,28 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Storyshots Addon|Links Go to welcome view 1`] = `
|
||||
<section
|
||||
class="storybook-snapshot-container"
|
||||
>
|
||||
<div
|
||||
class="main"
|
||||
>
|
||||
<h1>
|
||||
Link Action
|
||||
</h1>
|
||||
|
||||
|
||||
<button
|
||||
class="link"
|
||||
>
|
||||
Return to the
|
||||
<code
|
||||
class="code"
|
||||
>
|
||||
Welcome
|
||||
</code>
|
||||
view story.
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
`;
|
@ -0,0 +1,101 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Storyshots Addon|Notes Note with HTML 1`] = `
|
||||
<section
|
||||
class="storybook-snapshot-container"
|
||||
>
|
||||
<h1>
|
||||
Button view
|
||||
</h1>
|
||||
|
||||
|
||||
<button
|
||||
class="button svelte-n2tx93"
|
||||
>
|
||||
<strong>
|
||||
Square
|
||||
corners
|
||||
</strong>
|
||||
<br />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!---->
|
||||
🤔😳😯😮😄😩😓😱🤓😑😶😊
|
||||
:
|
||||
0
|
||||
</button>
|
||||
|
||||
|
||||
<p>
|
||||
A little text to show this is a view.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
If we need to test components in a Svelte environment, for instance to test slot behaviour,
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
then wrapping the component up in a view
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
made just for the story is the simplest way to achieve this.
|
||||
</p>
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`Storyshots Addon|Notes Simple note 1`] = `
|
||||
<section
|
||||
class="storybook-snapshot-container"
|
||||
>
|
||||
<h1>
|
||||
Button view
|
||||
</h1>
|
||||
|
||||
|
||||
<button
|
||||
class="button svelte-n2tx93"
|
||||
>
|
||||
<strong>
|
||||
Square
|
||||
corners
|
||||
</strong>
|
||||
<br />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!---->
|
||||
You clicked
|
||||
:
|
||||
0
|
||||
</button>
|
||||
|
||||
|
||||
<p>
|
||||
A little text to show this is a view.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
If we need to test components in a Svelte environment, for instance to test slot behaviour,
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
then wrapping the component up in a view
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
made just for the story is the simplest way to achieve this.
|
||||
</p>
|
||||
</section>
|
||||
`;
|
@ -0,0 +1,211 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Storyshots Button rounded 1`] = `
|
||||
<section
|
||||
class="storybook-snapshot-container"
|
||||
>
|
||||
<h1>
|
||||
Button view
|
||||
</h1>
|
||||
|
||||
|
||||
<button
|
||||
class="button rounded svelte-n2tx93"
|
||||
>
|
||||
<strong>
|
||||
Round
|
||||
corners
|
||||
</strong>
|
||||
<br />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!---->
|
||||
You clicked
|
||||
:
|
||||
0
|
||||
</button>
|
||||
|
||||
|
||||
<p>
|
||||
A little text to show this is a view.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
If we need to test components in a Svelte environment, for instance to test slot behaviour,
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
then wrapping the component up in a view
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
made just for the story is the simplest way to achieve this.
|
||||
</p>
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`Storyshots Button square 1`] = `
|
||||
<section
|
||||
class="storybook-snapshot-container"
|
||||
>
|
||||
<h1>
|
||||
Button view
|
||||
</h1>
|
||||
|
||||
|
||||
<button
|
||||
class="button svelte-n2tx93"
|
||||
>
|
||||
<strong>
|
||||
Square
|
||||
corners
|
||||
</strong>
|
||||
<br />
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!---->
|
||||
You clicked
|
||||
:
|
||||
0
|
||||
</button>
|
||||
|
||||
|
||||
<p>
|
||||
A little text to show this is a view.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
If we need to test components in a Svelte environment, for instance to test slot behaviour,
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
then wrapping the component up in a view
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
made just for the story is the simplest way to achieve this.
|
||||
</p>
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`Storyshots Welcome Welcome 1`] = `
|
||||
<section
|
||||
class="storybook-snapshot-container"
|
||||
>
|
||||
<div
|
||||
class="main svelte-1unvhkg"
|
||||
>
|
||||
<h1>
|
||||
Welcome to Storybook for Svelte
|
||||
</h1>
|
||||
|
||||
|
||||
<p>
|
||||
This is a UI component dev environment for your svelte app.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
We've added some basic stories inside the
|
||||
<code
|
||||
class="code svelte-1unvhkg"
|
||||
>
|
||||
src/stories
|
||||
</code>
|
||||
directory.
|
||||
|
||||
<strong>
|
||||
A story is like a visual test case
|
||||
</strong>
|
||||
|
||||
and represents a single state of one or more UI components.
|
||||
You can have as many stories as you want.
|
||||
</p>
|
||||
|
||||
|
||||
|
||||
<h1
|
||||
class="logo svelte-1unvhkg"
|
||||
>
|
||||
Svelte
|
||||
</h1>
|
||||
|
||||
|
||||
|
||||
<p>
|
||||
Just like that, you can add your own components as stories.
|
||||
You can also edit those components and see changes right away.
|
||||
|
||||
<br />
|
||||
|
||||
(Try editing the
|
||||
<code
|
||||
class="code svelte-1unvhkg"
|
||||
>
|
||||
Button
|
||||
</code>
|
||||
component
|
||||
located at
|
||||
<code
|
||||
class="code svelte-1unvhkg"
|
||||
>
|
||||
src/stories/views/Welcome.svelte
|
||||
</code>
|
||||
.)
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
Usually we create stories with smaller UI components in the app.
|
||||
<br />
|
||||
|
||||
Have a look at the
|
||||
|
||||
<a
|
||||
class="link svelte-1unvhkg"
|
||||
href="https://storybook.js.org/basics/writing-stories"
|
||||
target="_blank"
|
||||
>
|
||||
Writing Stories
|
||||
</a>
|
||||
|
||||
section in our documentation.
|
||||
</p>
|
||||
|
||||
|
||||
<p
|
||||
class="note svelte-1unvhkg"
|
||||
>
|
||||
<b>
|
||||
NOTE:
|
||||
</b>
|
||||
|
||||
|
||||
<br />
|
||||
|
||||
Have a look at the
|
||||
|
||||
<code
|
||||
class="code svelte-1unvhkg"
|
||||
>
|
||||
.storybook/webpack.config.js
|
||||
</code>
|
||||
|
||||
to add webpack
|
||||
loaders and plugins you are using in this project.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
`;
|
@ -0,0 +1,22 @@
|
||||
import { storiesOf } from '@storybook/svelte';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import ButtonView from './views/ButtonView.svelte';
|
||||
import Button from '../components/Button.svelte';
|
||||
|
||||
storiesOf('Addon|Actions', module)
|
||||
.add('Action on view method', () => ({
|
||||
Component: ButtonView,
|
||||
on: {
|
||||
click: action('I am logging in the actions tab'),
|
||||
},
|
||||
}))
|
||||
.add('Action on component method', () => ({
|
||||
Component: Button,
|
||||
data: {
|
||||
text: 'Custom text',
|
||||
},
|
||||
on: {
|
||||
click: action('I am logging in the actions tab too'),
|
||||
},
|
||||
}));
|
@ -0,0 +1,15 @@
|
||||
import { storiesOf } from '@storybook/svelte';
|
||||
import { withBackgrounds } from '@storybook/addon-backgrounds';
|
||||
|
||||
import ButtonView from './views/ButtonView.svelte';
|
||||
|
||||
storiesOf('Addon|Backgrounds', module)
|
||||
.addDecorator(
|
||||
withBackgrounds([
|
||||
{ name: 'twitter', value: '#00aced' },
|
||||
{ name: 'facebook', value: '#3b5998', default: true },
|
||||
])
|
||||
)
|
||||
.add('story 1', () => ({
|
||||
Component: ButtonView,
|
||||
}));
|
@ -0,0 +1,21 @@
|
||||
import { storiesOf } from '@storybook/svelte';
|
||||
import Centered from '@storybook/addon-centered/svelte';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
import Button from '../components/Button.svelte';
|
||||
|
||||
storiesOf('Addon|Centered', module)
|
||||
.addDecorator(Centered)
|
||||
.add('rounded', () => ({
|
||||
Component: Button,
|
||||
data: {
|
||||
rounded: true,
|
||||
text: "Look, I'm centered!",
|
||||
},
|
||||
}))
|
||||
.add('with action', () => ({
|
||||
Component: Button,
|
||||
on: {
|
||||
click: action(`Tell me it ain't so! Centered and with actions! Thanks @ekhaled :)`),
|
||||
},
|
||||
}));
|
@ -0,0 +1,32 @@
|
||||
import { storiesOf } from '@storybook/svelte';
|
||||
import { withKnobs, text, number } from '@storybook/addon-knobs';
|
||||
|
||||
import ActionKnobView from './views/ActionKnobView.svelte';
|
||||
|
||||
storiesOf('Addon|Knobs', module)
|
||||
.addDecorator(withKnobs)
|
||||
.add('Simple', () => {
|
||||
const backgroundColor = text('Background', 'green');
|
||||
const width = number('Width', 200, {
|
||||
range: true,
|
||||
min: 100,
|
||||
max: 1000,
|
||||
step: 100,
|
||||
});
|
||||
|
||||
const height = number('Height', 200, {
|
||||
range: true,
|
||||
min: 100,
|
||||
max: 1000,
|
||||
step: 100,
|
||||
});
|
||||
|
||||
return {
|
||||
Component: ActionKnobView,
|
||||
data: {
|
||||
backgroundColor,
|
||||
width,
|
||||
height,
|
||||
},
|
||||
};
|
||||
});
|
@ -0,0 +1,11 @@
|
||||
import { storiesOf } from '@storybook/svelte';
|
||||
import { linkTo } from '@storybook/addon-links';
|
||||
|
||||
import ActionLinkView from './views/ActionLinkView.svelte';
|
||||
|
||||
storiesOf('Addon|Links', module).add('Go to welcome view', () => ({
|
||||
Component: ActionLinkView,
|
||||
on: {
|
||||
click: linkTo('Welcome'),
|
||||
},
|
||||
}));
|
@ -0,0 +1,32 @@
|
||||
import { storiesOf } from '@storybook/svelte';
|
||||
import { withNotes } from '@storybook/addon-notes';
|
||||
|
||||
import ButtonView from './views/ButtonView.svelte';
|
||||
|
||||
storiesOf('Addon|Notes', module)
|
||||
.addDecorator(withNotes)
|
||||
.add(
|
||||
'Simple note',
|
||||
() => ({
|
||||
Component: ButtonView,
|
||||
}),
|
||||
{ notes: 'My notes on the ButtonView component' }
|
||||
)
|
||||
.add(
|
||||
'Note with HTML',
|
||||
() => ({
|
||||
Component: ButtonView,
|
||||
data: {
|
||||
text: '🤔😳😯😮😄😩😓😱🤓😑😶😊',
|
||||
},
|
||||
}),
|
||||
{
|
||||
notes: `
|
||||
<h2>My notes on emojies</h2>
|
||||
|
||||
<em>It's not all that important to be honest, but..</em>
|
||||
|
||||
Emojis are great, I love emojis, in fact I like using them in my Component notes too! 😇
|
||||
`,
|
||||
}
|
||||
);
|
24
examples/svelte-kitchen-sink/src/stories/index.js
Normal file
24
examples/svelte-kitchen-sink/src/stories/index.js
Normal file
@ -0,0 +1,24 @@
|
||||
import { storiesOf } from '@storybook/svelte';
|
||||
|
||||
import WelcomeView from './views/WelcomeView.svelte';
|
||||
import ButtonView from './views/ButtonView.svelte';
|
||||
|
||||
storiesOf('Welcome', module).add('Welcome', () => ({
|
||||
Component: WelcomeView,
|
||||
}));
|
||||
|
||||
storiesOf('Button', module)
|
||||
.add('rounded', () => ({
|
||||
Component: ButtonView,
|
||||
data: {
|
||||
rounded: true,
|
||||
message: 'Rounded text',
|
||||
},
|
||||
}))
|
||||
.add('square', () => ({
|
||||
Component: ButtonView,
|
||||
data: {
|
||||
rounded: false,
|
||||
message: 'Squared text',
|
||||
},
|
||||
}));
|
@ -0,0 +1,15 @@
|
||||
<div style="width: {width}px; height: {height}px; background-color: {backgroundColor}">
|
||||
<p>I am interactive</p>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
width: 200,
|
||||
height: 100,
|
||||
backgroundColor: 'yellow'
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
@ -0,0 +1,20 @@
|
||||
<div class="main">
|
||||
<h1>Link Action</h1>
|
||||
<button on:click="onClick(event)" class="link">
|
||||
Return to the <code class="code">Welcome</code> view story.
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
methods: {
|
||||
onClick(event) {
|
||||
this.fire('click', event);
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
@ -0,0 +1,39 @@
|
||||
<h1>Button view</h1>
|
||||
<Button {rounded} on:click="handleClick(event)">{text}: {count}</Button>
|
||||
<p>A little text to show this is a view.</p>
|
||||
<p>If we need to test components in a Svelte environment, for instance to test slot behaviour,</p>
|
||||
<p>then wrapping the component up in a view</p>
|
||||
<p>made just for the story is the simplest way to achieve this.</p>
|
||||
|
||||
<script>
|
||||
import Button from '../../components/Button.svelte';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
count: 0,
|
||||
text: 'You clicked'
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleClick(event) {
|
||||
this.incrementCount();
|
||||
|
||||
this.fire('click', { event });
|
||||
},
|
||||
|
||||
incrementCount() {
|
||||
let {count} = this.get();
|
||||
|
||||
count += 1;
|
||||
|
||||
this.set({count})
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
Button
|
||||
}
|
||||
};
|
||||
</script>
|
@ -0,0 +1,83 @@
|
||||
<div class="main">
|
||||
<h1>Welcome to Storybook for Svelte</h1>
|
||||
<p>
|
||||
This is a UI component dev environment for your svelte app.
|
||||
</p>
|
||||
<p>
|
||||
We've added some basic stories inside the <code class="code">src/stories</code> directory.
|
||||
<strong>A story is like a visual test case</strong>
|
||||
and represents a single state of one or more UI components.
|
||||
You can have as many stories as you want.
|
||||
</p>
|
||||
|
||||
<h1 class="logo">Svelte</h1>
|
||||
|
||||
<p>
|
||||
Just like that, you can add your own components as stories.
|
||||
You can also edit those components and see changes right away.
|
||||
<br />
|
||||
(Try editing the <code class="code">Button</code> component
|
||||
located at <code class="code">src/stories/views/Welcome.svelte</code>.)
|
||||
</p>
|
||||
<p>
|
||||
Usually we create stories with smaller UI components in the app.<br />
|
||||
Have a look at the
|
||||
<a
|
||||
class="link"
|
||||
href="https://storybook.js.org/basics/writing-stories"
|
||||
target="_blank"
|
||||
>
|
||||
Writing Stories
|
||||
</a>
|
||||
section in our documentation.
|
||||
</p>
|
||||
<p class="note">
|
||||
<b>NOTE:</b>
|
||||
<br />
|
||||
Have a look at the
|
||||
<code class="code">.storybook/webpack.config.js</code>
|
||||
to add webpack
|
||||
loaders and plugins you are using in this project.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css?family=Rajdhani');
|
||||
|
||||
.main {
|
||||
margin: 15px;
|
||||
max-width: 600;
|
||||
line-height: 1.4;
|
||||
font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-family: 'Rajdhani', sans-serif;
|
||||
color: rgb(170,30,30);
|
||||
font-weight: 300;
|
||||
font-size: 8rem;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.link {
|
||||
color: #1474f3;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid #1474f3;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.code {
|
||||
font-size: 15;
|
||||
font-weight: 600;
|
||||
padding: 2px 5px;
|
||||
border: 1px solid #eae9e9;
|
||||
border-radius: 4px;
|
||||
background-color: #f3f2f2;
|
||||
color: #3a3a3a;
|
||||
}
|
||||
|
||||
.note {
|
||||
opacity: 0.5;
|
||||
}
|
||||
</style>
|
9
examples/svelte-kitchen-sink/svelteshots.test.js
Normal file
9
examples/svelte-kitchen-sink/svelteshots.test.js
Normal file
@ -0,0 +1,9 @@
|
||||
import path from 'path';
|
||||
import initStoryshots, { multiSnapshotWithOptions } from '@storybook/addon-storyshots';
|
||||
|
||||
initStoryshots({
|
||||
framework: 'svelte',
|
||||
configPath: path.join(__dirname, '.storybook'),
|
||||
integrityOptions: { cwd: path.join(__dirname, 'src', 'stories') },
|
||||
test: multiSnapshotWithOptions(),
|
||||
});
|
@ -16,6 +16,7 @@ module.exports = {
|
||||
'<rootDir>/lib',
|
||||
'<rootDir>/examples/cra-kitchen-sink',
|
||||
'<rootDir>/examples/vue-kitchen-sink',
|
||||
'<rootDir>/examples/svelte-kitchen-sink',
|
||||
'<rootDir>/examples/html-kitchen-sink',
|
||||
'<rootDir>/examples/official-storybook',
|
||||
'<rootDir>/examples/angular-cli',
|
||||
@ -25,6 +26,7 @@ module.exports = {
|
||||
'^.+[/\\\\].storybook[/\\\\]config\\.ts$': '<rootDir>/scripts/jest-ts-babel.js',
|
||||
'^.+\\.(ts|html)$': '<rootDir>/node_modules/jest-preset-angular/preprocessor.js',
|
||||
'.*\\.(vue)$': '<rootDir>/node_modules/jest-vue-preprocessor',
|
||||
'.*\\.(svelte)$': '<rootDir>/node_modules/svelte-jest',
|
||||
},
|
||||
testPathIgnorePatterns: ['/node_modules/', 'addon-jest.test.js', '/cli/test/'],
|
||||
collectCoverage: false,
|
||||
@ -41,5 +43,5 @@ module.exports = {
|
||||
setupTestFrameworkScriptFile: './scripts/jest.init.js',
|
||||
setupFiles: ['raf/polyfill'],
|
||||
testURL: 'http://localhost',
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node', '.html', 'vue'],
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node', '.html', '.svelte', 'vue'],
|
||||
};
|
||||
|
@ -38,12 +38,13 @@
|
||||
"core-js": "^2.5.7",
|
||||
"css-loader": "^1.0.0",
|
||||
"dotenv-webpack": "^1.5.7",
|
||||
"ejs": "^2.6.1",
|
||||
"emotion": "^9.2.6",
|
||||
"express": "^4.16.3",
|
||||
"file-loader": "^1.1.11",
|
||||
"find-cache-dir": "^2.0.0",
|
||||
"generate-page-webpack-plugin": "^1.0.0",
|
||||
"global": "^4.3.2",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"interpret": "^1.1.0",
|
||||
"json5": "^1.0.1",
|
||||
"postcss-flexbugs-fixes": "^4.1.0",
|
||||
|
@ -4,7 +4,4 @@ const serverUtils = require('./dist/server/utils');
|
||||
const buildStatic = require('./dist/server/build-static');
|
||||
const buildDev = require('./dist/server/build-dev');
|
||||
|
||||
module.exports = assign({}, defaultWebpackConfig, buildStatic, buildDev, serverUtils, {
|
||||
indexHtmlPath: require.resolve('./src/server/index.html.ejs'),
|
||||
iframeHtmlPath: require.resolve('./src/server/iframe.html.ejs'),
|
||||
});
|
||||
module.exports = assign({}, defaultWebpackConfig, buildStatic, buildDev, serverUtils);
|
||||
|
114
lib/core/src/server/__snapshots__/mergeConfigs.test.js.snap
Normal file
114
lib/core/src/server/__snapshots__/mergeConfigs.test.js.snap
Normal file
@ -0,0 +1,114 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`mergeConfigs merges partial custom config 1`] = `
|
||||
Object {
|
||||
"devtool": "source-maps",
|
||||
"entry": Object {
|
||||
"bundle": "index.js",
|
||||
},
|
||||
"module": Object {
|
||||
"rules": Array [
|
||||
"r1",
|
||||
"r2",
|
||||
],
|
||||
},
|
||||
"output": Object {
|
||||
"filename": "[name].js",
|
||||
},
|
||||
"plugins": Array [
|
||||
"p1",
|
||||
"p2",
|
||||
"p3",
|
||||
],
|
||||
"resolve": Object {
|
||||
"alias": Object {
|
||||
"A1": "src/B1",
|
||||
"A2": "src/B2",
|
||||
},
|
||||
"enforceModuleExtension": true,
|
||||
"extensions": Array [
|
||||
".js",
|
||||
".json",
|
||||
".ts",
|
||||
".tsx",
|
||||
],
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`mergeConfigs merges successfully if custom config is empty 1`] = `
|
||||
Object {
|
||||
"devtool": "source-maps",
|
||||
"entry": Object {
|
||||
"bundle": "index.js",
|
||||
},
|
||||
"module": Object {
|
||||
"rules": Array [
|
||||
"r1",
|
||||
"r2",
|
||||
],
|
||||
},
|
||||
"output": Object {
|
||||
"filename": "[name].js",
|
||||
},
|
||||
"plugins": Array [
|
||||
"p1",
|
||||
"p2",
|
||||
],
|
||||
"resolve": Object {
|
||||
"alias": Object {
|
||||
"A1": "src/B1",
|
||||
"A2": "src/B2",
|
||||
},
|
||||
"enforceModuleExtension": true,
|
||||
"extensions": Array [
|
||||
".js",
|
||||
".json",
|
||||
],
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`mergeConfigs merges two full configs in one 1`] = `
|
||||
Object {
|
||||
"devtool": "source-maps",
|
||||
"entry": Object {
|
||||
"bundle": "index.js",
|
||||
},
|
||||
"module": Object {
|
||||
"noParse": /jquery\\|lodash/,
|
||||
"rules": Array [
|
||||
"r1",
|
||||
"r2",
|
||||
"r3",
|
||||
"r4",
|
||||
],
|
||||
},
|
||||
"output": Object {
|
||||
"filename": "[name].js",
|
||||
},
|
||||
"plugins": Array [
|
||||
"p1",
|
||||
"p2",
|
||||
"p3",
|
||||
"p4",
|
||||
],
|
||||
"profile": true,
|
||||
"resolve": Object {
|
||||
"alias": Object {
|
||||
"A1": "src/B1",
|
||||
"A2": "src/B2",
|
||||
"A3": "src/B3",
|
||||
"A4": "src/B4",
|
||||
},
|
||||
"enforceExtension": false,
|
||||
"enforceModuleExtension": true,
|
||||
"extensions": Array [
|
||||
".js",
|
||||
".json",
|
||||
".ts",
|
||||
".tsx",
|
||||
],
|
||||
},
|
||||
}
|
||||
`;
|
@ -4,6 +4,7 @@ import { createDefaultWebpackConfig } from './config/defaults/webpack.config';
|
||||
import devBabelConfig from './config/babel';
|
||||
import loadCustomBabelConfig from './loadCustomBabelConfig';
|
||||
import loadCustomWebpackConfig from './loadCustomWebpackConfig';
|
||||
import mergeConfigs from './mergeConfigs';
|
||||
|
||||
const noopWrapper = config => config;
|
||||
|
||||
@ -17,36 +18,6 @@ function getBabelConfig({
|
||||
return wrapBabelConfig(loadCustomBabelConfig(configDir, defaultConfig));
|
||||
}
|
||||
|
||||
function mergeConfigs(config, customConfig) {
|
||||
return {
|
||||
...customConfig,
|
||||
// We'll always load our configurations after the custom config.
|
||||
// So, we'll always load the stuff we need.
|
||||
...config,
|
||||
// Override with custom devtool if provided
|
||||
devtool: customConfig.devtool || config.devtool,
|
||||
// We need to use our and custom plugins.
|
||||
plugins: [...config.plugins, ...(customConfig.plugins || [])],
|
||||
module: {
|
||||
...config.module,
|
||||
// We need to use our and custom rules.
|
||||
...customConfig.module,
|
||||
rules: [
|
||||
...config.module.rules,
|
||||
...((customConfig.module && customConfig.module.rules) || []),
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
...config.resolve,
|
||||
...customConfig.resolve,
|
||||
alias: {
|
||||
...config.alias,
|
||||
...(customConfig.resolve && customConfig.resolve.alias),
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function informAboutCustomConfig(defaultConfigName) {
|
||||
if (!defaultConfigName) {
|
||||
logger.info('=> Using default webpack setup.');
|
||||
|
@ -37,7 +37,7 @@ export function loadEnv(options = {}) {
|
||||
}
|
||||
|
||||
export function getEntries(configDir) {
|
||||
const preview = [require.resolve('./polyfills'), require.resolve('./globals')];
|
||||
const iframe = [require.resolve('./polyfills'), require.resolve('./globals')];
|
||||
const manager = [require.resolve('./polyfills'), require.resolve('../../client/manager')];
|
||||
|
||||
// Check whether a config.{ext} file exists inside the storybook
|
||||
@ -47,7 +47,7 @@ export function getEntries(configDir) {
|
||||
throw new Error(`=> Create a storybook config file in "${configDir}/config.{ext}".`);
|
||||
}
|
||||
|
||||
preview.push(require.resolve(storybookConfigPath));
|
||||
iframe.push(require.resolve(storybookConfigPath));
|
||||
|
||||
// Check whether addons.{ext} file exists inside the storybook.
|
||||
const storybookCustomAddonsPath = getInterpretedFile(path.resolve(configDir, 'addons'));
|
||||
@ -56,5 +56,5 @@ export function getEntries(configDir) {
|
||||
manager.unshift(storybookCustomAddonsPath);
|
||||
}
|
||||
|
||||
return { preview, manager };
|
||||
return { iframe, manager };
|
||||
}
|
||||
|
@ -2,12 +2,10 @@ import path from 'path';
|
||||
import webpack from 'webpack';
|
||||
import { getEnvironment } from 'universal-dotenv';
|
||||
import Dotenv from 'dotenv-webpack';
|
||||
import InterpolateHtmlPlugin from 'react-dev-utils/InterpolateHtmlPlugin';
|
||||
import WatchMissingNodeModulesPlugin from 'react-dev-utils/WatchMissingNodeModulesPlugin';
|
||||
import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin';
|
||||
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||
|
||||
import { getPreviewHeadHtml, getManagerHeadHtml } from '../utils';
|
||||
import GeneratePagePlugin from 'generate-page-webpack-plugin';
|
||||
import { getPreviewHeadHtml, getManagerHeadHtml, getPreviewBodyHtml } from '../utils';
|
||||
|
||||
import {
|
||||
includePaths,
|
||||
@ -21,13 +19,23 @@ import { version } from '../../../package.json';
|
||||
|
||||
export default ({ configDir, quiet, babelOptions }) => {
|
||||
const entries = getEntries(configDir, true);
|
||||
const entriesMeta = {
|
||||
iframe: {
|
||||
headHtmlSnippet: getPreviewHeadHtml(configDir, process.env),
|
||||
bodyHtmlSnippet: getPreviewBodyHtml(),
|
||||
},
|
||||
manager: {
|
||||
headHtmlSnippet: getManagerHeadHtml(configDir, process.env),
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
mode: 'development',
|
||||
devtool: 'cheap-module-source-map',
|
||||
entry: {
|
||||
...entries,
|
||||
preview: [
|
||||
...entries.preview,
|
||||
iframe: [
|
||||
...entries.iframe,
|
||||
`${require.resolve('webpack-hot-middleware/client')}?reload=true`,
|
||||
],
|
||||
},
|
||||
@ -42,26 +50,21 @@ export default ({ configDir, quiet, babelOptions }) => {
|
||||
publicPath: '',
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
chunks: ['manager'],
|
||||
chunksSortMode: 'none',
|
||||
data: {
|
||||
managerHead: getManagerHeadHtml(configDir),
|
||||
version,
|
||||
new GeneratePagePlugin(
|
||||
{
|
||||
template: require.resolve('../templates/index.html.ejs'),
|
||||
// eslint-disable-next-line global-require
|
||||
parser: require('ejs'),
|
||||
filename: entry => (entry === 'manager' ? 'index' : entry),
|
||||
},
|
||||
template: require.resolve('../index.html.ejs'),
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'iframe.html',
|
||||
excludeChunks: ['manager'],
|
||||
chunksSortMode: 'none',
|
||||
data: {
|
||||
previewHead: getPreviewHeadHtml(configDir),
|
||||
},
|
||||
template: require.resolve('../iframe.html.ejs'),
|
||||
}),
|
||||
new InterpolateHtmlPlugin(process.env),
|
||||
{
|
||||
data: { version },
|
||||
headHtmlSnippet: entry =>
|
||||
entriesMeta[entry] ? entriesMeta[entry].headHtmlSnippet : null,
|
||||
bodyHtmlSnippet: entry =>
|
||||
entriesMeta[entry] ? entriesMeta[entry].bodyHtmlSnippet : null,
|
||||
}
|
||||
),
|
||||
new webpack.DefinePlugin(loadEnv()),
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new CaseSensitivePathsPlugin(),
|
||||
|
@ -1,92 +1,100 @@
|
||||
import webpack from 'webpack';
|
||||
import { getEnvironment } from 'universal-dotenv';
|
||||
import Dotenv from 'dotenv-webpack';
|
||||
import InterpolateHtmlPlugin from 'react-dev-utils/InterpolateHtmlPlugin';
|
||||
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
||||
import GeneratePagePlugin from 'generate-page-webpack-plugin';
|
||||
|
||||
import { version } from '../../../package.json';
|
||||
import { getPreviewHeadHtml, getManagerHeadHtml } from '../utils';
|
||||
import { getPreviewHeadHtml, getManagerHeadHtml, getPreviewBodyHtml } from '../utils';
|
||||
|
||||
import { includePaths, excludePaths, loadEnv, nodePaths, getEntries } from './utils';
|
||||
|
||||
export default ({ configDir, babelOptions }) => ({
|
||||
mode: 'production',
|
||||
bail: true,
|
||||
devtool: '#cheap-module-source-map',
|
||||
entry: getEntries(configDir),
|
||||
output: {
|
||||
filename: 'static/[name].[chunkhash].bundle.js',
|
||||
// Here we set the publicPath to ''.
|
||||
// This allows us to deploy storybook into subpaths like GitHub pages.
|
||||
// This works with css and image loaders too.
|
||||
// This is working for storybook since, we don't use pushState urls and
|
||||
// relative URLs works always.
|
||||
publicPath: '',
|
||||
},
|
||||
plugins: [
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
chunks: ['manager', 'runtime~manager'],
|
||||
chunksSortMode: 'none',
|
||||
data: {
|
||||
managerHead: getManagerHeadHtml(configDir),
|
||||
version,
|
||||
},
|
||||
template: require.resolve('../index.html.ejs'),
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'iframe.html',
|
||||
excludeChunks: ['manager', 'runtime~manager'],
|
||||
chunksSortMode: 'none',
|
||||
data: {
|
||||
previewHead: getPreviewHeadHtml(configDir),
|
||||
},
|
||||
template: require.resolve('../iframe.html.ejs'),
|
||||
}),
|
||||
new InterpolateHtmlPlugin(process.env),
|
||||
new webpack.DefinePlugin(loadEnv({ production: true })),
|
||||
new webpack.DefinePlugin(getEnvironment().webpack),
|
||||
new Dotenv({ silent: true }),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
use: [
|
||||
{
|
||||
loader: require.resolve('babel-loader'),
|
||||
options: babelOptions,
|
||||
},
|
||||
],
|
||||
include: includePaths,
|
||||
exclude: excludePaths,
|
||||
},
|
||||
{
|
||||
test: /\.md$/,
|
||||
use: [
|
||||
{
|
||||
loader: require.resolve('raw-loader'),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
// Since we ship with json-loader always, it's better to move extensions to here
|
||||
// from the default config.
|
||||
extensions: ['.js', '.json'],
|
||||
// Add support to NODE_PATH. With this we could avoid relative path imports.
|
||||
// Based on this CRA feature: https://github.com/facebookincubator/create-react-app/issues/253
|
||||
modules: ['node_modules'].concat(nodePaths),
|
||||
},
|
||||
optimization: {
|
||||
// Automatically split vendor and commons for preview bundle
|
||||
// https://twitter.com/wSokra/status/969633336732905474
|
||||
splitChunks: {
|
||||
chunks: chunk => chunk.name !== 'manager',
|
||||
export default ({ configDir, babelOptions }) => {
|
||||
const entries = getEntries(configDir);
|
||||
|
||||
const entriesMeta = {
|
||||
iframe: {
|
||||
headHtmlSnippet: getPreviewHeadHtml(configDir, process.env),
|
||||
bodyHtmlSnippet: getPreviewBodyHtml(),
|
||||
},
|
||||
// Keep the runtime chunk seperated to enable long term caching
|
||||
// https://twitter.com/wSokra/status/969679223278505985
|
||||
runtimeChunk: true,
|
||||
},
|
||||
});
|
||||
manager: {
|
||||
headHtmlSnippet: getManagerHeadHtml(configDir, process.env),
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
mode: 'production',
|
||||
bail: true,
|
||||
devtool: '#cheap-module-source-map',
|
||||
entry: entries,
|
||||
output: {
|
||||
filename: 'static/[name].[chunkhash].bundle.js',
|
||||
// Here we set the publicPath to ''.
|
||||
// This allows us to deploy storybook into subpaths like GitHub pages.
|
||||
// This works with css and image loaders too.
|
||||
// This is working for storybook since, we don't use pushState urls and
|
||||
// relative URLs works always.
|
||||
publicPath: '',
|
||||
},
|
||||
plugins: [
|
||||
new GeneratePagePlugin(
|
||||
{
|
||||
template: require.resolve('../templates/index.html.ejs'),
|
||||
// eslint-disable-next-line global-require
|
||||
parser: require('ejs'),
|
||||
filename: entry => (entry === 'manager' ? 'index' : entry),
|
||||
},
|
||||
{
|
||||
data: { version },
|
||||
headHtmlSnippet: entry =>
|
||||
entriesMeta[entry] ? entriesMeta[entry].headHtmlSnippet : null,
|
||||
bodyHtmlSnippet: entry =>
|
||||
entriesMeta[entry] ? entriesMeta[entry].bodyHtmlSnippet : null,
|
||||
}
|
||||
),
|
||||
new webpack.DefinePlugin(loadEnv({ production: true })),
|
||||
new webpack.DefinePlugin(getEnvironment().webpack),
|
||||
new Dotenv({ silent: true }),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
use: [
|
||||
{
|
||||
loader: require.resolve('babel-loader'),
|
||||
options: babelOptions,
|
||||
},
|
||||
],
|
||||
include: includePaths,
|
||||
exclude: excludePaths,
|
||||
},
|
||||
{
|
||||
test: /\.md$/,
|
||||
use: [
|
||||
{
|
||||
loader: require.resolve('raw-loader'),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
// Since we ship with json-loader always, it's better to move extensions to here
|
||||
// from the default config.
|
||||
extensions: ['.js', '.json'],
|
||||
// Add support to NODE_PATH. With this we could avoid relative path imports.
|
||||
// Based on this CRA feature: https://github.com/facebookincubator/create-react-app/issues/253
|
||||
modules: ['node_modules'].concat(nodePaths),
|
||||
},
|
||||
optimization: {
|
||||
// Automatically split vendor and commons for preview bundle
|
||||
// https://twitter.com/wSokra/status/969633336732905474
|
||||
splitChunks: {
|
||||
chunks: chunk => chunk.name !== 'manager',
|
||||
},
|
||||
// Keep the runtime chunk seperated to enable long term caching
|
||||
// https://twitter.com/wSokra/status/969679223278505985
|
||||
runtimeChunk: true,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -1,89 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible" />
|
||||
<base target="_parent">
|
||||
<title>Storybook</title>
|
||||
<link rel="shortcut icon" href="favicon.ico?v=1" />
|
||||
<%= htmlWebpackPlugin.options.data.previewHead %>
|
||||
<style>
|
||||
:not(.sb-show-main) > .sb-main,
|
||||
:not(.sb-show-nopreview) > .sb-nopreview,
|
||||
:not(.sb-show-errordisplay) > .sb-errordisplay {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
.sb-wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 20px;
|
||||
font-family: -apple-system, ".SFNSText-Regular", "San Francisco", Roboto, "Segoe UI", "Helvetica Neue", "Lucida Grande", sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.sb-heading {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.2px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
|
||||
.sb-nopreview {
|
||||
display: flex;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sb-nopreview_main {
|
||||
margin: auto;
|
||||
padding: 30px;
|
||||
border-radius: 10px;
|
||||
background: rgba(0,0,0,0.03);
|
||||
}
|
||||
|
||||
.sb-nopreview_heading {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
.sb-errordisplay {
|
||||
background-color: rgb(187, 49, 49);
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
.sb-errordisplay_code {
|
||||
font-size: 14px;
|
||||
width: 100vw;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="sb-show-main">
|
||||
<div id="root" class="sb-main"></div>
|
||||
|
||||
<div class="sb-nopreview sb-wrapper">
|
||||
<div class="sb-nopreview_main">
|
||||
<h1 class="sb-nopreview_heading sb-heading">No Preview</h1>
|
||||
<p>Sorry, but you either have no stories or none are selected somehow.</p>
|
||||
<ul>
|
||||
<li>Please check the storybook config.</li>
|
||||
<li>Try reloading the page.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sb-errordisplay sb-wrapper">
|
||||
<div id="error-message" class="sb-heading"></div>
|
||||
<pre class="sb-errordisplay_code">
|
||||
<code id="error-stack"></code>
|
||||
</pre>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,23 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="storybook-version" content="<%= htmlWebpackPlugin.options.data.version %>">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible" />
|
||||
<title>Storybook</title>
|
||||
<link rel="shortcut icon" href="favicon.ico?v=1" />
|
||||
<%= htmlWebpackPlugin.options.data.managerHead %>
|
||||
|
||||
</head>
|
||||
<body style="margin: 0;">
|
||||
<style>
|
||||
html, body {
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
50
lib/core/src/server/mergeConfigs.js
Normal file
50
lib/core/src/server/mergeConfigs.js
Normal file
@ -0,0 +1,50 @@
|
||||
function plugins({ plugins: defaultPlugins = [] }, { plugins: customPlugins = [] }) {
|
||||
return [...defaultPlugins, ...customPlugins];
|
||||
}
|
||||
|
||||
function rules({ rules: defaultRules = [] }, { rules: customRules = [] }) {
|
||||
return [...defaultRules, ...customRules];
|
||||
}
|
||||
|
||||
function extensions({ extensions: defaultExtensions = [] }, { extensions: customExtensions = [] }) {
|
||||
return [...defaultExtensions, ...customExtensions];
|
||||
}
|
||||
|
||||
function alias({ alias: defaultAlias = {} }, { alias: customAlias = {} }) {
|
||||
return {
|
||||
...defaultAlias,
|
||||
...customAlias,
|
||||
};
|
||||
}
|
||||
|
||||
function module({ module: defaultModule = {} }, { module: customModule = {} }) {
|
||||
return {
|
||||
...defaultModule,
|
||||
...customModule,
|
||||
rules: rules(defaultModule, customModule),
|
||||
};
|
||||
}
|
||||
|
||||
function resolve({ resolve: defaultResolve = {} }, { resolve: customResolve = {} }) {
|
||||
return {
|
||||
...defaultResolve,
|
||||
...customResolve,
|
||||
alias: alias(defaultResolve, customResolve),
|
||||
extensions: extensions(defaultResolve, customResolve),
|
||||
};
|
||||
}
|
||||
|
||||
function mergeConfigs(config, customConfig) {
|
||||
return {
|
||||
// We'll always load our configurations after the custom config.
|
||||
// So, we'll always load the stuff we need.
|
||||
...customConfig,
|
||||
...config,
|
||||
devtool: customConfig.devtool || config.devtool,
|
||||
plugins: plugins(config, customConfig),
|
||||
module: module(config, customConfig),
|
||||
resolve: resolve(config, customConfig),
|
||||
};
|
||||
}
|
||||
|
||||
export default mergeConfigs;
|
75
lib/core/src/server/mergeConfigs.test.js
Normal file
75
lib/core/src/server/mergeConfigs.test.js
Normal file
@ -0,0 +1,75 @@
|
||||
import mergeConfigs from './mergeConfigs';
|
||||
|
||||
const config = {
|
||||
devtool: 'source-maps',
|
||||
entry: {
|
||||
bundle: 'index.js',
|
||||
},
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
},
|
||||
module: {
|
||||
rules: ['r1', 'r2'],
|
||||
},
|
||||
plugins: ['p1', 'p2'],
|
||||
resolve: {
|
||||
enforceModuleExtension: true,
|
||||
extensions: ['.js', '.json'],
|
||||
alias: {
|
||||
A1: 'src/B1',
|
||||
A2: 'src/B2',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
describe('mergeConfigs', () => {
|
||||
it('merges two full configs in one', () => {
|
||||
const customConfig = {
|
||||
profile: true,
|
||||
entry: {
|
||||
bundle: 'should_not_be_merged.js',
|
||||
},
|
||||
output: {
|
||||
filename: 'should_not_be_merged.js',
|
||||
},
|
||||
module: {
|
||||
noParse: /jquery|lodash/,
|
||||
rules: ['r3', 'r4'],
|
||||
},
|
||||
plugins: ['p3', 'p4'],
|
||||
resolve: {
|
||||
enforceExtension: false,
|
||||
extensions: ['.ts', '.tsx'],
|
||||
alias: {
|
||||
A3: 'src/B3',
|
||||
A4: 'src/B4',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = mergeConfigs(config, customConfig);
|
||||
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('merges partial custom config', () => {
|
||||
const customConfig = {
|
||||
plugins: ['p3'],
|
||||
resolve: {
|
||||
extensions: ['.ts', '.tsx'],
|
||||
},
|
||||
};
|
||||
|
||||
const result = mergeConfigs(config, customConfig);
|
||||
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('merges successfully if custom config is empty', () => {
|
||||
const customConfig = {};
|
||||
|
||||
const result = mergeConfigs(config, customConfig);
|
||||
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
});
|
16
lib/core/src/server/templates/base-manager-head.html
Normal file
16
lib/core/src/server/templates/base-manager-head.html
Normal file
@ -0,0 +1,16 @@
|
||||
<style>
|
||||
html, body {
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
if (window.parent !== window) {
|
||||
window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = window.parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
||||
window.__VUE_DEVTOOLS_GLOBAL_HOOK__ = window.parent.__VUE_DEVTOOLS_GLOBAL_HOOK__;
|
||||
}
|
||||
</script>
|
17
lib/core/src/server/templates/base-preview-body.html
Normal file
17
lib/core/src/server/templates/base-preview-body.html
Normal file
@ -0,0 +1,17 @@
|
||||
<div class="sb-nopreview sb-wrapper">
|
||||
<div class="sb-nopreview_main">
|
||||
<h1 class="sb-nopreview_heading sb-heading">No Preview</h1>
|
||||
<p>Sorry, but you either have no stories or none are selected somehow.</p>
|
||||
<ul>
|
||||
<li>Please check the storybook config.</li>
|
||||
<li>Try reloading the page.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sb-errordisplay sb-wrapper">
|
||||
<div id="error-message" class="sb-heading"></div>
|
||||
<pre class="sb-errordisplay_code">
|
||||
<code id="error-stack"></code>
|
||||
</pre>
|
||||
</div>
|
62
lib/core/src/server/templates/base-preview-head.html
Normal file
62
lib/core/src/server/templates/base-preview-head.html
Normal file
@ -0,0 +1,62 @@
|
||||
<base target="_parent">
|
||||
|
||||
<style>
|
||||
:not(.sb-show-main) > .sb-main,
|
||||
:not(.sb-show-nopreview) > .sb-nopreview,
|
||||
:not(.sb-show-errordisplay) > .sb-errordisplay {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sb-wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 20px;
|
||||
font-family: -apple-system, ".SFNSText-Regular", "San Francisco", Roboto, "Segoe UI", "Helvetica Neue", "Lucida Grande", sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.sb-heading {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.2px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.sb-nopreview {
|
||||
display: flex;
|
||||
align-content: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sb-nopreview_main {
|
||||
margin: auto;
|
||||
padding: 30px;
|
||||
border-radius: 10px;
|
||||
background: rgba(0,0,0,0.03);
|
||||
}
|
||||
|
||||
.sb-nopreview_heading {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sb-errordisplay {
|
||||
background-color: rgb(187, 49, 49);
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
.sb-errordisplay_code {
|
||||
font-size: 14px;
|
||||
width: 100vw;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
if (window.parent !== window) {
|
||||
window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = window.parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
||||
window.__VUE_DEVTOOLS_GLOBAL_HOOK__ = window.parent.__VUE_DEVTOOLS_GLOBAL_HOOK__;
|
||||
}
|
||||
</script>
|
56
lib/core/src/server/templates/index.html.ejs
Normal file
56
lib/core/src/server/templates/index.html.ejs
Normal file
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta content="IE=edge" http-equiv="X-UA-Compatible" />
|
||||
<title>Storybook</title>
|
||||
<link rel="shortcut icon" href="favicon.ico?v=1" />
|
||||
|
||||
<% if (options.links) { %>
|
||||
<% for (item of options.links) { %>
|
||||
<% if (typeof item === 'string' || item instanceof String) { item = { href: item, rel: 'stylesheet' } } %>
|
||||
<link<% for (key in item) { %> <%= key %>="<%= item[key] %>"<% } %>>
|
||||
<% } %>
|
||||
<% } %>
|
||||
|
||||
<% if (options.headHtmlSnippet) { %>
|
||||
<%- options.headHtmlSnippet %>
|
||||
<% } %>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<% if (options.window) { %>
|
||||
<script>
|
||||
<% for (key in options.window) { %>
|
||||
window['<%= key %>'] = <%= JSON.stringify(options.window[key]) %>;
|
||||
<% } %>
|
||||
</script>
|
||||
<% } %>
|
||||
|
||||
<% if (options.bodyHtmlSnippet) { %>
|
||||
<%- options.bodyHtmlSnippet %>
|
||||
<% } %>
|
||||
|
||||
<div id="root"></div>
|
||||
|
||||
<% if (options.scripts) { %>
|
||||
<% for (item of options.scripts) { %>
|
||||
<% if (typeof item === 'string' || item instanceof String) { item = { src: item } } %>
|
||||
<script <% for (key in item) { %> <%= key %>="<%= item[key] %>"<% } %> defer></script>
|
||||
<% } %>
|
||||
<% } %>
|
||||
|
||||
<% for (key in dlls) { %>
|
||||
<script src="<%= compilation.outputOptions.publicPath %><%= dlls[key] %>" defer></script>
|
||||
<% } %>
|
||||
|
||||
<% for (index in chunks) { %>
|
||||
<% for (key in chunks[index].files) { %>
|
||||
<script src="<%= compilation.outputOptions.publicPath %><%= chunks[index].files[key] %>" defer></script>
|
||||
<% } %>
|
||||
<% } %>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -27,22 +27,35 @@ export function getMiddleware(configDir) {
|
||||
return () => {};
|
||||
}
|
||||
|
||||
export function getPreviewHeadHtml(configDirPath) {
|
||||
const interpolate = (string, data = {}) =>
|
||||
Object.entries(data).reduce((acc, [k, v]) => acc.replace(`%${k}%`, v), string);
|
||||
|
||||
export function getPreviewBodyHtml() {
|
||||
return fs.readFileSync(path.resolve(__dirname, 'templates/base-preview-body.html'), 'utf8');
|
||||
}
|
||||
|
||||
export function getPreviewHeadHtml(configDirPath, interpolations) {
|
||||
const base = fs.readFileSync(path.resolve(__dirname, 'templates/base-preview-head.html'), 'utf8');
|
||||
const headHtmlPath = path.resolve(configDirPath, 'preview-head.html');
|
||||
|
||||
let result = base;
|
||||
|
||||
if (fs.existsSync(headHtmlPath)) {
|
||||
return fs.readFileSync(headHtmlPath, 'utf8');
|
||||
result += fs.readFileSync(headHtmlPath, 'utf8');
|
||||
}
|
||||
|
||||
return '';
|
||||
return interpolate(result, interpolations);
|
||||
}
|
||||
|
||||
export function getManagerHeadHtml(configDirPath) {
|
||||
export function getManagerHeadHtml(configDirPath, interpolations) {
|
||||
const base = fs.readFileSync(path.resolve(__dirname, 'templates/base-manager-head.html'), 'utf8');
|
||||
const scriptPath = path.resolve(configDirPath, 'manager-head.html');
|
||||
|
||||
let result = base;
|
||||
|
||||
if (fs.existsSync(scriptPath)) {
|
||||
return fs.readFileSync(scriptPath, 'utf8');
|
||||
result += fs.readFileSync(scriptPath, 'utf8');
|
||||
}
|
||||
|
||||
return '';
|
||||
return interpolate(result, interpolations);
|
||||
}
|
||||
|
@ -2,11 +2,13 @@ import mock from 'mock-fs';
|
||||
import { getPreviewHeadHtml } from './utils';
|
||||
|
||||
const HEAD_HTML_CONTENTS = '<script>console.log("custom script!");</script>';
|
||||
const BASE_HTML_CONTENTS = '<script>console.log("base script!");</script>';
|
||||
|
||||
describe('server.getPreviewHeadHtml', () => {
|
||||
describe('when .storybook/preview-head.html does not exist', () => {
|
||||
beforeEach(() => {
|
||||
mock({
|
||||
[`${__dirname}/templates/base-preview-head.html`]: BASE_HTML_CONTENTS,
|
||||
config: {},
|
||||
});
|
||||
});
|
||||
@ -17,13 +19,14 @@ describe('server.getPreviewHeadHtml', () => {
|
||||
|
||||
it('return an empty string', () => {
|
||||
const result = getPreviewHeadHtml('./config');
|
||||
expect(result).toEqual('');
|
||||
expect(result).toEqual(BASE_HTML_CONTENTS);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when .storybook/preview-head.html exists', () => {
|
||||
beforeEach(() => {
|
||||
mock({
|
||||
[`${__dirname}/templates/base-preview-head.html`]: BASE_HTML_CONTENTS,
|
||||
config: {
|
||||
'preview-head.html': HEAD_HTML_CONTENTS,
|
||||
},
|
||||
@ -36,7 +39,7 @@ describe('server.getPreviewHeadHtml', () => {
|
||||
|
||||
it('return the contents of the file', () => {
|
||||
const result = getPreviewHeadHtml('./config');
|
||||
expect(result).toEqual(HEAD_HTML_CONTENTS);
|
||||
expect(result).toEqual(BASE_HTML_CONTENTS + HEAD_HTML_CONTENTS);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -112,6 +112,7 @@
|
||||
"remark-lint": "^6.0.2",
|
||||
"remark-preset-lint-recommended": "^3.0.2",
|
||||
"shelljs": "^0.8.2",
|
||||
"svelte-jest": "^0.2.0",
|
||||
"tslint": "~5.11.0",
|
||||
"tslint-config-prettier": "^1.14.0",
|
||||
"tslint-plugin-prettier": "^1.3.0",
|
||||
@ -175,6 +176,7 @@
|
||||
"examples/mithril-kitchen-sink",
|
||||
"examples/polymer-cli",
|
||||
"examples/vue-kitchen-sink",
|
||||
"examples/svelte-kitchen-sink",
|
||||
"examples/official-storybook",
|
||||
"lib/cli/test/run/*"
|
||||
]
|
||||
|
@ -2,7 +2,7 @@
|
||||
#
|
||||
# This builds all the example storybooks for running chromatic on your dev machine
|
||||
|
||||
examples=(angular-cli cra-kitchen-sink html-kitchen-sink marko-cli mithril-kitchen-sink polymer-cli vue-kitchen-sink official-storybook)
|
||||
examples=(angular-cli cra-kitchen-sink html-kitchen-sink marko-cli mithril-kitchen-sink polymer-cli vue-kitchen-sink svelte-kitchen-sink official-storybook)
|
||||
|
||||
for example in "${examples[@]}"
|
||||
do
|
||||
|
@ -28,6 +28,13 @@ elif [ "$BUILD_CONTEXT" = "VUE" ]; then
|
||||
yarn build-storybook
|
||||
mv storybook-static ../../netlify-build
|
||||
popd
|
||||
elif [ "$BUILD_CONTEXT" = "SVELTE" ]; then
|
||||
echo "netlify-build Svelte examples"
|
||||
pushd examples/svelte-kitchen-sink
|
||||
yarn
|
||||
yarn build-storybook
|
||||
mv storybook-static ../../netlify-build
|
||||
popd
|
||||
elif [ "$BUILD_CONTEXT" = "ANGULAR" ]; then
|
||||
echo "netlify-build Angular examples"
|
||||
pushd examples/angular-cli
|
||||
|
@ -43,7 +43,7 @@ const createOption = ({ defaultValue, option, name, extraParam }) => ({
|
||||
|
||||
const tasks = {
|
||||
core: createProject({
|
||||
name: `Core & React & Vue & Polymer & Angular ${chalk.gray('(core)')}`,
|
||||
name: `Core & React & Vue & Polymer & Angular & Svelte ${chalk.gray('(core)')}`,
|
||||
defaultValue: true,
|
||||
option: '--core',
|
||||
projectLocation: path.join(__dirname, '..'),
|
||||
|
50
yarn.lock
50
yarn.lock
@ -5822,6 +5822,10 @@ ejs@^2.5.7:
|
||||
version "2.5.7"
|
||||
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.7.tgz#cc872c168880ae3c7189762fd5ffc00896c9518a"
|
||||
|
||||
ejs@^2.6.1:
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.6.1.tgz#498ec0d495655abc6f23cd61868d926464071aa0"
|
||||
|
||||
ejson@^2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.yarnpkg.com/ejson/-/ejson-2.1.2.tgz#0eed4055bc7e0e7561fe59e8c320edc3ff8ce7df"
|
||||
@ -6394,14 +6398,7 @@ eslint-plugin-jsx-a11y@^6.1.1:
|
||||
has "^1.0.3"
|
||||
jsx-ast-utils "^2.0.1"
|
||||
|
||||
eslint-plugin-prettier@^2.2.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.4.0.tgz#85cab0775c6d5e3344ef01e78d960f166fb93aae"
|
||||
dependencies:
|
||||
fast-diff "^1.1.1"
|
||||
jest-docblock "^21.0.0"
|
||||
|
||||
eslint-plugin-prettier@^2.6.2:
|
||||
eslint-plugin-prettier@^2.2.0, eslint-plugin-prettier@^2.6.2:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.2.tgz#71998c60aedfa2141f7bfcbf9d1c459bf98b4fad"
|
||||
dependencies:
|
||||
@ -7584,6 +7581,10 @@ gaze@^1.0.0:
|
||||
dependencies:
|
||||
globule "^1.0.0"
|
||||
|
||||
generate-page-webpack-plugin@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/generate-page-webpack-plugin/-/generate-page-webpack-plugin-1.0.0.tgz#e6261efb7e6b9ef8a8136126b14fa26aedfb7f33"
|
||||
|
||||
genfun@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/genfun/-/genfun-4.0.1.tgz#ed10041f2e4a7f1b0a38466d17a5c3e27df1dfc1"
|
||||
@ -14654,7 +14655,7 @@ react-docgen@^3.0.0-beta12:
|
||||
node-dir "^0.1.10"
|
||||
recast "^0.12.6"
|
||||
|
||||
react-dom@^16.4.2:
|
||||
react-dom@^16.4.0, react-dom@^16.4.2:
|
||||
version "16.4.2"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.4.2.tgz#4afed569689f2c561d2b8da0b819669c38a0bda4"
|
||||
dependencies:
|
||||
@ -14952,7 +14953,7 @@ react-transition-group@^1.1.2:
|
||||
prop-types "^15.5.6"
|
||||
warning "^3.0.0"
|
||||
|
||||
react@^16.4.2:
|
||||
react@^16.4.0, react@^16.4.2:
|
||||
version "16.4.2"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-16.4.2.tgz#2cd90154e3a9d9dd8da2991149fdca3c260e129f"
|
||||
dependencies:
|
||||
@ -17306,6 +17307,25 @@ supports-hyperlinks@^1.0.1:
|
||||
has-flag "^2.0.0"
|
||||
supports-color "^5.0.0"
|
||||
|
||||
svelte-dev-helper@^1.1.7:
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/svelte-dev-helper/-/svelte-dev-helper-1.1.7.tgz#b7d887c7be5abf7e2436f9467560061b1e2a935f"
|
||||
|
||||
svelte-jest@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/svelte-jest/-/svelte-jest-0.2.0.tgz#a05ed16d092e8916de7a4526d1d5673499094756"
|
||||
|
||||
svelte-loader@^2.9.1:
|
||||
version "2.9.1"
|
||||
resolved "https://registry.yarnpkg.com/svelte-loader/-/svelte-loader-2.9.1.tgz#e493c51ac6c2fe53867b1512abf46eb991ca3205"
|
||||
dependencies:
|
||||
loader-utils "^1.1.0"
|
||||
svelte-dev-helper "^1.1.7"
|
||||
|
||||
svelte@^2.7.2:
|
||||
version "2.7.2"
|
||||
resolved "https://registry.yarnpkg.com/svelte/-/svelte-2.7.2.tgz#17019df4997d10206378fb45136b8cbb6edf2611"
|
||||
|
||||
svg-tags@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764"
|
||||
@ -17806,14 +17826,14 @@ tsickle@^0.32.1:
|
||||
source-map "^0.6.0"
|
||||
source-map-support "^0.5.0"
|
||||
|
||||
tslib@^1.7.1, tslib@^1.8.0, tslib@^1.8.1:
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.8.1.tgz#6946af2d1d651a7b1863b531d6e5afa41aa44eac"
|
||||
|
||||
tslib@^1.9.0:
|
||||
tslib@^1.7.1, tslib@^1.9.0:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
|
||||
|
||||
tslib@^1.8.0, tslib@^1.8.1:
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.8.1.tgz#6946af2d1d651a7b1863b531d6e5afa41aa44eac"
|
||||
|
||||
tslint-config-prettier@^1.14.0:
|
||||
version "1.14.0"
|
||||
resolved "https://registry.yarnpkg.com/tslint-config-prettier/-/tslint-config-prettier-1.14.0.tgz#860b36634e53f4c70c64c51ff3ef7fd9bbab7676"
|
||||
|
Loading…
x
Reference in New Issue
Block a user