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) => {