diff --git a/addons/essentials/src/index.ts b/addons/essentials/src/index.ts index d95fb32acf8..470d8d192f6 100644 --- a/addons/essentials/src/index.ts +++ b/addons/essentials/src/index.ts @@ -35,6 +35,6 @@ export function addons(options: PresetOptions = {}) { const main = requireMain(options.configDir); return ['actions', 'docs', 'backgrounds', 'viewport'] .filter((key) => (options as any)[key] !== false) - .map((key) => `@storybook/addon-${key}`) + .map((key) => require.resolve(`@storybook/addon-${key}`)) .filter((addon) => !checkInstalled(addon, main)); } diff --git a/app/angular/src/demo/welcome.component.ts b/app/angular/src/demo/welcome.component.ts index ab8309c1a58..9d97760c1d2 100644 --- a/app/angular/src/demo/welcome.component.ts +++ b/app/angular/src/demo/welcome.component.ts @@ -51,11 +51,9 @@ import { Component, Output, EventEmitter } from '@angular/core'; font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; background-color: #ffffff; } - .note { opacity: 0.5; } - .inline-code { font-size: 15px; font-weight: 600; @@ -65,7 +63,6 @@ import { Component, Output, EventEmitter } from '@angular/core'; background-color: #f3f2f2; color: #3a3a3a; } - a { color: #1474f3; text-decoration: none; diff --git a/app/aurelia/demo.d.ts b/app/aurelia/demo.d.ts deleted file mode 100644 index 0183b7ef451..00000000000 --- a/app/aurelia/demo.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module '@storybook/aurelia/demo' { - export const Button: any; - export const Welcome: any; -} diff --git a/app/aurelia/demo.js b/app/aurelia/demo.js deleted file mode 100644 index 64bcd548d7e..00000000000 --- a/app/aurelia/demo.js +++ /dev/null @@ -1,5 +0,0 @@ -/* eslint-disable global-require */ -module.exports = { - Welcome: require('./dist/demo/welcome').default, - Button: require('./dist/demo/button').default, -}; diff --git a/app/aurelia/src/demo/index.ts b/app/aurelia/src/demo/index.ts deleted file mode 100644 index 9463e32d9b5..00000000000 --- a/app/aurelia/src/demo/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as Button } from './button'; -export { default as Welcome } from './welcome'; diff --git a/app/aurelia/src/demo/button.ts b/examples/aurelia-kitchen-sink/src/stories/button.ts similarity index 100% rename from app/aurelia/src/demo/button.ts rename to examples/aurelia-kitchen-sink/src/stories/button.ts diff --git a/examples/aurelia-kitchen-sink/src/stories/mdx.stories.mdx b/examples/aurelia-kitchen-sink/src/stories/mdx.stories.mdx index 1d2eebc447a..cce4f666a6e 100644 --- a/examples/aurelia-kitchen-sink/src/stories/mdx.stories.mdx +++ b/examples/aurelia-kitchen-sink/src/stories/mdx.stories.mdx @@ -1,10 +1,10 @@ import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'; import { CoolButton } from '../cool-button/cool-button'; -import { Button } from '@storybook/aurelia/demo'; import { addComponents } from '@storybook/aurelia'; -import { text, withKnobs, } from '@storybook/addon-knobs'; +import { text, withKnobs } from '@storybook/addon-knobs'; +import Button from './button'; - + # Welcome @@ -15,10 +15,8 @@ This is a test document written in MDX that defines a `CoolButton` story wrapped {{ template: ``, state: { - testText: text('asfdafds', 'asasfdsa') - } + testText: text('asfdafds', 'asasfdsa'), + }, }} - - diff --git a/lib/cli/.babelrc.json b/lib/cli/.babelrc.json index 9ab56eefbb5..d2ad1c00b00 100644 --- a/lib/cli/.babelrc.json +++ b/lib/cli/.babelrc.json @@ -12,6 +12,7 @@ ] ], "ignore": [ + "./src/frameworks", "./src/generators/**/template", "./src/generators/**/template-csf", "./src/generators/**/template-csf-ts", diff --git a/lib/cli/src/generators/.eslintrc.js b/lib/cli/src/.eslintrc.js similarity index 53% rename from lib/cli/src/generators/.eslintrc.js rename to lib/cli/src/.eslintrc.js index d7fac90c788..ae114bfdcc2 100644 --- a/lib/cli/src/generators/.eslintrc.js +++ b/lib/cli/src/.eslintrc.js @@ -3,16 +3,17 @@ const ignore = 0; module.exports = { overrides: [ { - files: '*/template[-?]*/**', + files: '**/template[-?]*/**', env: { browser: true, }, rules: { 'react/no-this-in-sfc': ignore, 'import/no-unresolved': ignore, + 'react/react-in-jsx-scope': ignore, 'import/no-extraneous-dependencies': ignore, 'global-require': ignore, - 'react/react-in-jsx-scope': ignore, + 'no-redeclare': ignore, }, }, { @@ -21,5 +22,18 @@ module.exports = { browser: false, }, }, + { + files: 'frameworks/**/*', + env: { + browser: true, + }, + rules: { + 'jsx-a11y/anchor-is-valid': ignore, + 'import/no-unresolved': ignore, + 'react/prop-types': ignore, + 'react/react-in-jsx-scope': ignore, + 'import/no-extraneous-dependencies': ignore, + }, + }, ], }; diff --git a/lib/cli/src/generators/AURELIA/template-csf/src/stories/0-Welcome.stories.ts b/lib/cli/src/frameworks/angular/0-Welcome.stories.ts similarity index 77% rename from lib/cli/src/generators/AURELIA/template-csf/src/stories/0-Welcome.stories.ts rename to lib/cli/src/frameworks/angular/0-Welcome.stories.ts index 92ddbc26b27..38786fa3260 100644 --- a/lib/cli/src/generators/AURELIA/template-csf/src/stories/0-Welcome.stories.ts +++ b/lib/cli/src/frameworks/angular/0-Welcome.stories.ts @@ -1,4 +1,4 @@ -import { Welcome } from '@storybook/aurelia/demo'; +import Welcome from './welcome.component'; export default { title: 'Welcome', diff --git a/lib/cli/src/generators/ANGULAR/template-csf/src/stories/1-Button.stories.ts b/lib/cli/src/frameworks/angular/1-Button.stories.ts similarity index 94% rename from lib/cli/src/generators/ANGULAR/template-csf/src/stories/1-Button.stories.ts rename to lib/cli/src/frameworks/angular/1-Button.stories.ts index 4f740006eac..e82ad1c3156 100644 --- a/lib/cli/src/generators/ANGULAR/template-csf/src/stories/1-Button.stories.ts +++ b/lib/cli/src/frameworks/angular/1-Button.stories.ts @@ -1,7 +1,7 @@ import { action } from '@storybook/addon-actions'; import { linkTo } from '@storybook/addon-links'; -import { Button } from '@storybook/angular/demo'; +import Button from './button.component'; export default { title: 'Button', diff --git a/lib/cli/src/frameworks/angular/button.component.ts b/lib/cli/src/frameworks/angular/button.component.ts new file mode 100644 index 00000000000..da804e507b7 --- /dev/null +++ b/lib/cli/src/frameworks/angular/button.component.ts @@ -0,0 +1,26 @@ +import { Component, Input, Output, EventEmitter } from '@angular/core'; + +@Component({ + selector: 'storybook-button-component', + template: ` `, + styles: [ + ` + button { + border: 1px solid #eee; + border-radius: 3px; + background-color: #ffffff; + cursor: pointer; + font-size: 15px; + padding: 3px 10px; + margin: 10px; + } + `, + ], +}) +export default class ButtonComponent { + @Input() + text = ''; + + @Output() + onClick = new EventEmitter(); +} diff --git a/lib/cli/src/frameworks/angular/welcome.component.ts b/lib/cli/src/frameworks/angular/welcome.component.ts new file mode 100644 index 00000000000..ab8309c1a58 --- /dev/null +++ b/lib/cli/src/frameworks/angular/welcome.component.ts @@ -0,0 +1,81 @@ +import { Component, Output, EventEmitter } from '@angular/core'; + +@Component({ + selector: 'storybook-welcome-component', + template: ` +
+

Welcome to storybook

+

This is a UI component dev environment for your app.

+

+ We've added some basic stories inside the + src/stories directory.
+ A story is a single state of one or more UI components. You can have as many stories as you + want.
+ (Basically a story is like a visual test case.) +

+

+ See these sample + stories for a component + called Button . +

+

+ Just like that, you can add your own components as stories.
+ You can also edit those components and see changes right away.
+ (Try editing the Button stories located at + src/stories/index.js.) +

+

+ Usually we create stories with smaller UI components in the app.
+ Have a look at the + + Writing Stories + + section in our documentation. +

+

+ NOTE:
+ Have a look at the .storybook/webpack.config.js to add + webpack loaders and plugins you are using in this project. +

+
+ `, + styles: [ + ` + main { + padding: 15px; + line-height: 1.4; + font-family: 'Helvetica Neue', Helvetica, 'Segoe UI', Arial, freesans, sans-serif; + background-color: #ffffff; + } + + .note { + opacity: 0.5; + } + + .inline-code { + font-size: 15px; + font-weight: 600; + padding: 2px 5px; + border: 1px solid #eae9e9; + border-radius: 4px; + background-color: #f3f2f2; + color: #3a3a3a; + } + + a { + color: #1474f3; + text-decoration: none; + border-bottom: 1px solid #1474f3; + padding-bottom: 2px; + } + `, + ], +}) +export default class WelcomeComponent { + @Output() + showApp = new EventEmitter(); +} diff --git a/lib/cli/src/generators/ANGULAR/template-csf/src/stories/0-Welcome.stories.ts b/lib/cli/src/frameworks/aurelia/0-Welcome.stories.ts similarity index 77% rename from lib/cli/src/generators/ANGULAR/template-csf/src/stories/0-Welcome.stories.ts rename to lib/cli/src/frameworks/aurelia/0-Welcome.stories.ts index 058c0cc1355..acefc457a07 100644 --- a/lib/cli/src/generators/ANGULAR/template-csf/src/stories/0-Welcome.stories.ts +++ b/lib/cli/src/frameworks/aurelia/0-Welcome.stories.ts @@ -1,4 +1,4 @@ -import { Welcome } from '@storybook/angular/demo'; +import Welcome from './welcome'; export default { title: 'Welcome', diff --git a/lib/cli/src/generators/AURELIA/template-csf/src/stories/1-Button.stories.ts b/lib/cli/src/frameworks/aurelia/1-Button.stories.ts similarity index 94% rename from lib/cli/src/generators/AURELIA/template-csf/src/stories/1-Button.stories.ts rename to lib/cli/src/frameworks/aurelia/1-Button.stories.ts index 436ff09cb41..25989973d3a 100644 --- a/lib/cli/src/generators/AURELIA/template-csf/src/stories/1-Button.stories.ts +++ b/lib/cli/src/frameworks/aurelia/1-Button.stories.ts @@ -1,7 +1,7 @@ import { action } from '@storybook/addon-actions'; import { linkTo } from '@storybook/addon-links'; -import { Button } from '@storybook/aurelia/demo'; +import Button from './button'; export default { title: 'Button', diff --git a/lib/cli/src/frameworks/aurelia/button.ts b/lib/cli/src/frameworks/aurelia/button.ts new file mode 100644 index 00000000000..86cac656b57 --- /dev/null +++ b/lib/cli/src/frameworks/aurelia/button.ts @@ -0,0 +1,28 @@ +import { customElement, bindable } from 'aurelia'; + +@customElement({ + name: 'storybook-button-component', + template: ` + + `, +}) +export default class Button { + @bindable() + text = ''; + + @bindable() + onClick: MouseEvent; +} diff --git a/app/aurelia/src/demo/welcome.ts b/lib/cli/src/frameworks/aurelia/welcome.ts similarity index 100% rename from app/aurelia/src/demo/welcome.ts rename to lib/cli/src/frameworks/aurelia/welcome.ts diff --git a/lib/cli/src/generators/EMBER/template-csf/stories/0-Welcome.stories.js b/lib/cli/src/frameworks/ember/0-Welcome.stories.js similarity index 100% rename from lib/cli/src/generators/EMBER/template-csf/stories/0-Welcome.stories.js rename to lib/cli/src/frameworks/ember/0-Welcome.stories.js diff --git a/lib/cli/src/generators/EMBER/template-csf/stories/1-Button.stories.js b/lib/cli/src/frameworks/ember/1-Button.stories.js similarity index 100% rename from lib/cli/src/generators/EMBER/template-csf/stories/1-Button.stories.js rename to lib/cli/src/frameworks/ember/1-Button.stories.js diff --git a/lib/cli/src/generators/HTML/template-csf/stories/0-Welcome.stories.js b/lib/cli/src/frameworks/html/0-Welcome.stories.js similarity index 100% rename from lib/cli/src/generators/HTML/template-csf/stories/0-Welcome.stories.js rename to lib/cli/src/frameworks/html/0-Welcome.stories.js diff --git a/lib/cli/src/generators/HTML/template-csf/stories/1-Button.stories.js b/lib/cli/src/frameworks/html/1-Button.stories.js similarity index 100% rename from lib/cli/src/generators/HTML/template-csf/stories/1-Button.stories.js rename to lib/cli/src/frameworks/html/1-Button.stories.js diff --git a/lib/cli/src/generators/MARIONETTE/template/stories/index.stories.js b/lib/cli/src/frameworks/marionette/index.stories.js similarity index 83% rename from lib/cli/src/generators/MARIONETTE/template/stories/index.stories.js rename to lib/cli/src/frameworks/marionette/index.stories.js index 32f924b9360..a21a5519472 100644 --- a/lib/cli/src/generators/MARIONETTE/template/stories/index.stories.js +++ b/lib/cli/src/frameworks/marionette/index.stories.js @@ -1,11 +1,11 @@ -import Marionette from 'backbone.marionette'; +import { View } from 'backbone.marionette'; import { storiesOf } from '@storybook/marionette'; storiesOf('Demo', module).add( 'button', () => - new Marionette.View({ + new View({ template: () => '', ui: { button: '#my_button', diff --git a/lib/cli/src/generators/MARKO/template-csf/stories/index.stories.js b/lib/cli/src/frameworks/marko/0-Welcome.stories.js similarity index 68% rename from lib/cli/src/generators/MARKO/template-csf/stories/index.stories.js rename to lib/cli/src/frameworks/marko/0-Welcome.stories.js index 41fcb8b4fc1..a0cba3b6d1b 100644 --- a/lib/cli/src/generators/MARKO/template-csf/stories/index.stories.js +++ b/lib/cli/src/frameworks/marko/0-Welcome.stories.js @@ -1,4 +1,4 @@ -import Welcome from './components/welcome/index.marko'; +import Welcome from './welcome.marko'; export default { title: 'Welcome', diff --git a/lib/cli/src/frameworks/marko/welcome.marko b/lib/cli/src/frameworks/marko/welcome.marko new file mode 100644 index 00000000000..828d359bcc4 --- /dev/null +++ b/lib/cli/src/frameworks/marko/welcome.marko @@ -0,0 +1,37 @@ + +class { + onCreate() {} +} + +style { + #app { + font-family: 'Avenir', Helvetica, Arial, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-align: center; + color: #2c3e50; + margin-top: 60px; + } + + h1, h2 { + font-weight: normal; + } + + ul { + list-style-type: none; + padding: 0; + } + + li { + display: inline-block; + margin: 0 10px; + } + + a { + color: #42b983; + } +} + + +

Welcome to storybook

+ diff --git a/lib/cli/src/generators/MITHRIL/template-csf/stories/0-Welcome.stories.js b/lib/cli/src/frameworks/mithril/0-Welcome.stories.js similarity index 100% rename from lib/cli/src/generators/MITHRIL/template-csf/stories/0-Welcome.stories.js rename to lib/cli/src/frameworks/mithril/0-Welcome.stories.js diff --git a/lib/cli/src/generators/MITHRIL/template-csf/stories/1-Button.stories.js b/lib/cli/src/frameworks/mithril/1-Button.stories.js similarity index 100% rename from lib/cli/src/generators/MITHRIL/template-csf/stories/1-Button.stories.js rename to lib/cli/src/frameworks/mithril/1-Button.stories.js diff --git a/lib/cli/src/generators/MITHRIL/template-csf/stories/Button.js b/lib/cli/src/frameworks/mithril/Button.js similarity index 100% rename from lib/cli/src/generators/MITHRIL/template-csf/stories/Button.js rename to lib/cli/src/frameworks/mithril/Button.js diff --git a/lib/cli/src/generators/MITHRIL/template-csf/stories/Welcome.js b/lib/cli/src/frameworks/mithril/Welcome.js similarity index 100% rename from lib/cli/src/generators/MITHRIL/template-csf/stories/Welcome.js rename to lib/cli/src/frameworks/mithril/Welcome.js diff --git a/lib/cli/src/generators/PREACT/template-csf/stories/0-Welcome.stories.js b/lib/cli/src/frameworks/preact/0-Welcome.stories.js similarity index 100% rename from lib/cli/src/generators/PREACT/template-csf/stories/0-Welcome.stories.js rename to lib/cli/src/frameworks/preact/0-Welcome.stories.js diff --git a/lib/cli/src/generators/PREACT/template-csf/stories/1-Button.stories.js b/lib/cli/src/frameworks/preact/1-Button.stories.js similarity index 100% rename from lib/cli/src/generators/PREACT/template-csf/stories/1-Button.stories.js rename to lib/cli/src/frameworks/preact/1-Button.stories.js diff --git a/lib/cli/src/generators/PREACT/template-csf/stories/Button.js b/lib/cli/src/frameworks/preact/Button.js similarity index 74% rename from lib/cli/src/generators/PREACT/template-csf/stories/Button.js rename to lib/cli/src/frameworks/preact/Button.js index 2a3546d48c5..698f9d88193 100644 --- a/lib/cli/src/generators/PREACT/template-csf/stories/Button.js +++ b/lib/cli/src/frameworks/preact/Button.js @@ -1,5 +1,5 @@ /** @jsx h */ -/* eslint-disable react/no-unknown-property, react/prop-types */ +/* eslint-disable react/no-unknown-property */ import { h } from 'preact'; const Button = ({ children, ...props }) => ( diff --git a/lib/cli/src/generators/PREACT/template-csf/stories/Welcome.js b/lib/cli/src/frameworks/preact/Welcome.js similarity index 94% rename from lib/cli/src/generators/PREACT/template-csf/stories/Welcome.js rename to lib/cli/src/frameworks/preact/Welcome.js index b4ce7052f26..7a47695cf12 100644 --- a/lib/cli/src/generators/PREACT/template-csf/stories/Welcome.js +++ b/lib/cli/src/frameworks/preact/Welcome.js @@ -13,7 +13,6 @@ const Main = (props) => ( /> ); -// eslint-disable-next-line react/prop-types const Title = ({ children, ...props }) =>

{children}

; const Note = (props) => ( @@ -40,7 +39,6 @@ const InlineCode = (props) => ( /> ); -// eslint-disable-next-line react/prop-types const Link = ({ children, href, ...props }) => ( ( ); -// eslint-disable-next-line react/prop-types const NavButton = ({ children, ...props }) => ( ); -/* eslint-disable-next-line react/prop-types */ const Welcome = ({ showApp }) => (
Welcome to storybook diff --git a/lib/cli/src/generators/RAX/template-csf/stories/0-Welcome.stories.js b/lib/cli/src/frameworks/rax/0-Welcome.stories.js similarity index 100% rename from lib/cli/src/generators/RAX/template-csf/stories/0-Welcome.stories.js rename to lib/cli/src/frameworks/rax/0-Welcome.stories.js diff --git a/lib/cli/src/generators/RAX/template-csf/stories/1-Button.stories.js b/lib/cli/src/frameworks/rax/1-Button.stories.js similarity index 100% rename from lib/cli/src/generators/RAX/template-csf/stories/1-Button.stories.js rename to lib/cli/src/frameworks/rax/1-Button.stories.js diff --git a/lib/cli/src/generators/RAX/template-csf/stories/Welcome.js b/lib/cli/src/frameworks/rax/Welcome.js similarity index 97% rename from lib/cli/src/generators/RAX/template-csf/stories/Welcome.js rename to lib/cli/src/frameworks/rax/Welcome.js index 340844748cd..6995d7de594 100644 --- a/lib/cli/src/generators/RAX/template-csf/stories/Welcome.js +++ b/lib/cli/src/frameworks/rax/Welcome.js @@ -1,4 +1,3 @@ -/* eslint-disable react/prop-types, jsx-a11y/anchor-is-valid */ import { createElement } from 'rax'; import View from 'rax-view'; import Text from 'rax-text'; diff --git a/lib/cli/src/generators/REACT/template-csf/stories/0-Welcome.stories.js b/lib/cli/src/frameworks/react/js/0-Welcome.stories.js similarity index 83% rename from lib/cli/src/generators/REACT/template-csf/stories/0-Welcome.stories.js rename to lib/cli/src/frameworks/react/js/0-Welcome.stories.js index 9920a416e1f..4c2d95bdb22 100644 --- a/lib/cli/src/generators/REACT/template-csf/stories/0-Welcome.stories.js +++ b/lib/cli/src/frameworks/react/js/0-Welcome.stories.js @@ -1,6 +1,6 @@ import React from 'react'; import { linkTo } from '@storybook/addon-links'; -import { Welcome } from '@storybook/react/demo'; +import { Welcome } from './Welcome'; export default { title: 'Welcome', diff --git a/lib/cli/src/generators/REACT_SCRIPTS/template-csf/src/stories/1-Button.stories.js b/lib/cli/src/frameworks/react/js/1-Button.stories.js similarity index 95% rename from lib/cli/src/generators/REACT_SCRIPTS/template-csf/src/stories/1-Button.stories.js rename to lib/cli/src/frameworks/react/js/1-Button.stories.js index fdbd42fe76f..68a91009701 100644 --- a/lib/cli/src/generators/REACT_SCRIPTS/template-csf/src/stories/1-Button.stories.js +++ b/lib/cli/src/frameworks/react/js/1-Button.stories.js @@ -1,7 +1,7 @@ import React from 'react'; import { action } from '@storybook/addon-actions'; import { linkTo } from '@storybook/addon-links'; -import { Button } from '@storybook/react/demo'; +import { Button } from './Button'; export default { title: 'Button', diff --git a/lib/cli/src/frameworks/react/js/Button.jsx b/lib/cli/src/frameworks/react/js/Button.jsx new file mode 100644 index 00000000000..0b9a6baeb6a --- /dev/null +++ b/lib/cli/src/frameworks/react/js/Button.jsx @@ -0,0 +1,17 @@ +import React from 'react'; + +const styles = { + border: '1px solid #eee', + borderRadius: 3, + backgroundColor: '#FFFFFF', + cursor: 'pointer', + fontSize: 15, + padding: '3px 10px', + margin: 10, +}; + +export const Button = ({ children, onClick }) => ( + +); diff --git a/lib/cli/src/frameworks/react/js/Welcome.jsx b/lib/cli/src/frameworks/react/js/Welcome.jsx new file mode 100644 index 00000000000..45d25f6ebaf --- /dev/null +++ b/lib/cli/src/frameworks/react/js/Welcome.jsx @@ -0,0 +1,126 @@ +import React from 'react'; + +const Main = (props) => ( +
+); + +const Title = ({ children, ...props }) =>

{children}

; + +const Note = (props) => ( +

+); + +const InlineCode = (props) => ( + +); + +const Link = ({ children, href, target, rel, ...props }) => ( + + {children} + +); + +const NavButton = ({ children, onClick, ...props }) => ( + +); + +export const Welcome = ({ showApp }) => ( +

+ Welcome to storybook +

This is a UI component dev environment for your app.

+

+ We've added some basic stories inside the src/stories directory. +
A story is a single state of one or more UI components. You can have as many stories as + you want. +
+ (Basically a story is like a visual test case.) +

+

+ See these sample stories for a component called  + Button. +

+

+ Just like that, you can add your own components as stories. +
+ You can also edit those components and see changes right away. +
+ (Try editing the Button stories located at  + src/stories/1-Button.stories.js + .) +

+

+ Usually we create stories with smaller UI components in the app. +
+ Have a look at the  + + Writing Stories + +  section in our documentation. +

+ + NOTE: +
+ Have a look at the .storybook/webpack.config.js to add webpack + loaders and plugins you are using in this project. +
+
+); diff --git a/lib/cli/src/generators/REACT_SCRIPTS/template-csf-ts/src/stories/0-Welcome.stories.tsx b/lib/cli/src/frameworks/react/ts/0-Welcome.stories.tsx similarity index 83% rename from lib/cli/src/generators/REACT_SCRIPTS/template-csf-ts/src/stories/0-Welcome.stories.tsx rename to lib/cli/src/frameworks/react/ts/0-Welcome.stories.tsx index 9920a416e1f..4c2d95bdb22 100644 --- a/lib/cli/src/generators/REACT_SCRIPTS/template-csf-ts/src/stories/0-Welcome.stories.tsx +++ b/lib/cli/src/frameworks/react/ts/0-Welcome.stories.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { linkTo } from '@storybook/addon-links'; -import { Welcome } from '@storybook/react/demo'; +import { Welcome } from './Welcome'; export default { title: 'Welcome', diff --git a/lib/cli/src/generators/REACT/template-csf-ts/src/stories/1-Button.stories.tsx b/lib/cli/src/frameworks/react/ts/1-Button.stories.tsx similarity index 95% rename from lib/cli/src/generators/REACT/template-csf-ts/src/stories/1-Button.stories.tsx rename to lib/cli/src/frameworks/react/ts/1-Button.stories.tsx index fdbd42fe76f..68a91009701 100644 --- a/lib/cli/src/generators/REACT/template-csf-ts/src/stories/1-Button.stories.tsx +++ b/lib/cli/src/frameworks/react/ts/1-Button.stories.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { action } from '@storybook/addon-actions'; import { linkTo } from '@storybook/addon-links'; -import { Button } from '@storybook/react/demo'; +import { Button } from './Button'; export default { title: 'Button', diff --git a/lib/cli/src/frameworks/react/ts/Button.tsx b/lib/cli/src/frameworks/react/ts/Button.tsx new file mode 100644 index 00000000000..42b1313f8bf --- /dev/null +++ b/lib/cli/src/frameworks/react/ts/Button.tsx @@ -0,0 +1,20 @@ +import React, { FunctionComponent, HTMLAttributes } from 'react'; + +const styles = { + border: '1px solid #eee', + borderRadius: 3, + backgroundColor: '#FFFFFF', + cursor: 'pointer', + fontSize: 15, + padding: '3px 10px', + margin: 10, +}; + +export type ButtonProps = HTMLAttributes; +export const Button: FunctionComponent = ({ children, onClick }: ButtonProps) => ( + +); + +export default Button; diff --git a/lib/cli/src/frameworks/react/ts/Welcome.tsx b/lib/cli/src/frameworks/react/ts/Welcome.tsx new file mode 100644 index 00000000000..3d0885f6bbd --- /dev/null +++ b/lib/cli/src/frameworks/react/ts/Welcome.tsx @@ -0,0 +1,159 @@ +import React, { + AnchorHTMLAttributes, + ButtonHTMLAttributes, + DetailedHTMLProps, + FunctionComponent, + HTMLAttributes, +} from 'react'; + +type MainProps = Omit, HTMLElement>, 'style'>; +const Main: FunctionComponent = (props) => ( +
+); + +type TitleProps = DetailedHTMLProps, HTMLHeadingElement>; +const Title: FunctionComponent = ({ children, ...props }) => ( +

{children}

+); + +type NoteProps = Omit< + DetailedHTMLProps, HTMLParagraphElement>, + 'style' +>; +const Note: FunctionComponent = (props) => ( +

+); + +type InlineCodeProps = Omit, HTMLElement>, 'style'>; +const InlineCode: FunctionComponent = (props) => ( + +); + +type LinkProps = Omit< + DetailedHTMLProps, HTMLAnchorElement>, + 'style' +> & { + href: string; + target: string; + rel: string; +}; +const Link: FunctionComponent = ({ children, href, target, rel, ...props }) => ( + + {children} + +); + +type NavButtonProps = Omit< + DetailedHTMLProps, HTMLButtonElement>, + 'style' | 'type' +> & {}; +const NavButton: FunctionComponent = ({ children, onClick, ...props }) => ( + +); + +export interface WelcomeProps { + showApp: () => void; +} +export const Welcome: FunctionComponent = ({ showApp }: WelcomeProps) => ( +

+ Welcome to storybook +

This is a UI component dev environment for your app.

+

+ We've added some basic stories inside the src/stories directory. +
A story is a single state of one or more UI components. You can have as many stories as + you want. +
+ (Basically a story is like a visual test case.) +

+

+ See these sample stories for a component called  + Button. +

+

+ Just like that, you can add your own components as stories. +
+ You can also edit those components and see changes right away. +
+ (Try editing the Button stories located at  + src/stories/1-Button.stories.js + .) +

+

+ Usually we create stories with smaller UI components in the app. +
+ Have a look at the  + + Writing Stories + +  section in our documentation. +

+ + NOTE: +
+ Have a look at the .storybook/webpack.config.js to add webpack + loaders and plugins you are using in this project. +
+
+); +Welcome.displayName = 'Welcome'; + +export { Welcome as default }; diff --git a/lib/cli/src/generators/RIOT/template-csf/stories/0-Welcome.stories.js b/lib/cli/src/frameworks/riot/0-Welcome.stories.js similarity index 100% rename from lib/cli/src/generators/RIOT/template-csf/stories/0-Welcome.stories.js rename to lib/cli/src/frameworks/riot/0-Welcome.stories.js diff --git a/lib/cli/src/generators/RIOT/template-csf/stories/1-Button.stories.js b/lib/cli/src/frameworks/riot/1-Button.stories.js similarity index 100% rename from lib/cli/src/generators/RIOT/template-csf/stories/1-Button.stories.js rename to lib/cli/src/frameworks/riot/1-Button.stories.js diff --git a/lib/cli/src/generators/RIOT/template-csf/stories/MyButton.tag b/lib/cli/src/frameworks/riot/MyButton.tag similarity index 100% rename from lib/cli/src/generators/RIOT/template-csf/stories/MyButton.tag rename to lib/cli/src/frameworks/riot/MyButton.tag diff --git a/lib/cli/src/generators/RIOT/template-csf/stories/Welcome.tag b/lib/cli/src/frameworks/riot/Welcome.tag similarity index 100% rename from lib/cli/src/generators/RIOT/template-csf/stories/Welcome.tag rename to lib/cli/src/frameworks/riot/Welcome.tag diff --git a/lib/cli/src/generators/SVELTE/template-csf/stories/0-welcome.stories.js b/lib/cli/src/frameworks/svelte/0-welcome.stories.js similarity index 100% rename from lib/cli/src/generators/SVELTE/template-csf/stories/0-welcome.stories.js rename to lib/cli/src/frameworks/svelte/0-welcome.stories.js diff --git a/lib/cli/src/generators/SVELTE/template-csf/stories/1-button.stories.js b/lib/cli/src/frameworks/svelte/1-button.stories.js similarity index 100% rename from lib/cli/src/generators/SVELTE/template-csf/stories/1-button.stories.js rename to lib/cli/src/frameworks/svelte/1-button.stories.js diff --git a/lib/cli/src/generators/SVELTE/template-csf/stories/button.svelte b/lib/cli/src/frameworks/svelte/button.svelte similarity index 100% rename from lib/cli/src/generators/SVELTE/template-csf/stories/button.svelte rename to lib/cli/src/frameworks/svelte/button.svelte diff --git a/lib/cli/src/generators/SVELTE/template-csf/stories/welcome.svelte b/lib/cli/src/frameworks/svelte/welcome.svelte similarity index 100% rename from lib/cli/src/generators/SVELTE/template-csf/stories/welcome.svelte rename to lib/cli/src/frameworks/svelte/welcome.svelte diff --git a/lib/cli/src/generators/SFC_VUE/template-csf/src/stories/0-Welcome.stories.js b/lib/cli/src/frameworks/vue/0-Welcome.stories.js similarity index 100% rename from lib/cli/src/generators/SFC_VUE/template-csf/src/stories/0-Welcome.stories.js rename to lib/cli/src/frameworks/vue/0-Welcome.stories.js diff --git a/lib/cli/src/generators/VUE/template-csf/stories/1-Button.stories.js b/lib/cli/src/frameworks/vue/1-Button.stories.js similarity index 96% rename from lib/cli/src/generators/VUE/template-csf/stories/1-Button.stories.js rename to lib/cli/src/frameworks/vue/1-Button.stories.js index 790039811cc..f2f44d6351b 100644 --- a/lib/cli/src/generators/VUE/template-csf/stories/1-Button.stories.js +++ b/lib/cli/src/frameworks/vue/1-Button.stories.js @@ -1,7 +1,7 @@ import { action } from '@storybook/addon-actions'; import { linkTo } from '@storybook/addon-links'; -import MyButton from './MyButton'; +import MyButton from './Button.vue'; export default { title: 'Button', diff --git a/lib/cli/src/generators/SFC_VUE/template-csf/src/stories/MyButton.vue b/lib/cli/src/frameworks/vue/Button.vue similarity index 100% rename from lib/cli/src/generators/SFC_VUE/template-csf/src/stories/MyButton.vue rename to lib/cli/src/frameworks/vue/Button.vue diff --git a/lib/cli/src/generators/SFC_VUE/template-csf/src/stories/Welcome.vue b/lib/cli/src/frameworks/vue/Welcome.vue similarity index 100% rename from lib/cli/src/generators/SFC_VUE/template-csf/src/stories/Welcome.vue rename to lib/cli/src/frameworks/vue/Welcome.vue diff --git a/lib/cli/src/generators/WEB-COMPONENTS/template/stories/0-Welcome.stories.js b/lib/cli/src/frameworks/web-components/0-Welcome.stories.js similarity index 100% rename from lib/cli/src/generators/WEB-COMPONENTS/template/stories/0-Welcome.stories.js rename to lib/cli/src/frameworks/web-components/0-Welcome.stories.js diff --git a/lib/cli/src/generators/WEB-COMPONENTS/template/stories/1-Button.stories.js b/lib/cli/src/frameworks/web-components/1-Button.stories.js similarity index 100% rename from lib/cli/src/generators/WEB-COMPONENTS/template/stories/1-Button.stories.js rename to lib/cli/src/frameworks/web-components/1-Button.stories.js diff --git a/lib/cli/src/generators/ANGULAR/index.ts b/lib/cli/src/generators/ANGULAR/index.ts index 9ab5196a019..ddfdc4ba36e 100644 --- a/lib/cli/src/generators/ANGULAR/index.ts +++ b/lib/cli/src/generators/ANGULAR/index.ts @@ -5,45 +5,12 @@ import { getAngularAppTsConfigJson, getAngularAppTsConfigPath, } from './angular-helpers'; -import { getBabelDependencies, writeFileAsJson, copyTemplate } from '../../helpers'; -import { StoryFormat } from '../../project_types'; -import { NpmOptions } from '../../NpmOptions'; -import { Generator, GeneratorOptions } from '../Generator'; -import { JsPackageManager } from '../../js-package-manager'; - -async function addDependencies( - packageManager: JsPackageManager, - npmOptions: NpmOptions, - { storyFormat }: GeneratorOptions -) { - const packages = [ - '@storybook/angular', - '@storybook/addon-actions', - '@storybook/addon-links', - '@storybook/addons', - ]; - - if (storyFormat === StoryFormat.MDX) { - packages.push('@storybook/addon-docs'); - } - - const versionedPackages = await packageManager.getVersionedPackages(...packages); - - const packageJson = packageManager.retrievePackageJson(); - - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - ...versionedPackages, - ...babelDependencies, - ]); - - packageManager.addStorybookCommandInScripts(); -} +import { writeFileAsJson, copyTemplate } from '../../helpers'; +import { baseGenerator, Generator } from '../generator'; function editAngularAppTsConfig() { const tsConfigJson = getAngularAppTsConfigJson(); - const glob = '**/*.stories.ts'; + const glob = '**/*.stories.*'; if (!tsConfigJson) { return; } @@ -57,16 +24,15 @@ function editAngularAppTsConfig() { writeFileAsJson(getAngularAppTsConfigPath(), tsConfigJson); } -const generator: Generator = async (packageManager, npmOptions, { storyFormat }) => { +const generator: Generator = async (packageManager, npmOptions, options) => { if (!isDefaultProjectSet()) { throw new Error( 'Could not find a default project in your Angular workspace.\nSet a defaultProject in your angular.json and re-run the installation.' ); } + baseGenerator(packageManager, npmOptions, options, 'angular'); + copyTemplate(__dirname, options.storyFormat); - copyTemplate(__dirname, storyFormat); - - await addDependencies(packageManager, npmOptions, { storyFormat }); editAngularAppTsConfig(); editStorybookTsConfig(path.resolve('./.storybook/tsconfig.json')); }; diff --git a/lib/cli/src/generators/ANGULAR/template-csf/.storybook/main.js b/lib/cli/src/generators/ANGULAR/template-csf/.storybook/main.js deleted file mode 100644 index 16aa97cdc16..00000000000 --- a/lib/cli/src/generators/ANGULAR/template-csf/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../src/**/*.stories.ts'], - addons: ['@storybook/addon-actions', '@storybook/addon-links'], -}; diff --git a/lib/cli/src/generators/ANGULAR/template-mdx/.storybook/main.js b/lib/cli/src/generators/ANGULAR/template-mdx/.storybook/main.js deleted file mode 100644 index 43bbb3968c4..00000000000 --- a/lib/cli/src/generators/ANGULAR/template-mdx/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../src/**/*.stories.@(ts|mdx)'], - addons: ['@storybook/addon-docs', '@storybook/addon-actions', '@storybook/addon-links'], -}; diff --git a/lib/cli/src/generators/ANGULAR/template-mdx/src/stories/0-Welcome.stories.mdx b/lib/cli/src/generators/ANGULAR/template-mdx/src/stories/0-Welcome.stories.mdx index 5fc361cd9b6..1abbfd8a65e 100644 --- a/lib/cli/src/generators/ANGULAR/template-mdx/src/stories/0-Welcome.stories.mdx +++ b/lib/cli/src/generators/ANGULAR/template-mdx/src/stories/0-Welcome.stories.mdx @@ -1,5 +1,5 @@ import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'; -import { Welcome } from '@storybook/angular/demo'; +import Welcome from './welcome.component'; diff --git a/lib/cli/src/generators/ANGULAR/template-mdx/src/stories/1-Button.stories.mdx b/lib/cli/src/generators/ANGULAR/template-mdx/src/stories/1-Button.stories.mdx index 9aabc6f50ed..13c38a6621f 100644 --- a/lib/cli/src/generators/ANGULAR/template-mdx/src/stories/1-Button.stories.mdx +++ b/lib/cli/src/generators/ANGULAR/template-mdx/src/stories/1-Button.stories.mdx @@ -2,7 +2,7 @@ import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'; import { action } from '@storybook/addon-actions'; import { linkTo } from '@storybook/addon-links'; -import { Button } from '@storybook/angular/demo'; +import Button from './button.component'; diff --git a/lib/cli/src/generators/AURELIA/index.ts b/lib/cli/src/generators/AURELIA/index.ts index 04ec62b89ed..8367b1667ec 100644 --- a/lib/cli/src/generators/AURELIA/index.ts +++ b/lib/cli/src/generators/AURELIA/index.ts @@ -1,6 +1,5 @@ -import { getBabelDependencies, writeFileAsJson, copyTemplate, readFileAsJson } from '../../helpers'; -import { Generator } from '../Generator'; -import { StoryFormat } from '../../project_types'; +import { writeFileAsJson, readFileAsJson, copyTemplate } from '../../helpers'; +import { baseGenerator, Generator } from '../generator'; function addStorybookExcludeGlobToTsConfig() { const tsConfigJson = readFileAsJson('tsconfig.json', true); @@ -17,39 +16,13 @@ function addStorybookExcludeGlobToTsConfig() { tsConfigJson.exclude = [...exclude, glob]; writeFileAsJson('tsconfig.json', tsConfigJson); } -const generator: Generator = async ( - packageManager, - npmOptions, - { storyFormat = StoryFormat.CSF } -) => { - copyTemplate(__dirname, storyFormat); - const packages = [ - '@storybook/aurelia', - '@storybook/addon-actions', - '@storybook/addon-links', - '@storybook/addons', - '@storybook/addon-storysource', - '@storybook/addon-knobs', - '@storybook/addon-options', - '@storybook/addon-a11y', - '@storybook/addon-backgrounds', - 'aurelia', - ]; - if (storyFormat === 'mdx') { - packages.push('@storybook/addon-docs'); - } - - const versionedPackages = await packageManager.getVersionedPackages(...packages); - const packageJson = packageManager.retrievePackageJson(); +const generator: Generator = async (packageManager, npmOptions, options) => { addStorybookExcludeGlobToTsConfig(); - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - ...versionedPackages, - ...babelDependencies, - ]); - - packageManager.addStorybookCommandInScripts(); + baseGenerator(packageManager, npmOptions, options, 'aurelia', { + extraPackages: ['aurelia'], + }); + copyTemplate(__dirname, options.storyFormat); }; export default generator; diff --git a/lib/cli/src/generators/AURELIA/template-csf/.storybook/main.js b/lib/cli/src/generators/AURELIA/template-csf/.storybook/main.js deleted file mode 100644 index 16aa97cdc16..00000000000 --- a/lib/cli/src/generators/AURELIA/template-csf/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../src/**/*.stories.ts'], - addons: ['@storybook/addon-actions', '@storybook/addon-links'], -}; diff --git a/lib/cli/src/generators/AURELIA/template-mdx/.storybook/main.js b/lib/cli/src/generators/AURELIA/template-mdx/.storybook/main.js deleted file mode 100644 index 43bbb3968c4..00000000000 --- a/lib/cli/src/generators/AURELIA/template-mdx/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../src/**/*.stories.@(ts|mdx)'], - addons: ['@storybook/addon-docs', '@storybook/addon-actions', '@storybook/addon-links'], -}; diff --git a/lib/cli/src/generators/AURELIA/template-mdx/src/stories/0-Welcome.stories.mdx b/lib/cli/src/generators/AURELIA/template-mdx/src/stories/0-Welcome.stories.mdx index 17ad75634de..531a441afb6 100644 --- a/lib/cli/src/generators/AURELIA/template-mdx/src/stories/0-Welcome.stories.mdx +++ b/lib/cli/src/generators/AURELIA/template-mdx/src/stories/0-Welcome.stories.mdx @@ -1,5 +1,5 @@ import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'; -import { Welcome } from '@storybook/aurelia/demo'; +import Welcome from './welcome'; diff --git a/lib/cli/src/generators/AURELIA/template-mdx/src/stories/1-Button.stories.mdx b/lib/cli/src/generators/AURELIA/template-mdx/src/stories/1-Button.stories.mdx index fe4f4783439..a488b7b8fd7 100644 --- a/lib/cli/src/generators/AURELIA/template-mdx/src/stories/1-Button.stories.mdx +++ b/lib/cli/src/generators/AURELIA/template-mdx/src/stories/1-Button.stories.mdx @@ -2,7 +2,7 @@ import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'; import { action } from '@storybook/addon-actions'; import { linkTo } from '@storybook/addon-links'; -import { Button } from '@storybook/aurelia/demo'; +import Button from './button'; diff --git a/lib/cli/src/generators/EMBER/index.ts b/lib/cli/src/generators/EMBER/index.ts index 36fb1c1ef53..d1d88751a85 100644 --- a/lib/cli/src/generators/EMBER/index.ts +++ b/lib/cli/src/generators/EMBER/index.ts @@ -1,41 +1,15 @@ -import { getBabelDependencies, copyTemplate } from '../../helpers'; -import { Generator } from '../Generator'; - -const generator: Generator = async (packageManager, npmOptions, { storyFormat }) => { - const [ - storybookVersion, - babelPluginEmberModulePolyfillVersion, - babelPluginHtmlBarsInlinePrecompileVersion, - linksVersion, - actionsVersion, - addonsVersion, - ] = await packageManager.getVersions( - '@storybook/ember', - // babel-plugin-ember-modules-api-polyfill is a peerDep of @storybook/ember - 'babel-plugin-ember-modules-api-polyfill', - // babel-plugin-htmlbars-inline-precompile is a peerDep of @storybook/ember - 'babel-plugin-htmlbars-inline-precompile', - '@storybook/addon-links', - '@storybook/addon-actions', - '@storybook/addons' - ); - - copyTemplate(__dirname, storyFormat); - - const packageJson = packageManager.retrievePackageJson(); - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - `@storybook/ember@${storybookVersion}`, - `@storybook/addon-actions@${actionsVersion}`, - `@storybook/addon-links@${linksVersion}`, - `@storybook/addons@${addonsVersion}`, - `babel-plugin-ember-modules-api-polyfill@${babelPluginEmberModulePolyfillVersion}`, - `babel-plugin-htmlbars-inline-precompile@${babelPluginHtmlBarsInlinePrecompileVersion}`, - ...babelDependencies, - ]); - - packageManager.addStorybookCommandInScripts(); +import { baseGenerator, Generator } from '../generator'; + +const generator: Generator = async (packageManager, npmOptions, options) => { + baseGenerator(packageManager, npmOptions, options, 'ember', { + extraPackages: [ + // babel-plugin-ember-modules-api-polyfill is a peerDep of @storybook/ember + 'babel-plugin-ember-modules-api-polyfill', + // babel-plugin-htmlbars-inline-precompile is a peerDep of @storybook/ember + 'babel-plugin-htmlbars-inline-precompile', + ], + staticDir: 'dist', + }); }; export default generator; diff --git a/lib/cli/src/generators/EMBER/template-csf/.storybook/main.js b/lib/cli/src/generators/EMBER/template-csf/.storybook/main.js deleted file mode 100644 index 3036098563c..00000000000 --- a/lib/cli/src/generators/EMBER/template-csf/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../stories/**/*.stories.js'], - addons: ['@storybook/addon-actions', '@storybook/addon-links'], -}; diff --git a/lib/cli/src/generators/Generator.ts b/lib/cli/src/generators/Generator.ts deleted file mode 100644 index 7d081f55c9a..00000000000 --- a/lib/cli/src/generators/Generator.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { NpmOptions } from '../NpmOptions'; -import { StoryFormat } from '../project_types'; -import { JsPackageManager } from '../js-package-manager'; - -export type GeneratorOptions = { - storyFormat: StoryFormat; -}; - -export type Generator = ( - packageManager: JsPackageManager, - npmOptions: NpmOptions, - options: GeneratorOptions -) => Promise; diff --git a/lib/cli/src/generators/HTML/index.ts b/lib/cli/src/generators/HTML/index.ts index eb96ae0ff49..76b975ff825 100755 --- a/lib/cli/src/generators/HTML/index.ts +++ b/lib/cli/src/generators/HTML/index.ts @@ -1,25 +1,12 @@ -import { getBabelDependencies, copyTemplate } from '../../helpers'; +import { baseGenerator, Generator } from '../generator'; import { StoryFormat } from '../../project_types'; -import { Generator } from '../Generator'; +import { copyTemplate } from '../../helpers'; -const generator: Generator = async (packageManager, npmOptions, { storyFormat }) => { - const packages = ['@storybook/html', '@storybook/addon-actions', '@storybook/addon-links']; - if (storyFormat === StoryFormat.MDX) { - packages.push('@storybook/addon-docs'); +const generator: Generator = async (packageManager, npmOptions, options) => { + baseGenerator(packageManager, npmOptions, options, 'html'); + if (options.storyFormat === StoryFormat.MDX) { + copyTemplate(__dirname, StoryFormat.MDX); } - - const versionedPackages = await packageManager.getVersionedPackages(...packages); - - copyTemplate(__dirname, storyFormat); - - const packageJson = packageManager.retrievePackageJson(); - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - ...versionedPackages, - ...babelDependencies, - ]); - - packageManager.addStorybookCommandInScripts(); }; export default generator; diff --git a/lib/cli/src/generators/HTML/template-csf/.storybook/main.js b/lib/cli/src/generators/HTML/template-csf/.storybook/main.js deleted file mode 100644 index 3036098563c..00000000000 --- a/lib/cli/src/generators/HTML/template-csf/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../stories/**/*.stories.js'], - addons: ['@storybook/addon-actions', '@storybook/addon-links'], -}; diff --git a/lib/cli/src/generators/HTML/template-mdx/.storybook/main.js b/lib/cli/src/generators/HTML/template-mdx/.storybook/main.js deleted file mode 100644 index c3211c95188..00000000000 --- a/lib/cli/src/generators/HTML/template-mdx/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../stories/**/*.stories.@(js|mdx)'], - addons: ['@storybook/addon-docs'], -}; diff --git a/lib/cli/src/generators/MARIONETTE/index.ts b/lib/cli/src/generators/MARIONETTE/index.ts index c29c891b00e..74496591d55 100644 --- a/lib/cli/src/generators/MARIONETTE/index.ts +++ b/lib/cli/src/generators/MARIONETTE/index.ts @@ -1,22 +1,7 @@ -import fse from 'fs-extra'; -import path from 'path'; -import { getBabelDependencies } from '../../helpers'; -import { Generator } from '../Generator'; +import { baseGenerator, Generator } from '../generator'; -const generator: Generator = async (packageManager, npmOptions) => { - const storybookVersion = await packageManager.getVersion('@storybook/marionette'); - fse.copySync(path.resolve(__dirname, 'template/'), '.', { overwrite: true }); - - const packageJson = packageManager.retrievePackageJson(); - - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - `@storybook/marionette@${storybookVersion}`, - ...babelDependencies, - ]); - - packageManager.addStorybookCommandInScripts(); +const generator: Generator = async (packageManager, npmOptions, options) => { + await baseGenerator(packageManager, npmOptions, options, 'marionette'); }; export default generator; diff --git a/lib/cli/src/generators/MARIONETTE/template/.storybook/main.js b/lib/cli/src/generators/MARIONETTE/template/.storybook/main.js deleted file mode 100644 index a0f65ec500a..00000000000 --- a/lib/cli/src/generators/MARIONETTE/template/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: '../stories/**/*.stories.js', - addons: ['@storybook/addon-actions', '@storybook/addon-knobs'], -}; diff --git a/lib/cli/src/generators/MARKO/index.ts b/lib/cli/src/generators/MARKO/index.ts index f28c62ff86d..01dc5e7bd10 100644 --- a/lib/cli/src/generators/MARKO/index.ts +++ b/lib/cli/src/generators/MARKO/index.ts @@ -1,31 +1,7 @@ -import { getBabelDependencies, copyTemplate } from '../../helpers'; -import { Generator } from '../Generator'; +import { baseGenerator, Generator } from '../generator'; -const generator: Generator = async (packageManager, npmOptions, { storyFormat }) => { - const [ - storybookVersion, - addonActionVersion, - addonKnobsVersion, - ] = await packageManager.getVersions( - '@storybook/marko', - '@storybook/addon-actions', - '@storybook/addon-knobs' - ); - - copyTemplate(__dirname, storyFormat); - - const packageJson = packageManager.retrievePackageJson(); - - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - `@storybook/marko@${storybookVersion}`, - `@storybook/addon-actions@${addonActionVersion}`, - `@storybook/addon-knobs@${addonKnobsVersion}`, - ...babelDependencies, - ]); - - packageManager.addStorybookCommandInScripts(); +const generator: Generator = async (packageManager, npmOptions, options) => { + await baseGenerator(packageManager, npmOptions, options, 'marko'); }; export default generator; diff --git a/lib/cli/src/generators/MARKO/template-csf/.storybook/main.js b/lib/cli/src/generators/MARKO/template-csf/.storybook/main.js deleted file mode 100644 index c6a06f1fbc3..00000000000 --- a/lib/cli/src/generators/MARKO/template-csf/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../stories/**/*.stories.js'], - addons: ['@storybook/addon-actions', '@storybook/addon-knobs'], -}; diff --git a/lib/cli/src/generators/MARKO/template-csf/stories/components/welcome/index.marko b/lib/cli/src/generators/MARKO/template-csf/stories/components/welcome/index.marko deleted file mode 100644 index 272d7211f2b..00000000000 --- a/lib/cli/src/generators/MARKO/template-csf/stories/components/welcome/index.marko +++ /dev/null @@ -1,46 +0,0 @@ - -class { - onCreate() {} -} - -style { - #app { - font-family: 'Avenir', Helvetica, Arial, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-align: center; - color: #2c3e50; - margin-top: 60px; - } - - .logo { - background-image:url('data:image/png;base64,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'); - background-repeat:no-repeat; - display:inline-block; - width: 365px; - height: 200px; - } - - h1, h2 { - font-weight: normal; - } - - ul { - list-style-type: none; - padding: 0; - } - - li { - display: inline-block; - margin: 0 10px; - } - - a { - color: #42b983; - } -} - - -

Welcome to storybook

- - diff --git a/lib/cli/src/generators/METEOR/index.ts b/lib/cli/src/generators/METEOR/index.ts index 95ae0183490..852f4e29bc0 100644 --- a/lib/cli/src/generators/METEOR/index.ts +++ b/lib/cli/src/generators/METEOR/index.ts @@ -1,43 +1,12 @@ import fs from 'fs'; import JSON5 from 'json5'; -import { getBabelDependencies, copyTemplate } from '../../helpers'; -import { Generator } from '../Generator'; -import { writePackageJson } from '../../js-package-manager'; +import { baseGenerator, Generator } from '../generator'; -const generator: Generator = async (packageManager, npmOptions, { storyFormat }) => { - const [ - storybookVersion, - actionsVersion, - linksVersion, - knobsVersion, - addonsVersion, - reactVersion, - reactDomVersion, - presetEnvVersion, - presetReactVersion, - ] = await packageManager.getVersions( - '@storybook/react', - '@storybook/addon-actions', - '@storybook/addon-links', - '@storybook/addon-knobs', - '@storybook/addons', - 'react', - 'react-dom', - '@babel/preset-env', - '@babel/preset-react' - ); - - copyTemplate(__dirname, storyFormat); - - const packageJson = packageManager.retrievePackageJson(); - - const devDependencies = [ - `@storybook/react@${storybookVersion}`, - `@storybook/addon-actions@${actionsVersion}`, - `@storybook/addon-links@${linksVersion}`, - `@storybook/addon-knobs@${knobsVersion}`, - `@storybook/addons@${addonsVersion}`, - ]; +const generator: Generator = async (packageManager, npmOptions, options) => { + baseGenerator(packageManager, npmOptions, options, 'react', { + extraPackages: ['react', 'react-dom', '@babel/preset-env', '@babel/preset-react'], + staticDir: 'dist', + }); // create or update .babelrc let babelrc = null; @@ -52,39 +21,9 @@ const generator: Generator = async (packageManager, npmOptions, { storyFormat }) '@babel/preset-react', ], }; - - devDependencies.push(`@babel/preset-env@${presetEnvVersion}`); - devDependencies.push(`@babel/preset-react@${presetReactVersion}`); } fs.writeFileSync('.babelrc', JSON.stringify(babelrc, null, 2), 'utf8'); - - writePackageJson(packageJson); - - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - - // add react packages. - const dependencies = []; - if (!packageJson.dependencies.react) { - dependencies.push(`react@${reactVersion}`); - } - if (!packageJson.dependencies['react-dom']) { - dependencies.push(`react-dom@${reactDomVersion}`); - } - - if (dependencies.length > 0) { - packageManager.addDependencies( - { ...npmOptions, packageJson, installAsDevDependencies: false }, - dependencies - ); - } - - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - ...devDependencies, - ...babelDependencies, - ]); - - packageManager.addStorybookCommandInScripts(); }; export default generator; diff --git a/lib/cli/src/generators/METEOR/template-csf/.storybook/main.js b/lib/cli/src/generators/METEOR/template-csf/.storybook/main.js deleted file mode 100644 index c6a06f1fbc3..00000000000 --- a/lib/cli/src/generators/METEOR/template-csf/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../stories/**/*.stories.js'], - addons: ['@storybook/addon-actions', '@storybook/addon-knobs'], -}; diff --git a/lib/cli/src/generators/METEOR/template-csf/stories/0-Welcome.stories.js b/lib/cli/src/generators/METEOR/template-csf/stories/0-Welcome.stories.js deleted file mode 100644 index 9920a416e1f..00000000000 --- a/lib/cli/src/generators/METEOR/template-csf/stories/0-Welcome.stories.js +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import { linkTo } from '@storybook/addon-links'; -import { Welcome } from '@storybook/react/demo'; - -export default { - title: 'Welcome', - component: Welcome, -}; - -export const ToStorybook = () => ; - -ToStorybook.storyName = 'to Storybook'; diff --git a/lib/cli/src/generators/METEOR/template-csf/stories/1-Button.stories.js b/lib/cli/src/generators/METEOR/template-csf/stories/1-Button.stories.js deleted file mode 100644 index 6bcfa214662..00000000000 --- a/lib/cli/src/generators/METEOR/template-csf/stories/1-Button.stories.js +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import { action } from '@storybook/addon-actions'; -import { Button } from '@storybook/react/demo'; - -export default { - title: 'Button', - component: Button, -}; - -export const Text = () => ; - -export const Emoji = () => ( - -); diff --git a/lib/cli/src/generators/MITHRIL/index.ts b/lib/cli/src/generators/MITHRIL/index.ts index 329b521c9d7..46ec36e633d 100644 --- a/lib/cli/src/generators/MITHRIL/index.ts +++ b/lib/cli/src/generators/MITHRIL/index.ts @@ -1,37 +1,7 @@ -import { getBabelDependencies, copyTemplate } from '../../helpers'; -import { Generator } from '../Generator'; +import { baseGenerator, Generator } from '../generator'; -const generator: Generator = async (packageManager, npmOptions, { storyFormat }) => { - const [ - storybookVersion, - actionsVersion, - linksVersion, - knobsVersion, - addonsVersion, - ] = await packageManager.getVersions( - '@storybook/mithril', - '@storybook/addon-actions', - '@storybook/addon-links', - '@storybook/addon-knobs', - '@storybook/addons' - ); - - copyTemplate(__dirname, storyFormat); - - const packageJson = packageManager.retrievePackageJson(); - - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - `@storybook/mithril@${storybookVersion}`, - `@storybook/addon-actions@${actionsVersion}`, - `@storybook/addon-links@${linksVersion}`, - `@storybook/addon-knobs@${knobsVersion}`, - `@storybook/addons@${addonsVersion}`, - ...babelDependencies, - ]); - - packageManager.addStorybookCommandInScripts(); +const generator: Generator = async (packageManager, npmOptions, options) => { + baseGenerator(packageManager, npmOptions, options, 'mithril'); }; export default generator; diff --git a/lib/cli/src/generators/MITHRIL/template-csf/.storybook/main.js b/lib/cli/src/generators/MITHRIL/template-csf/.storybook/main.js deleted file mode 100644 index c6a06f1fbc3..00000000000 --- a/lib/cli/src/generators/MITHRIL/template-csf/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../stories/**/*.stories.js'], - addons: ['@storybook/addon-actions', '@storybook/addon-knobs'], -}; diff --git a/lib/cli/src/generators/PREACT/index.ts b/lib/cli/src/generators/PREACT/index.ts index f6ceceac04d..5c83eb2bfb0 100644 --- a/lib/cli/src/generators/PREACT/index.ts +++ b/lib/cli/src/generators/PREACT/index.ts @@ -1,34 +1,7 @@ -import { getBabelDependencies, copyTemplate } from '../../helpers'; -import { Generator } from '../Generator'; +import { baseGenerator, Generator } from '../generator'; -const generator: Generator = async (packageManager, npmOptions, { storyFormat }) => { - const [ - storybookVersion, - actionsVersion, - linksVersion, - addonsVersion, - ] = await packageManager.getVersions( - '@storybook/preact', - '@storybook/addon-actions', - '@storybook/addon-links', - '@storybook/addons' - ); - - copyTemplate(__dirname, storyFormat); - - const packageJson = packageManager.retrievePackageJson(); - - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - `@storybook/preact@${storybookVersion}`, - `@storybook/addon-actions@${actionsVersion}`, - `@storybook/addon-links@${linksVersion}`, - `@storybook/addons@${addonsVersion}`, - ...babelDependencies, - ]); - - packageManager.addStorybookCommandInScripts(); +const generator: Generator = async (packageManager, npmOptions, options) => { + baseGenerator(packageManager, npmOptions, options, 'preact'); }; export default generator; diff --git a/lib/cli/src/generators/PREACT/template-csf/.storybook/main.js b/lib/cli/src/generators/PREACT/template-csf/.storybook/main.js deleted file mode 100644 index 3036098563c..00000000000 --- a/lib/cli/src/generators/PREACT/template-csf/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../stories/**/*.stories.js'], - addons: ['@storybook/addon-actions', '@storybook/addon-links'], -}; diff --git a/lib/cli/src/generators/RAX/index.ts b/lib/cli/src/generators/RAX/index.ts index ed0b4bdfa3c..fc0ebc038b5 100644 --- a/lib/cli/src/generators/RAX/index.ts +++ b/lib/cli/src/generators/RAX/index.ts @@ -1,24 +1,8 @@ -import { getBabelDependencies, copyTemplate } from '../../helpers'; -import { Generator } from '../Generator'; +import { baseGenerator, Generator } from '../generator'; import { writePackageJson } from '../../js-package-manager'; -const generator: Generator = async (packageManager, npmOptions, { storyFormat }) => { - const [ - storybookVersion, - actionsVersion, - linksVersion, - addonsVersion, - latestRaxVersion, - ] = await packageManager.getVersions( - '@storybook/rax', - '@storybook/addon-actions', - '@storybook/addon-links', - '@storybook/addons', - 'rax' - ); - - copyTemplate(__dirname, storyFormat); - +const generator: Generator = async (packageManager, npmOptions, options) => { + const [latestRaxVersion] = await packageManager.getVersions('rax'); const packageJson = packageManager.retrievePackageJson(); const raxVersion = packageJson.dependencies.rax || latestRaxVersion; @@ -34,17 +18,9 @@ const generator: Generator = async (packageManager, npmOptions, { storyFormat }) writePackageJson(packageJson); - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - `@storybook/rax@${storybookVersion}`, - `@storybook/addon-actions@${actionsVersion}`, - `@storybook/addon-links@${linksVersion}`, - `@storybook/addons@${addonsVersion}`, - ...babelDependencies, - ]); - - packageManager.addStorybookCommandInScripts(); + baseGenerator(packageManager, npmOptions, options, 'rax', { + extraPackages: ['rax'], + }); }; export default generator; diff --git a/lib/cli/src/generators/RAX/template-csf/.storybook/main.js b/lib/cli/src/generators/RAX/template-csf/.storybook/main.js deleted file mode 100644 index 3036098563c..00000000000 --- a/lib/cli/src/generators/RAX/template-csf/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../stories/**/*.stories.js'], - addons: ['@storybook/addon-actions', '@storybook/addon-links'], -}; diff --git a/lib/cli/src/generators/REACT/index.ts b/lib/cli/src/generators/REACT/index.ts index 2a6606bc4d2..06581ac590b 100644 --- a/lib/cli/src/generators/REACT/index.ts +++ b/lib/cli/src/generators/REACT/index.ts @@ -1,32 +1,12 @@ -import { getBabelDependencies, copyTemplate } from '../../helpers'; +import { baseGenerator, Generator } from '../generator'; import { StoryFormat } from '../../project_types'; -import { Generator } from '../Generator'; +import { copyTemplate } from '../../helpers'; -const generator: Generator = async (packageManager, npmOptions, { storyFormat }) => { - const packages = [ - '@storybook/react', - '@storybook/addon-actions', - '@storybook/addon-links', - '@storybook/addons', - ]; - if (storyFormat === StoryFormat.MDX) { - packages.push('@storybook/addon-docs'); +const generator: Generator = async (packageManager, npmOptions, options) => { + await baseGenerator(packageManager, npmOptions, options, 'react'); + if (options.storyFormat === StoryFormat.MDX) { + copyTemplate(__dirname, StoryFormat.MDX); } - - const versionedPackages = await packageManager.getVersionedPackages(...packages); - - copyTemplate(__dirname, storyFormat); - - const packageJson = packageManager.retrievePackageJson(); - - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - ...versionedPackages, - ...babelDependencies, - ]); - - packageManager.addStorybookCommandInScripts(); }; export default generator; diff --git a/lib/cli/src/generators/REACT/template-csf-ts/.storybook/main.js b/lib/cli/src/generators/REACT/template-csf-ts/.storybook/main.js deleted file mode 100644 index 523dca65b67..00000000000 --- a/lib/cli/src/generators/REACT/template-csf-ts/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../src/**/*.stories.@(ts|tsx|js|jsx)'], - addons: ['@storybook/addon-actions', '@storybook/addon-links'], -}; diff --git a/lib/cli/src/generators/REACT/template-csf-ts/src/stories/0-Welcome.stories.tsx b/lib/cli/src/generators/REACT/template-csf-ts/src/stories/0-Welcome.stories.tsx deleted file mode 100644 index c76f45f3b4b..00000000000 --- a/lib/cli/src/generators/REACT/template-csf-ts/src/stories/0-Welcome.stories.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react'; -import { linkTo } from '@storybook/addon-links'; -import { Welcome } from '@storybook/react/demo'; - -export default { - title: 'Welcome', - component: Welcome, -}; - -export const ToStorybook = () => ; - -ToStorybook.story = { - name: 'to Storybook', -}; diff --git a/lib/cli/src/generators/REACT/template-csf/.storybook/main.js b/lib/cli/src/generators/REACT/template-csf/.storybook/main.js deleted file mode 100644 index 64815ba01ea..00000000000 --- a/lib/cli/src/generators/REACT/template-csf/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../stories/**/*.stories.@(ts|tsx|js|jsx)'], - addons: ['@storybook/addon-actions', '@storybook/addon-links'], -}; diff --git a/lib/cli/src/generators/REACT/template-csf/stories/1-Button.stories.js b/lib/cli/src/generators/REACT/template-csf/stories/1-Button.stories.js deleted file mode 100644 index fdbd42fe76f..00000000000 --- a/lib/cli/src/generators/REACT/template-csf/stories/1-Button.stories.js +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import { action } from '@storybook/addon-actions'; -import { linkTo } from '@storybook/addon-links'; -import { Button } from '@storybook/react/demo'; - -export default { - title: 'Button', - component: Button, -}; - -export const Text = () => ; - -export const Emoji = () => ( - -); - -Emoji.parameters = { notes: 'My notes on a button with emojis' }; - -export const TextWithAction = () => ( - -); - -TextWithAction.storyName = 'With an action'; -TextWithAction.parameters = { notes: 'My notes on a button with emojis' }; - -export const ButtonWithLinkToAnotherStory = () => ( - -); - -ButtonWithLinkToAnotherStory.storyName = 'button with link to another story'; diff --git a/lib/cli/src/generators/REACT/template-mdx/.storybook/main.js b/lib/cli/src/generators/REACT/template-mdx/.storybook/main.js deleted file mode 100644 index e44fb99d3d7..00000000000 --- a/lib/cli/src/generators/REACT/template-mdx/.storybook/main.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - stories: ['../stories/**/*.stories.@(js|mdx)'], - addons: [ - '@storybook/addon-actions', - '@storybook/addon-links', - { - name: '@storybook/addon-docs', - options: { configureJSX: true }, - }, - ], -}; diff --git a/lib/cli/src/generators/REACT/template-mdx/stories/0-Welcome.stories.mdx b/lib/cli/src/generators/REACT/template-mdx/stories/0-Welcome.stories.mdx index 8f48008a3b5..705382f9fa5 100644 --- a/lib/cli/src/generators/REACT/template-mdx/stories/0-Welcome.stories.mdx +++ b/lib/cli/src/generators/REACT/template-mdx/stories/0-Welcome.stories.mdx @@ -1,8 +1,8 @@ import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'; import { linkTo } from '@storybook/addon-links'; -import { Welcome } from '@storybook/react/demo'; +import Welcome from './Welcome'; - + # Welcome diff --git a/lib/cli/src/generators/REACT/template-mdx/stories/1-Button.stories.mdx b/lib/cli/src/generators/REACT/template-mdx/stories/1-Button.stories.mdx index ed90840f9dc..9688920f604 100644 --- a/lib/cli/src/generators/REACT/template-mdx/stories/1-Button.stories.mdx +++ b/lib/cli/src/generators/REACT/template-mdx/stories/1-Button.stories.mdx @@ -1,8 +1,8 @@ import { action } from '@storybook/addon-actions'; -import { Button } from '@storybook/react/demo'; import { Meta, Story } from '@storybook/addon-docs/blocks'; +import Button from './Button'; - + # Button diff --git a/lib/cli/src/generators/REACT_NATIVE/index.ts b/lib/cli/src/generators/REACT_NATIVE/index.ts index a47856934c7..20ece5e36b6 100644 --- a/lib/cli/src/generators/REACT_NATIVE/index.ts +++ b/lib/cli/src/generators/REACT_NATIVE/index.ts @@ -1,30 +1,16 @@ import shell from 'shelljs'; import chalk from 'chalk'; -import { paddedLog, getBabelDependencies, copyTemplate } from '../../helpers'; +import { paddedLog, copyTemplate } from '../../helpers'; import { NpmOptions } from '../../NpmOptions'; -import { GeneratorOptions } from '../Generator'; -import { JsPackageManager, writePackageJson } from '../../js-package-manager'; +import { baseGenerator, GeneratorOptions } from '../generator'; +import { JsPackageManager } from '../../js-package-manager'; -export default async ( +const generator = async ( packageManager: JsPackageManager, npmOptions: NpmOptions, installServer: boolean, - { storyFormat }: GeneratorOptions -) => { - const [ - storybookVersion, - addonsVersion, - actionsVersion, - linksVersion, - ] = await packageManager.getVersions( - '@storybook/react-native', - '@storybook/addons', - '@storybook/addon-actions', - '@storybook/addon-links' - ); - - copyTemplate(__dirname, storyFormat); - + options: GeneratorOptions +): Promise => { // set correct project name on entry files if possible const dirname = shell.ls('-d', 'ios/*.xcodeproj').stdout; @@ -45,38 +31,19 @@ export default async ( const packageJson = packageManager.retrievePackageJson(); - packageJson.dependencies = packageJson.dependencies || {}; - packageJson.devDependencies = packageJson.devDependencies || {}; - - const devDependencies = [ - `@storybook/react-native@${storybookVersion}`, - `@storybook/addon-actions@${actionsVersion}`, - `@storybook/addon-links@${linksVersion}`, - `@storybook/addons@${addonsVersion}`, - ]; - - if (installServer) { - devDependencies.push(`@storybook/react-native-server@${storybookVersion}`); - } - - if (!packageJson.dependencies['react-dom'] && !packageJson.devDependencies['react-dom']) { - if (packageJson.dependencies.react) { - const reactVersion = packageJson.dependencies.react; - devDependencies.push(`react-dom@${reactVersion}`); - } - } - - if (installServer) { - packageJson.scripts = packageJson.scripts || {}; - packageJson.scripts.storybook = 'start-storybook -p 7007'; - } - - writePackageJson(packageJson); - - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - ...devDependencies, - ...babelDependencies, - ]); + const missingReactDom = + !packageJson.dependencies['react-dom'] && !packageJson.devDependencies['react-dom']; + const reactVersion = packageJson.dependencies.react; + + await baseGenerator(packageManager, npmOptions, options, 'react-native', { + extraPackages: [ + missingReactDom && reactVersion && `react-dom@${reactVersion}`, + installServer && '@storybook/react-native-server', + ].filter(Boolean), + addScripts: installServer, + addComponents: false, // We copy template-csf as it's wrapped in a storybook folder + }); + copyTemplate(__dirname, options.storyFormat); }; + +export default generator; diff --git a/lib/cli/src/generators/REACT_SCRIPTS/index.ts b/lib/cli/src/generators/REACT_SCRIPTS/index.ts index bba68ba18b7..573d91c8b2c 100644 --- a/lib/cli/src/generators/REACT_SCRIPTS/index.ts +++ b/lib/cli/src/generators/REACT_SCRIPTS/index.ts @@ -1,39 +1,18 @@ import path from 'path'; import fs from 'fs'; -import { getBabelDependencies, copyTemplate } from '../../helpers'; -import { StoryFormat } from '../../project_types'; -import { Generator } from '../Generator'; - -const generator: Generator = async (packageManager, npmOptions, { storyFormat }) => { - const packages = [ - '@storybook/react', - '@storybook/preset-create-react-app', - '@storybook/addon-actions', - '@storybook/addon-links', - '@storybook/addons', - ]; - - if (storyFormat === StoryFormat.MDX) { - packages.push('@storybook/addon-docs'); - } - - const versionedPackages = await packageManager.getVersionedPackages(...packages); - copyTemplate(__dirname, storyFormat); - - const packageJson = packageManager.retrievePackageJson(); - - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - ...versionedPackages, - ...babelDependencies, - ]); +import { baseGenerator, Generator } from '../generator'; +import { copyTemplate } from '../../helpers'; +import { StoryFormat } from '../../project_types'; - packageManager.addStorybookCommandInScripts({ - port: 9009, - staticFolder: fs.existsSync(path.resolve('./public')) ? 'public' : undefined, +const generator: Generator = async (packageManager, npmOptions, options) => { + await baseGenerator(packageManager, npmOptions, options, 'react', { + extraAddons: ['@storybook/preset-create-react-app'], + staticDir: fs.existsSync(path.resolve('./public')) ? 'public' : undefined, }); + if (options.storyFormat === StoryFormat.MDX) { + copyTemplate(__dirname, StoryFormat.MDX); + } }; export default generator; diff --git a/lib/cli/src/generators/REACT_SCRIPTS/template-csf-ts/.storybook/main.js b/lib/cli/src/generators/REACT_SCRIPTS/template-csf-ts/.storybook/main.js deleted file mode 100644 index cc503660aed..00000000000 --- a/lib/cli/src/generators/REACT_SCRIPTS/template-csf-ts/.storybook/main.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - stories: ['../src/**/*.stories.@(ts|tsx|js|jsx)'], - addons: [ - '@storybook/preset-create-react-app', - '@storybook/addon-actions', - '@storybook/addon-links', - ], -}; diff --git a/lib/cli/src/generators/REACT_SCRIPTS/template-csf-ts/src/stories/1-Button.stories.tsx b/lib/cli/src/generators/REACT_SCRIPTS/template-csf-ts/src/stories/1-Button.stories.tsx deleted file mode 100644 index 6bcfa214662..00000000000 --- a/lib/cli/src/generators/REACT_SCRIPTS/template-csf-ts/src/stories/1-Button.stories.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import { action } from '@storybook/addon-actions'; -import { Button } from '@storybook/react/demo'; - -export default { - title: 'Button', - component: Button, -}; - -export const Text = () => ; - -export const Emoji = () => ( - -); diff --git a/lib/cli/src/generators/REACT_SCRIPTS/template-csf/.storybook/main.js b/lib/cli/src/generators/REACT_SCRIPTS/template-csf/.storybook/main.js deleted file mode 100644 index 8f79d4617f2..00000000000 --- a/lib/cli/src/generators/REACT_SCRIPTS/template-csf/.storybook/main.js +++ /dev/null @@ -1,8 +0,0 @@ -module.exports = { - stories: ['../src/**/*.stories.js'], - addons: [ - '@storybook/preset-create-react-app', - '@storybook/addon-actions', - '@storybook/addon-links', - ], -}; diff --git a/lib/cli/src/generators/REACT_SCRIPTS/template-csf/src/stories/0-Welcome.stories.js b/lib/cli/src/generators/REACT_SCRIPTS/template-csf/src/stories/0-Welcome.stories.js deleted file mode 100644 index 9920a416e1f..00000000000 --- a/lib/cli/src/generators/REACT_SCRIPTS/template-csf/src/stories/0-Welcome.stories.js +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import { linkTo } from '@storybook/addon-links'; -import { Welcome } from '@storybook/react/demo'; - -export default { - title: 'Welcome', - component: Welcome, -}; - -export const ToStorybook = () => ; - -ToStorybook.storyName = 'to Storybook'; diff --git a/lib/cli/src/generators/REACT_SCRIPTS/template-mdx/.storybook/main.js b/lib/cli/src/generators/REACT_SCRIPTS/template-mdx/.storybook/main.js deleted file mode 100644 index 050ab43274f..00000000000 --- a/lib/cli/src/generators/REACT_SCRIPTS/template-mdx/.storybook/main.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = { - stories: ['../src/**/*.stories.@(js|mdx)'], - addons: [ - '@storybook/addon-actions', - '@storybook/addon-links', - '@storybook/preset-create-react-app', - { - name: '@storybook/addon-docs', - options: { - configureJSX: true, - }, - }, - ], -}; diff --git a/lib/cli/src/generators/REACT_SCRIPTS/template-mdx/src/stories/0-Welcome.stories.mdx b/lib/cli/src/generators/REACT_SCRIPTS/template-mdx/stories/0-Welcome.stories.mdx similarity index 78% rename from lib/cli/src/generators/REACT_SCRIPTS/template-mdx/src/stories/0-Welcome.stories.mdx rename to lib/cli/src/generators/REACT_SCRIPTS/template-mdx/stories/0-Welcome.stories.mdx index 8f48008a3b5..705382f9fa5 100644 --- a/lib/cli/src/generators/REACT_SCRIPTS/template-mdx/src/stories/0-Welcome.stories.mdx +++ b/lib/cli/src/generators/REACT_SCRIPTS/template-mdx/stories/0-Welcome.stories.mdx @@ -1,8 +1,8 @@ import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'; import { linkTo } from '@storybook/addon-links'; -import { Welcome } from '@storybook/react/demo'; +import Welcome from './Welcome'; - + # Welcome diff --git a/lib/cli/src/generators/REACT_SCRIPTS/template-mdx/src/stories/1-Button.stories.mdx b/lib/cli/src/generators/REACT_SCRIPTS/template-mdx/stories/1-Button.stories.mdx similarity index 82% rename from lib/cli/src/generators/REACT_SCRIPTS/template-mdx/src/stories/1-Button.stories.mdx rename to lib/cli/src/generators/REACT_SCRIPTS/template-mdx/stories/1-Button.stories.mdx index 7c87b32323c..2abc573287c 100644 --- a/lib/cli/src/generators/REACT_SCRIPTS/template-mdx/src/stories/1-Button.stories.mdx +++ b/lib/cli/src/generators/REACT_SCRIPTS/template-mdx/stories/1-Button.stories.mdx @@ -1,8 +1,8 @@ import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'; import { action } from '@storybook/addon-actions'; -import { Button } from '@storybook/react/demo'; +import Button from './Button'; - + # Button diff --git a/lib/cli/src/generators/RIOT/index.ts b/lib/cli/src/generators/RIOT/index.ts index 404eb4aeacf..21601dfe3b3 100644 --- a/lib/cli/src/generators/RIOT/index.ts +++ b/lib/cli/src/generators/RIOT/index.ts @@ -1,52 +1,9 @@ -import { getBabelDependencies, copyTemplate } from '../../helpers'; -import { Generator } from '../Generator'; -import { writePackageJson } from '../../js-package-manager'; +import { baseGenerator, Generator } from '../generator'; -const generator: Generator = async (packageManager, npmOptions, { storyFormat }) => { - const [ - storybookVersion, - actionsVersion, - linksVersion, - addonsVersion, - tagLoaderVersion, - ] = await packageManager.getVersions( - '@storybook/riot', - '@storybook/addon-actions', - '@storybook/addon-links', - '@storybook/addons', - 'riot-tag-loader' - ); - - copyTemplate(__dirname, storyFormat); - - const packageJson = packageManager.retrievePackageJson(); - - packageJson.dependencies = packageJson.dependencies || {}; - packageJson.devDependencies = packageJson.devDependencies || {}; - - const dependencies = [ - `@storybook/riot@${storybookVersion}`, - `@storybook/addon-actions@${actionsVersion}`, - `@storybook/addon-links@${linksVersion}`, - `@storybook/addons@${addonsVersion}`, - ]; - if ( - !packageJson.devDependencies['riot-tag-loader'] && - !packageJson.dependencies['riot-tag-loader'] - ) { - dependencies.push(`riot-tag-loader@${tagLoaderVersion}`); - } - - writePackageJson(packageJson); - - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - ...dependencies, - ...babelDependencies, - ]); - - packageManager.addStorybookCommandInScripts(); +const generator: Generator = async (packageManager, npmOptions, options) => { + baseGenerator(packageManager, npmOptions, options, 'riot', { + extraPackages: ['riot-tag-loader'], + }); }; export default generator; diff --git a/lib/cli/src/generators/RIOT/template-csf/.storybook/main.js b/lib/cli/src/generators/RIOT/template-csf/.storybook/main.js deleted file mode 100644 index 3036098563c..00000000000 --- a/lib/cli/src/generators/RIOT/template-csf/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../stories/**/*.stories.js'], - addons: ['@storybook/addon-actions', '@storybook/addon-links'], -}; diff --git a/lib/cli/src/generators/SFC_VUE/index.ts b/lib/cli/src/generators/SFC_VUE/index.ts index df945f683fa..bced886ae3a 100644 --- a/lib/cli/src/generators/SFC_VUE/index.ts +++ b/lib/cli/src/generators/SFC_VUE/index.ts @@ -1,31 +1,12 @@ -import { getBabelDependencies, copyTemplate } from '../../helpers'; +import { baseGenerator, Generator } from '../generator'; import { StoryFormat } from '../../project_types'; -import { Generator } from '../Generator'; +import { copyTemplate } from '../../helpers'; -const generator: Generator = async (packageManager, npmOptions, { storyFormat }) => { - const packages = [ - '@storybook/vue', - '@storybook/addon-actions', - '@storybook/addon-links', - '@storybook/addons', - ]; - if (storyFormat === StoryFormat.MDX) { - packages.push('@storybook/addon-docs'); +const generator: Generator = async (packageManager, npmOptions, options) => { + baseGenerator(packageManager, npmOptions, options, 'vue'); + if (options.storyFormat === StoryFormat.MDX) { + copyTemplate(__dirname, StoryFormat.MDX); } - const versionedPackages = await packageManager.getVersionedPackages(...packages); - - copyTemplate(__dirname, storyFormat); - - const packageJson = packageManager.retrievePackageJson(); - - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - ...versionedPackages, - ...babelDependencies, - ]); - - packageManager.addStorybookCommandInScripts(); }; export default generator; diff --git a/lib/cli/src/generators/SFC_VUE/template-csf/.storybook/main.js b/lib/cli/src/generators/SFC_VUE/template-csf/.storybook/main.js deleted file mode 100644 index 302586ca409..00000000000 --- a/lib/cli/src/generators/SFC_VUE/template-csf/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../src/**/*.stories.js'], - addons: ['@storybook/addon-actions', '@storybook/addon-links'], -}; diff --git a/lib/cli/src/generators/SFC_VUE/template-csf/src/stories/1-Button.stories.js b/lib/cli/src/generators/SFC_VUE/template-csf/src/stories/1-Button.stories.js deleted file mode 100644 index 2a8f67f6c0a..00000000000 --- a/lib/cli/src/generators/SFC_VUE/template-csf/src/stories/1-Button.stories.js +++ /dev/null @@ -1,32 +0,0 @@ -import { action } from '@storybook/addon-actions'; -import { linkTo } from '@storybook/addon-links'; - -import MyButton from './MyButton.vue'; - -export default { - title: 'Button', - component: MyButton, -}; - -export const Text = () => ({ - components: { MyButton }, - template: 'Hello Button', - methods: { action: action('clicked') }, -}); - -export const TextWithAction = () => ({ - components: { MyButton }, - template: 'Trigger Action', - methods: { action: () => action('This was clicked')() }, -}); - -TextWithAction.storyName = 'With an action'; -TextWithAction.parameters = { notes: 'My notes on a button with emojis' }; - -export const ButtonWithLinkToAnotherStory = () => ({ - components: { MyButton }, - template: 'Go to Welcome Story', - methods: { action: linkTo('Welcome') }, -}); - -ButtonWithLinkToAnotherStory.storyName = 'button with link to another story'; diff --git a/lib/cli/src/generators/SFC_VUE/template-mdx/.storybook/main.js b/lib/cli/src/generators/SFC_VUE/template-mdx/.storybook/main.js deleted file mode 100644 index 320231e699e..00000000000 --- a/lib/cli/src/generators/SFC_VUE/template-mdx/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../src/**/*.stories.@(js|mdx)'], - addons: ['@storybook/addon-docs', '@storybook/addon-actions', '@storybook/addon-links'], -}; diff --git a/lib/cli/src/generators/SFC_VUE/template-mdx/src/stories/MyButton.vue b/lib/cli/src/generators/SFC_VUE/template-mdx/src/stories/MyButton.vue deleted file mode 100644 index 4ad8ff85f08..00000000000 --- a/lib/cli/src/generators/SFC_VUE/template-mdx/src/stories/MyButton.vue +++ /dev/null @@ -1,29 +0,0 @@ - - - - - diff --git a/lib/cli/src/generators/SFC_VUE/template-mdx/src/stories/Welcome.vue b/lib/cli/src/generators/SFC_VUE/template-mdx/src/stories/Welcome.vue deleted file mode 100644 index bfb932da3d2..00000000000 --- a/lib/cli/src/generators/SFC_VUE/template-mdx/src/stories/Welcome.vue +++ /dev/null @@ -1,119 +0,0 @@ - - - - - diff --git a/lib/cli/src/generators/SFC_VUE/template-mdx/src/stories/0-Welcome.stories.mdx b/lib/cli/src/generators/SFC_VUE/template-mdx/stories/0-Welcome.stories.mdx similarity index 100% rename from lib/cli/src/generators/SFC_VUE/template-mdx/src/stories/0-Welcome.stories.mdx rename to lib/cli/src/generators/SFC_VUE/template-mdx/stories/0-Welcome.stories.mdx diff --git a/lib/cli/src/generators/SFC_VUE/template-mdx/src/stories/1-Button.stories.mdx b/lib/cli/src/generators/SFC_VUE/template-mdx/stories/1-Button.stories.mdx similarity index 94% rename from lib/cli/src/generators/SFC_VUE/template-mdx/src/stories/1-Button.stories.mdx rename to lib/cli/src/generators/SFC_VUE/template-mdx/stories/1-Button.stories.mdx index f37647542ac..8a5b92a8d63 100644 --- a/lib/cli/src/generators/SFC_VUE/template-mdx/src/stories/1-Button.stories.mdx +++ b/lib/cli/src/generators/SFC_VUE/template-mdx/stories/1-Button.stories.mdx @@ -1,7 +1,7 @@ import { Meta, Story } from '@storybook/addon-docs/blocks'; import { action } from '@storybook/addon-actions'; import { linkTo } from '@storybook/addon-links'; -import MyButton from './MyButton.vue'; +import MyButton from './Button.vue'; diff --git a/lib/cli/src/generators/SVELTE/index.ts b/lib/cli/src/generators/SVELTE/index.ts index 646e234961c..9558f33787c 100644 --- a/lib/cli/src/generators/SVELTE/index.ts +++ b/lib/cli/src/generators/SVELTE/index.ts @@ -1,40 +1,9 @@ -import { getBabelDependencies, copyTemplate } from '../../helpers'; -import { Generator } from '../Generator'; +import { baseGenerator, Generator } from '../generator'; -const generator: Generator = async (packageManager, npmOptions, { storyFormat }) => { - const [ - storybookVersion, - actionsVersion, - linksVersion, - addonsVersion, - svelte, - svelteLoader, - ] = await packageManager.getVersions( - '@storybook/svelte', - '@storybook/addon-actions', - '@storybook/addon-links', - '@storybook/addons', - 'svelte', - 'svelte-loader' - ); - - copyTemplate(__dirname, storyFormat); - - const packageJson = packageManager.retrievePackageJson(); - - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - `@storybook/svelte@${storybookVersion}`, - `@storybook/addon-actions@${actionsVersion}`, - `@storybook/addon-links@${linksVersion}`, - `@storybook/addons@${addonsVersion}`, - `svelte@${svelte}`, - `svelte-loader@${svelteLoader}`, - ...babelDependencies, - ]); - - packageManager.addStorybookCommandInScripts(); +const generator: Generator = async (packageManager, npmOptions, options) => { + baseGenerator(packageManager, npmOptions, options, 'svelte', { + extraPackages: ['svelte', 'svelte-loader'], + }); }; export default generator; diff --git a/lib/cli/src/generators/SVELTE/template-csf/.storybook/main.js b/lib/cli/src/generators/SVELTE/template-csf/.storybook/main.js deleted file mode 100644 index 3036098563c..00000000000 --- a/lib/cli/src/generators/SVELTE/template-csf/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../stories/**/*.stories.js'], - addons: ['@storybook/addon-actions', '@storybook/addon-links'], -}; diff --git a/lib/cli/src/generators/VUE/index.ts b/lib/cli/src/generators/VUE/index.ts index 0efb2d56bb0..bced886ae3a 100644 --- a/lib/cli/src/generators/VUE/index.ts +++ b/lib/cli/src/generators/VUE/index.ts @@ -1,52 +1,12 @@ -import { - getBabelDependencies, - addToDevDependenciesIfNotPresent, - copyTemplate, -} from '../../helpers'; +import { baseGenerator, Generator } from '../generator'; import { StoryFormat } from '../../project_types'; -import { Generator } from '../Generator'; -import { writePackageJson } from '../../js-package-manager'; +import { copyTemplate } from '../../helpers'; -const generator: Generator = async (packageManager, npmOptions, { storyFormat }) => { - const packages = [ - '@storybook/vue', - '@storybook/addon-actions', - '@storybook/addon-links', - '@storybook/addons', - '@babel/core', - ]; - if (storyFormat === StoryFormat.MDX) { - packages.push('@storybook/addon-docs'); +const generator: Generator = async (packageManager, npmOptions, options) => { + baseGenerator(packageManager, npmOptions, options, 'vue'); + if (options.storyFormat === StoryFormat.MDX) { + copyTemplate(__dirname, StoryFormat.MDX); } - const versionedPackages = await packageManager.getVersionedPackages(...packages); - - copyTemplate(__dirname, storyFormat); - - const packageJson = packageManager.retrievePackageJson(); - - const packageBabelCoreVersion = - packageJson.dependencies['babel-core'] || packageJson.devDependencies['babel-core']; - - // This seems to be the version installed by the Vue CLI, and it is not handled by - // installBabel below. For some reason it leads to the wrong version of @babel/core (a beta) - // being installed - if (packageBabelCoreVersion === '7.0.0-bridge.0') { - addToDevDependenciesIfNotPresent( - packageJson, - '@babel/core', - await packageManager.getVersion('@babel/core') - ); - } - - writePackageJson(packageJson); - - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - ...versionedPackages, - ...babelDependencies, - ]); - - packageManager.addStorybookCommandInScripts(); }; export default generator; diff --git a/lib/cli/src/generators/VUE/template-csf/.storybook/main.js b/lib/cli/src/generators/VUE/template-csf/.storybook/main.js deleted file mode 100644 index 3036098563c..00000000000 --- a/lib/cli/src/generators/VUE/template-csf/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../stories/**/*.stories.js'], - addons: ['@storybook/addon-actions', '@storybook/addon-links'], -}; diff --git a/lib/cli/src/generators/VUE/template-csf/stories/0-Welcome.stories.js b/lib/cli/src/generators/VUE/template-csf/stories/0-Welcome.stories.js deleted file mode 100644 index 751d3002ef6..00000000000 --- a/lib/cli/src/generators/VUE/template-csf/stories/0-Welcome.stories.js +++ /dev/null @@ -1,16 +0,0 @@ -import { linkTo } from '@storybook/addon-links'; - -import Welcome from './Welcome'; - -export default { - title: 'Welcome', - component: Welcome, -}; - -export const ToStorybook = () => ({ - components: { Welcome }, - template: '', - methods: { action: linkTo('Button') }, -}); - -ToStorybook.storyName = 'to Storybook'; diff --git a/lib/cli/src/generators/VUE/template-csf/stories/MyButton.js b/lib/cli/src/generators/VUE/template-csf/stories/MyButton.js deleted file mode 100644 index 7ed4b85378d..00000000000 --- a/lib/cli/src/generators/VUE/template-csf/stories/MyButton.js +++ /dev/null @@ -1,29 +0,0 @@ -export default { - name: 'my-button', - - data() { - return { - buttonStyles: { - border: '1px solid #eee', - borderRadius: 3, - backgroundColor: '#FFFFFF', - cursor: 'pointer', - fontSize: 15, - padding: '3px 10px', - margin: 10, - }, - }; - }, - - template: ` - - `, - - methods: { - onClick() { - this.$emit('click'); - }, - }, -}; diff --git a/lib/cli/src/generators/VUE/template-csf/stories/Welcome.js b/lib/cli/src/generators/VUE/template-csf/stories/Welcome.js deleted file mode 100644 index 80df0039e05..00000000000 --- a/lib/cli/src/generators/VUE/template-csf/stories/Welcome.js +++ /dev/null @@ -1,121 +0,0 @@ -// eslint-disable-next-line no-console -const log = () => console.log('Welcome to storybook!'); - -export default { - name: 'welcome', - - props: { - showApp: { - type: Function, - default: log, - }, - }, - - data() { - return { - main: { - padding: 15, - lineHeight: 1.4, - fontFamily: '"Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif', - backgroundColor: '#ffffff', - }, - - logo: { - width: 200, - }, - - link: { - color: '#1474f3', - textDecoration: 'none', - borderBottom: '1px solid #1474f3', - paddingBottom: 2, - }, - - code: { - fontSize: 15, - fontWeight: 600, - padding: '2px 5px', - border: '1px solid #eae9e9', - borderRadius: 4, - backgroundColor: '#f3f2f2', - color: '#3a3a3a', - }, - - note: { - opacity: 0.5, - }, - }; - }, - - template: ` -
-

Welcome to storybook

-

- This is a UI component dev environment for your app. -

-

- We've added some basic stories inside the -
- src/stories -
- directory. -
- A story is a single state of one or more UI components. You can have as many stories as - you want. -
- (Basically a story is like a visual test case.) -

-

- See these sample -
- stories -
- for a component called -
- Button - . -

-

- Just like that, you can add your own components as stories. -
- You can also edit those components and see changes right away. -
- (Try editing the Button component - located at src/stories/Button.js.) -

-

- This is just one thing you can do with Storybook. -
- Have a look at the -
- - Storybook - -
- repo for more information. -

-

- NOTE: -
- Have a look at the -
- .storybook/webpack.config.js -
- to add webpack - loaders and plugins you are using in this project. -

-
- `, - - methods: { - onClick(event) { - event.preventDefault(); - this.showApp(); - }, - }, -}; diff --git a/lib/cli/src/generators/WEB-COMPONENTS/index.ts b/lib/cli/src/generators/WEB-COMPONENTS/index.ts index 03ced0f5e0c..58e11363da3 100755 --- a/lib/cli/src/generators/WEB-COMPONENTS/index.ts +++ b/lib/cli/src/generators/WEB-COMPONENTS/index.ts @@ -1,35 +1,11 @@ -import fse from 'fs-extra'; -import path from 'path'; -import { getBabelDependencies } from '../../helpers'; -import { StoryFormat } from '../../project_types'; -import { Generator } from '../Generator'; - -const generator: Generator = async (packageManager, npmOptions, { storyFormat }) => { - const packages = [ - '@storybook/web-components', - '@storybook/addon-actions', - '@storybook/addon-links', - 'lit-html', - ]; - - const versionedPackages = await packageManager.getVersionedPackages(...packages); - - fse.copySync(path.resolve(__dirname, 'template/'), '.', { overwrite: true }); - - if (storyFormat === StoryFormat.MDX) { - // TODO: handle adding of docs mode - } - - const packageJson = packageManager.retrievePackageJson(); - - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - ...versionedPackages, - ...babelDependencies, - ]); - - packageManager.addStorybookCommandInScripts(); +import { baseGenerator, Generator } from '../generator'; +import { copyTemplate } from '../../helpers'; + +const generator: Generator = async (packageManager, npmOptions, options) => { + baseGenerator(packageManager, npmOptions, options, 'web-components', { + extraPackages: ['lit-html'], + }); + copyTemplate(__dirname, options.storyFormat); }; export default generator; diff --git a/lib/cli/src/generators/WEB-COMPONENTS/template/.storybook/preview.js b/lib/cli/src/generators/WEB-COMPONENTS/template-csf/.storybook/preview.js similarity index 100% rename from lib/cli/src/generators/WEB-COMPONENTS/template/.storybook/preview.js rename to lib/cli/src/generators/WEB-COMPONENTS/template-csf/.storybook/preview.js diff --git a/lib/cli/src/generators/WEB-COMPONENTS/template/.storybook/main.js b/lib/cli/src/generators/WEB-COMPONENTS/template/.storybook/main.js deleted file mode 100644 index 3036098563c..00000000000 --- a/lib/cli/src/generators/WEB-COMPONENTS/template/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../stories/**/*.stories.js'], - addons: ['@storybook/addon-actions', '@storybook/addon-links'], -}; diff --git a/lib/cli/src/generators/WEBPACK_REACT/index.ts b/lib/cli/src/generators/WEBPACK_REACT/index.ts index 5c030def1ee..6a40334f6bf 100644 --- a/lib/cli/src/generators/WEBPACK_REACT/index.ts +++ b/lib/cli/src/generators/WEBPACK_REACT/index.ts @@ -1,31 +1,12 @@ -import { getBabelDependencies, copyTemplate } from '../../helpers'; +import { baseGenerator, Generator } from '../generator'; import { StoryFormat } from '../../project_types'; -import { Generator } from '../Generator'; +import { copyTemplate } from '../../helpers'; -const generator: Generator = async (packageManager, npmOptions, { storyFormat }) => { - const packages = [ - '@storybook/react', - '@storybook/addon-actions', - '@storybook/addon-links', - '@storybook/addons', - ]; - if (storyFormat === StoryFormat.MDX) { - packages.push('@storybook/addon-docs'); +const generator: Generator = async (packageManager, npmOptions, options) => { + baseGenerator(packageManager, npmOptions, options, 'react'); + if (options.storyFormat === StoryFormat.MDX) { + copyTemplate(__dirname, StoryFormat.MDX); } - const versionedPackages = await packageManager.getVersionedPackages(...packages); - - copyTemplate(__dirname, storyFormat); - - const packageJson = packageManager.retrievePackageJson(); - - const babelDependencies = await getBabelDependencies(packageManager, packageJson); - - packageManager.addDependencies({ ...npmOptions, packageJson }, [ - ...versionedPackages, - ...babelDependencies, - ]); - - packageManager.addStorybookCommandInScripts(); }; export default generator; diff --git a/lib/cli/src/generators/WEBPACK_REACT/template-csf-ts/.storybook/main.js b/lib/cli/src/generators/WEBPACK_REACT/template-csf-ts/.storybook/main.js deleted file mode 100644 index 523dca65b67..00000000000 --- a/lib/cli/src/generators/WEBPACK_REACT/template-csf-ts/.storybook/main.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - stories: ['../src/**/*.stories.@(ts|tsx|js|jsx)'], - addons: ['@storybook/addon-actions', '@storybook/addon-links'], -}; diff --git a/lib/cli/src/generators/WEBPACK_REACT/template-csf-ts/src/stories/0-Welcome.stories.tsx b/lib/cli/src/generators/WEBPACK_REACT/template-csf-ts/src/stories/0-Welcome.stories.tsx deleted file mode 100644 index c76f45f3b4b..00000000000 --- a/lib/cli/src/generators/WEBPACK_REACT/template-csf-ts/src/stories/0-Welcome.stories.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react'; -import { linkTo } from '@storybook/addon-links'; -import { Welcome } from '@storybook/react/demo'; - -export default { - title: 'Welcome', - component: Welcome, -}; - -export const ToStorybook = () => ; - -ToStorybook.story = { - name: 'to Storybook', -}; diff --git a/lib/cli/src/generators/WEBPACK_REACT/template-csf-ts/src/stories/1-Button.stories.tsx b/lib/cli/src/generators/WEBPACK_REACT/template-csf-ts/src/stories/1-Button.stories.tsx deleted file mode 100644 index 6bcfa214662..00000000000 --- a/lib/cli/src/generators/WEBPACK_REACT/template-csf-ts/src/stories/1-Button.stories.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import { action } from '@storybook/addon-actions'; -import { Button } from '@storybook/react/demo'; - -export default { - title: 'Button', - component: Button, -}; - -export const Text = () => ; - -export const Emoji = () => ( - -); diff --git a/lib/cli/src/generators/WEBPACK_REACT/template-csf/.storybook/main.js b/lib/cli/src/generators/WEBPACK_REACT/template-csf/.storybook/main.js deleted file mode 100644 index 69e89d84f74..00000000000 --- a/lib/cli/src/generators/WEBPACK_REACT/template-csf/.storybook/main.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - stories: ['../stories/**/*.stories.js'], - addons: ['@storybook/addon-actions', '@storybook/addon-links'], - webpackFinal: async (config) => { - // do mutation to the config - - return config; - }, -}; diff --git a/lib/cli/src/generators/WEBPACK_REACT/template-csf/stories/0-Welcome.stories.js b/lib/cli/src/generators/WEBPACK_REACT/template-csf/stories/0-Welcome.stories.js deleted file mode 100644 index 9920a416e1f..00000000000 --- a/lib/cli/src/generators/WEBPACK_REACT/template-csf/stories/0-Welcome.stories.js +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import { linkTo } from '@storybook/addon-links'; -import { Welcome } from '@storybook/react/demo'; - -export default { - title: 'Welcome', - component: Welcome, -}; - -export const ToStorybook = () => ; - -ToStorybook.storyName = 'to Storybook'; diff --git a/lib/cli/src/generators/WEBPACK_REACT/template-csf/stories/1-Button.stories.js b/lib/cli/src/generators/WEBPACK_REACT/template-csf/stories/1-Button.stories.js deleted file mode 100644 index fdbd42fe76f..00000000000 --- a/lib/cli/src/generators/WEBPACK_REACT/template-csf/stories/1-Button.stories.js +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import { action } from '@storybook/addon-actions'; -import { linkTo } from '@storybook/addon-links'; -import { Button } from '@storybook/react/demo'; - -export default { - title: 'Button', - component: Button, -}; - -export const Text = () => ; - -export const Emoji = () => ( - -); - -Emoji.parameters = { notes: 'My notes on a button with emojis' }; - -export const TextWithAction = () => ( - -); - -TextWithAction.storyName = 'With an action'; -TextWithAction.parameters = { notes: 'My notes on a button with emojis' }; - -export const ButtonWithLinkToAnotherStory = () => ( - -); - -ButtonWithLinkToAnotherStory.storyName = 'button with link to another story'; diff --git a/lib/cli/src/generators/WEBPACK_REACT/template-mdx/.storybook/main.js b/lib/cli/src/generators/WEBPACK_REACT/template-mdx/.storybook/main.js deleted file mode 100644 index 055aea01539..00000000000 --- a/lib/cli/src/generators/WEBPACK_REACT/template-mdx/.storybook/main.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = { - stories: ['../stories/**/*.stories.@(js|mdx)'], - addons: [ - '@storybook/addon-actions', - '@storybook/addon-links', - { - name: '@storybook/addon-docs', - options: { configureJSX: true }, - }, - ], - webpackFinal: async (config) => { - // do mutation to the config - - return config; - }, -}; diff --git a/lib/cli/src/generators/WEBPACK_REACT/template-mdx/stories/0-Welcome.stories.mdx b/lib/cli/src/generators/WEBPACK_REACT/template-mdx/stories/0-Welcome.stories.mdx index 8f48008a3b5..705382f9fa5 100644 --- a/lib/cli/src/generators/WEBPACK_REACT/template-mdx/stories/0-Welcome.stories.mdx +++ b/lib/cli/src/generators/WEBPACK_REACT/template-mdx/stories/0-Welcome.stories.mdx @@ -1,8 +1,8 @@ import { Meta, Story, Preview } from '@storybook/addon-docs/blocks'; import { linkTo } from '@storybook/addon-links'; -import { Welcome } from '@storybook/react/demo'; +import Welcome from './Welcome'; - + # Welcome diff --git a/lib/cli/src/generators/WEBPACK_REACT/template-mdx/stories/1-Button.stories.mdx b/lib/cli/src/generators/WEBPACK_REACT/template-mdx/stories/1-Button.stories.mdx index 876782206a8..329ea1da39c 100644 --- a/lib/cli/src/generators/WEBPACK_REACT/template-mdx/stories/1-Button.stories.mdx +++ b/lib/cli/src/generators/WEBPACK_REACT/template-mdx/stories/1-Button.stories.mdx @@ -1,8 +1,8 @@ import { Meta, Story } from '@storybook/addon-docs/blocks'; import { action } from '@storybook/addon-actions'; -import { Button } from '@storybook/react/demo'; +import Button from './Button'; - + # Button diff --git a/lib/cli/src/generators/configure.ts b/lib/cli/src/generators/configure.ts new file mode 100644 index 00000000000..a390c4a0f6e --- /dev/null +++ b/lib/cli/src/generators/configure.ts @@ -0,0 +1,19 @@ +import fse from 'fs-extra'; + +function mainConfigurationGenerator(addons: string[], custom?: any) { + const hasSrc = fse.existsSync('./src'); + + const config = { + stories: [!hasSrc && '../stories/**/*.stories.*', hasSrc && '../src/**/*.stories.*'].filter( + Boolean + ), + addons, + ...custom, + }; + + const stringified = `module.exports = ${JSON.stringify(config, null, 2)}`; + fse.ensureDirSync('./.storybook'); + fse.writeFileSync('./.storybook/main.js', stringified, { encoding: 'utf8' }); +} + +export default mainConfigurationGenerator; diff --git a/lib/cli/src/generators/generator.ts b/lib/cli/src/generators/generator.ts new file mode 100644 index 00000000000..344c3e8438c --- /dev/null +++ b/lib/cli/src/generators/generator.ts @@ -0,0 +1,89 @@ +import { NpmOptions } from '../NpmOptions'; +import { StoryFormat, SupportedLanguage, SupportedFrameworks } from '../project_types'; +import { getBabelDependencies, copyComponents } from '../helpers'; +import configure from './configure'; +import { JsPackageManager } from '../js-package-manager'; + +export type GeneratorOptions = { + language: SupportedLanguage; + storyFormat: StoryFormat; +}; + +export interface FrameworkOptions { + extraPackages?: string[]; + extraAddons?: string[]; + staticDir?: string; + addScripts?: boolean; + addComponents?: boolean; +} + +export type Generator = ( + packageManager: JsPackageManager, + npmOptions: NpmOptions, + options: GeneratorOptions +) => Promise; + +const defaultOptions: FrameworkOptions = { + extraPackages: [], + extraAddons: [], + staticDir: undefined, + addScripts: true, + addComponents: true, +}; + +export async function baseGenerator( + packageManager: JsPackageManager, + npmOptions: NpmOptions, + { language }: GeneratorOptions, + framework: SupportedFrameworks, + options: FrameworkOptions = defaultOptions +) { + const { extraAddons, extraPackages, staticDir, addScripts, addComponents } = { + ...defaultOptions, + ...options, + }; + + const addons = [ + '@storybook/addon-links', + '@storybook/addon-actions', + // If angular skip `docs` because docs is buggy for now (https://github.com/storybookjs/storybook/issues/9103) + // for others framework add `essentials` i.e. `actions`, `backgrounds`, `docs`, `viewport` + // API of essentials needs to be clarified whether we need to add dependencies or not + framework !== 'angular' && '@storybook/addon-docs', + ].filter(Boolean); + + // ⚠️ Some addons have peer deps that must be added too, like '@storybook/addon-docs' => 'react-is' + const addonsPeerDeps = addons.some( + (addon) => addon === '@storybook/addon-essentials' || addon === '@storybook/addon-docs' + ) + ? ['react-is'] + : []; + + const packages = [ + `@storybook/${framework}`, + ...addons, + ...extraPackages, + ...extraAddons, + ...addonsPeerDeps, + ].filter(Boolean); + const versionedPackages = await packageManager.getVersionedPackages(...packages); + console.log('versionedPackages', versionedPackages); + configure([...addons, ...extraAddons]); + if (addComponents) { + copyComponents(framework, language); + } + + const packageJson = packageManager.retrievePackageJson(); + + if (addScripts) { + packageManager.addStorybookCommandInScripts({ + port: 6006, + staticFolder: staticDir, + }); + } + const babelDependencies = await getBabelDependencies(packageManager, packageJson); + packageManager.addDependencies({ ...npmOptions, packageJson }, [ + ...versionedPackages, + ...babelDependencies, + ]); +} diff --git a/lib/cli/src/helpers.test.ts b/lib/cli/src/helpers.test.ts index 675733fe759..1a7d32cfaf5 100644 --- a/lib/cli/src/helpers.test.ts +++ b/lib/cli/src/helpers.test.ts @@ -2,7 +2,7 @@ import fs from 'fs'; import fse from 'fs-extra'; import * as helpers from './helpers'; -import { StoryFormat } from './project_types'; +import { StoryFormat, SupportedLanguage, SupportedFrameworks } from './project_types'; jest.mock('fs', () => ({ existsSync: jest.fn(), @@ -10,6 +10,8 @@ jest.mock('fs', () => ({ jest.mock('fs-extra', () => ({ copySync: jest.fn(() => ({})), + ensureDir: jest.fn(() => {}), + existsSync: jest.fn(), })); jest.mock('path', () => ({ @@ -50,4 +52,58 @@ describe('Helpers', () => { }).toThrowError(expectedMessage); }); }); + + it.each` + language | exists | expected + ${'javascript'} | ${['js', 'ts']} | ${'/js'} + ${'typescript'} | ${['js', 'ts']} | ${'/ts'} + ${'typescript'} | ${['js']} | ${'/js'} + ${'javascript'} | ${[]} | ${''} + ${'typescript'} | ${[]} | ${''} + `( + `should copy $expected when folder $exists exists for language $language`, + ({ language, exists, expected }) => { + const componentsDirectory = exists.map((folder: string) => `frameworks/react/${folder}`); + const expectedDirectory = `frameworks/react${expected}`; + (fse.existsSync as jest.Mock).mockImplementation((filePath) => { + return componentsDirectory.includes(filePath) || filePath === 'frameworks/react'; + }); + helpers.copyComponents('react', language); + + const copySyncSpy = jest.spyOn(fse, 'copySync'); + expect(copySyncSpy).toHaveBeenCalledWith( + expectedDirectory, + expect.anything(), + expect.anything() + ); + } + ); + + it(`should copy to src folder when exists`, () => { + (fse.existsSync as jest.Mock).mockImplementation((filePath) => { + return filePath === 'frameworks/react' || filePath === './src'; + }); + helpers.copyComponents('react', SupportedLanguage.JAVASCRIPT); + expect(fse.copySync).toHaveBeenCalledWith( + expect.anything(), + './src/stories', + expect.anything() + ); + }); + + it(`should copy to root folder when src doesn't exist`, () => { + (fse.existsSync as jest.Mock).mockImplementation((filePath) => { + return filePath === 'frameworks/react'; + }); + helpers.copyComponents('react', SupportedLanguage.JAVASCRIPT); + expect(fse.copySync).toHaveBeenCalledWith(expect.anything(), './stories', expect.anything()); + }); + + it(`should throw an error for unsupported framework`, () => { + const framework = 'unknown framework' as SupportedFrameworks; + const expectedMessage = `Unsupported framework: ${framework}`; + expect(() => { + helpers.copyComponents(framework, SupportedLanguage.JAVASCRIPT); + }).toThrowError(expectedMessage); + }); }); diff --git a/lib/cli/src/helpers.ts b/lib/cli/src/helpers.ts index 9f32d3c4fac..ad32fc1816f 100644 --- a/lib/cli/src/helpers.ts +++ b/lib/cli/src/helpers.ts @@ -6,7 +6,7 @@ import chalk from 'chalk'; import { satisfies } from '@storybook/semver'; import stripJsonComments from 'strip-json-comments'; -import { StoryFormat } from './project_types'; +import { StoryFormat, SupportedFrameworks, SupportedLanguage } from './project_types'; import { JsPackageManager, PackageJson, PackageJsonWithDepsAndDevDeps } from './js-package-manager'; const logger = console; @@ -165,6 +165,7 @@ export function addToDevDependenciesIfNotPresent( export function copyTemplate(templateRoot: string, storyFormat: StoryFormat) { const templateDir = path.resolve(templateRoot, `template-${storyFormat}/`); + if (!fs.existsSync(templateDir)) { // Fallback to CSF plain first, in case format is typescript but template is not available. if (storyFormat === StoryFormat.CSF_TYPESCRIPT) { @@ -176,3 +177,42 @@ export function copyTemplate(templateRoot: string, storyFormat: StoryFormat) { } fse.copySync(templateDir, '.', { overwrite: true }); } + +export function copyComponents(framework: SupportedFrameworks, language: SupportedLanguage) { + const languageFolderMapping: Record = { + javascript: 'js', + typescript: 'ts', + }; + const componentsPath = () => { + const frameworkPath = `frameworks/${framework}`; + const languageSpecific = path.resolve( + __dirname, + `${frameworkPath}/${languageFolderMapping[language]}` + ); + if (fse.existsSync(languageSpecific)) { + return languageSpecific; + } + const jsFallback = path.resolve( + __dirname, + `${frameworkPath}/${languageFolderMapping.javascript}` + ); + if (fse.existsSync(jsFallback)) { + return jsFallback; + } + const frameworkRootPath = path.resolve(__dirname, frameworkPath); + if (fse.existsSync(frameworkRootPath)) { + return frameworkRootPath; + } + throw new Error(`Unsupported framework: ${framework}`); + }; + + const targetPath = () => { + if (fse.existsSync('./src')) { + return './src/stories'; + } + return './stories'; + }; + + const destinationPath = targetPath(); + fse.copySync(componentsPath(), destinationPath, { overwrite: true }); +} diff --git a/lib/cli/src/initiate.ts b/lib/cli/src/initiate.ts index a204d606a33..743ab7a31fd 100644 --- a/lib/cli/src/initiate.ts +++ b/lib/cli/src/initiate.ts @@ -53,7 +53,8 @@ const installStorybook = (projectType: ProjectType, options: CommandOptions): Pr skipInstall: options.skipInstall, }; - const hasTSDependency = detectLanguage() === SupportedLanguage.TYPESCRIPT; + const language = detectLanguage(); + const hasTSDependency = language === SupportedLanguage.TYPESCRIPT; warn({ hasTSDependency }); @@ -61,6 +62,7 @@ const installStorybook = (projectType: ProjectType, options: CommandOptions): Pr const generatorOptions = { storyFormat: options.storyFormat || defaultStoryFormat, + language, }; const end = () => { diff --git a/lib/cli/src/js-package-manager/JsPackageManager.ts b/lib/cli/src/js-package-manager/JsPackageManager.ts index eeb52bfa4be..43ee1fb5435 100644 --- a/lib/cli/src/js-package-manager/JsPackageManager.ts +++ b/lib/cli/src/js-package-manager/JsPackageManager.ts @@ -129,6 +129,7 @@ export abstract class JsPackageManager { * @param packageNames */ public getVersions(...packageNames: string[]): Promise { + console.log('getVersions', packageNames); return Promise.all(packageNames.map((packageName) => this.getVersion(packageName))); } diff --git a/lib/cli/src/project_types.ts b/lib/cli/src/project_types.ts index 48df5d20076..35cf14657a8 100644 --- a/lib/cli/src/project_types.ts +++ b/lib/cli/src/project_types.ts @@ -1,3 +1,4 @@ +// Should match @storybook/ export type SupportedFrameworks = | 'react' | 'react-native' @@ -11,7 +12,10 @@ export type SupportedFrameworks = | 'meteor' | 'preact' | 'svelte' - | 'rax'; + | 'rax' + | 'aurelia' + | 'html' + | 'web-components'; export enum ProjectType { UNDETECTED = 'UNDETECTED', diff --git a/lib/cli/test/fixtures/sfc_vue/package.json b/lib/cli/test/fixtures/sfc_vue/package.json index ed04921b850..a9bed94b180 100644 --- a/lib/cli/test/fixtures/sfc_vue/package.json +++ b/lib/cli/test/fixtures/sfc_vue/package.json @@ -23,6 +23,7 @@ "@babel/preset-env": "^7.4.1", "@babel/preset-stage-2": "^7.0.0", "@babel/register": "^7.0.0", + "@storybook/semver": "^7.3.2", "autoprefixer": "^9.4.9", "babel-core": "^7.0.0-bridge.0", "babel-loader": "^8.0.5", @@ -42,7 +43,6 @@ "optimize-css-assets-webpack-plugin": "^2.0.0", "ora": "^3.2.0", "rimraf": "^2.6.3", - "@storybook/semver": "^7.3.2", "shelljs": "^0.8.3", "url-loader": "^1.1.2", "vue-loader": "15.7.0", diff --git a/lib/cli/tsconfig.json b/lib/cli/tsconfig.json index c4e40706894..d87605d41af 100644 --- a/lib/cli/tsconfig.json +++ b/lib/cli/tsconfig.json @@ -12,5 +12,5 @@ "noFallthroughCasesInSwitch": true }, "include": ["src/**/*"], - "exclude": ["src/**/template*"] + "exclude": ["src/**/template*", "src/frameworks/**/*"] } diff --git a/lib/cli/versions.json b/lib/cli/versions.json index 484f7588068..32702f5965b 100644 --- a/lib/cli/versions.json +++ b/lib/cli/versions.json @@ -1,17 +1,17 @@ { - "@storybook/angular": "6.0.0-beta.23", - "@storybook/aurelia": "6.0.0-beta.23", - "@storybook/ember": "6.0.0-beta.23", - "@storybook/html": "6.0.0-beta.23", - "@storybook/marionette": "6.0.0-beta.23", - "@storybook/marko": "6.0.0-beta.23", - "@storybook/mithril": "6.0.0-beta.23", - "@storybook/preact": "6.0.0-beta.23", - "@storybook/rax": "6.0.0-beta.23", - "@storybook/react": "6.0.0-beta.23", - "@storybook/riot": "6.0.0-beta.23", - "@storybook/server": "6.0.0-beta.23", - "@storybook/svelte": "6.0.0-beta.23", - "@storybook/vue": "6.0.0-beta.23", - "@storybook/web-components": "6.0.0-beta.23" + "@storybook/angular": "6.0.0-beta.25", + "@storybook/aurelia": "6.0.0-beta.25", + "@storybook/ember": "6.0.0-beta.25", + "@storybook/html": "6.0.0-beta.25", + "@storybook/marionette": "6.0.0-beta.25", + "@storybook/marko": "6.0.0-beta.25", + "@storybook/mithril": "6.0.0-beta.25", + "@storybook/preact": "6.0.0-beta.25", + "@storybook/rax": "6.0.0-beta.25", + "@storybook/react": "6.0.0-beta.25", + "@storybook/riot": "6.0.0-beta.25", + "@storybook/server": "6.0.0-beta.25", + "@storybook/svelte": "6.0.0-beta.25", + "@storybook/vue": "6.0.0-beta.25", + "@storybook/web-components": "6.0.0-beta.25" } \ No newline at end of file diff --git a/scripts/prepare.js b/scripts/prepare.js index 19e50ee6bcc..84c397565b5 100644 --- a/scripts/prepare.js +++ b/scripts/prepare.js @@ -34,9 +34,16 @@ function cleanup() { if (fs.existsSync(path.join(process.cwd(), 'dist'))) { const files = shell.find('dist').filter((filePath) => { // Do not remove folder - // And do not clean anything for @storybook/cli/dist/generators/**/template* because these are the template files + // And do not clean anything for: + // - @storybook/cli/dist/generators/**/template* + // - @storybook/cli/dist/frameworks/* + // because these are the template files // that will be copied to init SB on users' projects - if (fs.lstatSync(filePath).isDirectory() || /generators\/.+\/template.*/.test(filePath)) { + if ( + fs.lstatSync(filePath).isDirectory() || + /generators\/.+\/template.*/.test(filePath) || + /dist\/frameworks\/.*/.test(filePath) + ) { return false; }