diff --git a/examples/vue-kitchen-sink/.babelrc b/examples/vue-kitchen-sink/.babelrc new file mode 100644 index 000000000000..bc4c4c4af5d2 --- /dev/null +++ b/examples/vue-kitchen-sink/.babelrc @@ -0,0 +1,7 @@ +{ + "presets": [ + ["env", { "modules": false }], + "vue" + ] +} + diff --git a/examples/vue-kitchen-sink/package.json b/examples/vue-kitchen-sink/package.json index c975f8e9c315..a30d633191b6 100644 --- a/examples/vue-kitchen-sink/package.json +++ b/examples/vue-kitchen-sink/package.json @@ -13,6 +13,7 @@ "babel-core": "^6.26.0", "babel-loader": "^7.1.2", "babel-preset-env": "^1.6.0", + "babel-preset-vue": "^1.2.1", "cross-env": "^3.0.0", "css-loader": "^0.28.7", "file-loader": "^0.11.2", diff --git a/examples/vue-kitchen-sink/src/stories/index.js b/examples/vue-kitchen-sink/src/stories/index.js index cbaea1df5144..82c9820433c8 100644 --- a/examples/vue-kitchen-sink/src/stories/index.js +++ b/examples/vue-kitchen-sink/src/stories/index.js @@ -1,3 +1,5 @@ +/* eslint-disable react/react-in-jsx-scope */ + import Vuex from 'vuex'; import { storiesOf } from '@storybook/vue'; import { action } from '@storybook/addon-actions'; @@ -68,6 +70,12 @@ storiesOf('Method for rendering Vue', module) action: linkTo('Button'), }, })) + .add('JSX', () => ({ + components: { MyButton }, + render() { + return MyButton rendered with JSX; + }, + })) .add('vuex + actions', () => ({ components: { MyButton }, template: 'with vuex: {{ $store.state.count }}', @@ -238,3 +246,5 @@ storiesOf('Addon Knobs', module) `, }; }); + +/* eslint-enable react/react-in-jsx-scope */ diff --git a/lib/cli/generators/SFC_VUE/index.js b/lib/cli/generators/SFC_VUE/index.js index 5b8fb90f0b66..68cd9665a991 100644 --- a/lib/cli/generators/SFC_VUE/index.js +++ b/lib/cli/generators/SFC_VUE/index.js @@ -7,7 +7,8 @@ module.exports = Promise.all([ latestVersion('@storybook/vue'), latestVersion('@storybook/addon-actions'), latestVersion('@storybook/addon-links'), -]).then(([storybookVersion, actionsVersion, linksVersion]) => { + latestVersion('babel-preset-vue'), +]).then(([storybookVersion, actionsVersion, linksVersion, babelPresetVersion]) => { mergeDirs(path.resolve(__dirname, 'template'), '.', 'overwrite'); const packageJson = helpers.getPackageJson(); @@ -16,10 +17,25 @@ module.exports = Promise.all([ packageJson.devDependencies['@storybook/vue'] = `^${storybookVersion}`; packageJson.devDependencies['@storybook/addon-actions'] = `^${actionsVersion}`; packageJson.devDependencies['@storybook/addon-links'] = `^${linksVersion}`; + packageJson.devDependencies['babel-preset-vue'] = `^${babelPresetVersion}`; packageJson.scripts = packageJson.scripts || {}; packageJson.scripts.storybook = 'start-storybook -p 6006'; packageJson.scripts['build-storybook'] = 'build-storybook'; helpers.writePackageJson(packageJson); + + const babelRc = helpers.getBabelRc() || { + presets: [['env', { modules: false }]], + }; + const hasPreset = babelRc.presets.find( + preset => + (Array.isArray(preset) && preset[0] === 'vue') || + (typeof preset === 'string' && preset === 'vue') + ); + if (!hasPreset) { + babelRc.presets.push('vue'); + } + + helpers.writeBabelRc(babelRc); }); diff --git a/lib/cli/generators/SFC_VUE/template/src/stories/index.js b/lib/cli/generators/SFC_VUE/template/src/stories/index.js index b1f09e9bb3d9..4fb3479a0b79 100644 --- a/lib/cli/generators/SFC_VUE/template/src/stories/index.js +++ b/lib/cli/generators/SFC_VUE/template/src/stories/index.js @@ -1,3 +1,5 @@ +/* eslint-disable react/react-in-jsx-scope */ + import { storiesOf } from '@storybook/vue'; import { action } from '@storybook/addon-actions'; import { linkTo } from '@storybook/addon-links'; @@ -17,8 +19,17 @@ storiesOf('Button', module) template: 'Hello Button', methods: { action: action('clicked') }, })) + .add('with JSX', () => ({ + components: { MyButton }, + render() { + return With JSX; + }, + methods: { action: linkTo('clicked') }, + })) .add('with some emoji', () => ({ components: { MyButton }, template: '😀 😎 👍 💯', methods: { action: action('clicked') }, })); + +/* eslint-enable react/react-in-jsx-scope */ diff --git a/lib/cli/generators/VUE/index.js b/lib/cli/generators/VUE/index.js index 5b8fb90f0b66..68cd9665a991 100644 --- a/lib/cli/generators/VUE/index.js +++ b/lib/cli/generators/VUE/index.js @@ -7,7 +7,8 @@ module.exports = Promise.all([ latestVersion('@storybook/vue'), latestVersion('@storybook/addon-actions'), latestVersion('@storybook/addon-links'), -]).then(([storybookVersion, actionsVersion, linksVersion]) => { + latestVersion('babel-preset-vue'), +]).then(([storybookVersion, actionsVersion, linksVersion, babelPresetVersion]) => { mergeDirs(path.resolve(__dirname, 'template'), '.', 'overwrite'); const packageJson = helpers.getPackageJson(); @@ -16,10 +17,25 @@ module.exports = Promise.all([ packageJson.devDependencies['@storybook/vue'] = `^${storybookVersion}`; packageJson.devDependencies['@storybook/addon-actions'] = `^${actionsVersion}`; packageJson.devDependencies['@storybook/addon-links'] = `^${linksVersion}`; + packageJson.devDependencies['babel-preset-vue'] = `^${babelPresetVersion}`; packageJson.scripts = packageJson.scripts || {}; packageJson.scripts.storybook = 'start-storybook -p 6006'; packageJson.scripts['build-storybook'] = 'build-storybook'; helpers.writePackageJson(packageJson); + + const babelRc = helpers.getBabelRc() || { + presets: [['env', { modules: false }]], + }; + const hasPreset = babelRc.presets.find( + preset => + (Array.isArray(preset) && preset[0] === 'vue') || + (typeof preset === 'string' && preset === 'vue') + ); + if (!hasPreset) { + babelRc.presets.push('vue'); + } + + helpers.writeBabelRc(babelRc); }); diff --git a/lib/cli/generators/VUE/template/stories/index.js b/lib/cli/generators/VUE/template/stories/index.js index b6f10120c7db..8435cbe3f227 100644 --- a/lib/cli/generators/VUE/template/stories/index.js +++ b/lib/cli/generators/VUE/template/stories/index.js @@ -1,3 +1,5 @@ +/* eslint-disable react/react-in-jsx-scope */ + import { storiesOf } from '@storybook/vue'; import { linkTo } from '@storybook/addon-links'; @@ -16,8 +18,17 @@ storiesOf('Button', module) template: 'Hello Button', methods: { action: linkTo('clicked') }, })) + .add('with JSX', () => ({ + components: { MyButton }, + render() { + return With JSX; + }, + methods: { action: linkTo('clicked') }, + })) .add('with some emoji', () => ({ components: { MyButton }, template: '😀 😎 👍 💯', methods: { action: linkTo('clicked') }, })); + +/* eslint-enable react/react-in-jsx-scope */ diff --git a/lib/cli/lib/helpers.js b/lib/cli/lib/helpers.js index 0288cd9185be..ceeb171d2018 100644 --- a/lib/cli/lib/helpers.js +++ b/lib/cli/lib/helpers.js @@ -22,6 +22,23 @@ exports.writePackageJson = function writePackageJson(packageJson) { fs.writeFileSync(packageJsonPath, content, 'utf8'); }; +exports.getBabelRc = function getBabelRc() { + const babelRcPath = path.resolve('.babelrc'); + if (!fs.existsSync(babelRcPath)) { + return false; + } + + const babelRcContent = fs.readFileSync(babelRcPath, 'utf8'); + return JSON.parse(babelRcContent); +}; + +exports.writeBabelRc = function writeBabelRc(babelRc) { + const content = `${JSON.stringify(babelRc, null, 2)}\n`; + const babelRcPath = path.resolve('.babelrc'); + + fs.writeFileSync(babelRcPath, content, 'utf8'); +}; + exports.commandLog = function commandLog(message) { process.stdout.write(chalk.cyan(' • ') + message); const done = (errorMessage, errorInfo) => {