diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000000..398ff439977d --- /dev/null +++ b/.eslintignore @@ -0,0 +1,4 @@ +dist +build +coverage +node_modules diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 521bb1321c05..000000000000 --- a/.eslintrc +++ /dev/null @@ -1,27 +0,0 @@ -{ - "extends": "airbnb", - "rules": { - # We use _ to define private variables and methods in clases - "no-underscore-dangle": 0, - # This seems to be buggy we don't want eslint to check this - "import/no-extraneous-dependencies": 0, - # This is a depricated rule. So we turned off it. - "react/require-extension": 0, - # We can write JSX in anyfile we want. - "react/jsx-filename-extension": 0, - # We don't like this rule. - "arrow-body-style": 0, - # We don't like this rule. We write arrow functions only when we needed. - "prefer-arrow-callback": 0, - # We don't need to write function names always. - "func-names": 0, - # propTypes can be object - "react/forbid-prop-types": 0, - }, - "parserOptions": { - "ecmaVersion": 6, - "ecmaFeatures": { - "experimentalObjectRestSpread": true - } - }, -} diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 000000000000..ea25eb04850a --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,28 @@ +module.exports = { + extends: [ + './node_modules/eslint-config-airbnb-base/rules/es6.js', + ], + plugins: [ + 'prettier', + ], + parser: 'babel-eslint', + parserOptions: { + sourceType: 'module', + }, + env: { + es6: true, + node: true, + }, + rules: { + strict: 0, + 'prettier/prettier': ['warn', { + printWidth: 100, + tabWidth: 2, + bracketSpacing: true, + trailingComma: 'all', + singleQuote: true, + }], + quotes: ['warn', 'single'], + 'arrow-parens': ['warn', 'as-needed'], + }, +} diff --git a/.gitignore b/.gitignore index 206eafec8112..b2bd0422bcc4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,8 @@ node_modules .idea npm-shrinkwrap.json dist +.tern-port +*.DS_Store +*.lerna_backup +build +yarn.lock diff --git a/.npmignore b/.npmignore index 329fc8d67ad9..02ba1793bbe8 100644 --- a/.npmignore +++ b/.npmignore @@ -1,3 +1 @@ -docs -src .babelrc diff --git a/.travis.yml b/.travis.yml index 24a8ab9d2958..e906c10cbae3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,14 @@ language: node_js +cache: + yarn: true + directories: + - node_modules +notifications: + email: false node_js: - - "5" + - "node" +before_install: ./scripts/travis/before_install.sh +after_success: ./scripts/travis/after_success.sh +script: npm run lint && npm run test +git: + depth: 1 diff --git a/README.md b/README.md index 17d1495981ec..1ce63deb45d3 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,8 @@ -# React Storybook [![Build Status](https://travis-ci.org/storybooks/react-storybook.svg?branch=master)](https://travis-ci.org/storybooks/react-storybook) [![npm version](https://badge.fury.io/js/%40kadira%2Fstorybook.svg)](https://badge.fury.io/js/%40kadira%2Fstorybook) [![Storybook Slack](https://storybooks-slackin.herokuapp.com/badge.svg)](https://storybooks-slackin.herokuapp.com/) +# storybooks mono repo -React Storybook is a UI development environment for your React components. With it, you can visualize different states of your UI components and develop them interactively. +[![Greenkeeper badge](https://badges.greenkeeper.io/storybooks/mono.svg)](https://greenkeeper.io/) +[![Build Status](https://travis-ci.org/storybooks/mono.svg?branch=master)](https://travis-ci.org/storybooks/mono) +[![CodeFactor](https://www.codefactor.io/repository/github/storybooks/mono/badge)](https://www.codefactor.io/repository/github/storybooks/mono) +[![BCH compliance](https://bettercodehub.com/edge/badge/storybooks/mono)](https://bettercodehub.com/results/storybooks/mono) -![React Storybook Screenshot](docs/demo.gif) - -React Storybook runs outside of your app. So you can develop UI components in isolation without worrying about app specific dependencies and requirements. - -## Getting Started - -```js -npm i -g getstorybook -cd my-react-app -getstorybook -``` - -For more information visit: https://getstorybook.io - ---- - -React Storybook also comes with a lot of [addons](https://getstorybook.io/docs/addons/introduction) and a great API to customize as you wish. You can also build a [static version](https://getstorybook.io/docs/basics/exporting-storybook) of your storybook and deploy it anywhere you want. - -Here are some featured storybooks that you can reference to see how Storybook works: - - * [Demo of React Dates](http://airbnb.io/react-dates/) - [source](https://github.com/airbnb/react-dates) - * [Demo of React Native Web](http://necolas.github.io/react-native-web/storybook/) - [source](https://github.com/necolas/react-native-web) - -## Docs - -* [Basics](https://getstorybook.io/docs/basics/introduction) -* [Configurations](https://getstorybook.io/docs/configurations/default-config) -* [Addons](https://getstorybook.io/docs/addons/introduction) +experiment of a mono repo diff --git a/dist/client/index.js b/dist/client/index.js deleted file mode 100644 index 6a606601d81d..000000000000 --- a/dist/client/index.js +++ /dev/null @@ -1,38 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.linkTo = exports.action = exports.getStorybook = exports.configure = exports.addDecorator = exports.setAddon = exports.storiesOf = undefined; - -var _storybookAddonActions = require('@kadira/storybook-addon-actions'); - -Object.defineProperty(exports, 'action', { - enumerable: true, - get: function get() { - return _storybookAddonActions.action; - } -}); - -var _storybookAddonLinks = require('@kadira/storybook-addon-links'); - -Object.defineProperty(exports, 'linkTo', { - enumerable: true, - get: function get() { - return _storybookAddonLinks.linkTo; - } -}); - -var _preview = require('./preview'); - -var previewApi = _interopRequireWildcard(_preview); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -var storiesOf = exports.storiesOf = previewApi.storiesOf; -var setAddon = exports.setAddon = previewApi.setAddon; -var addDecorator = exports.addDecorator = previewApi.addDecorator; -var configure = exports.configure = previewApi.configure; -var getStorybook = exports.getStorybook = previewApi.getStorybook; - -// NOTE export these to keep backwards compatibility \ No newline at end of file diff --git a/dist/client/manager/index.js b/dist/client/manager/index.js deleted file mode 100644 index 5e5c9e65029f..000000000000 --- a/dist/client/manager/index.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; - -var _storybookUi = require('@kadira/storybook-ui'); - -var _storybookUi2 = _interopRequireDefault(_storybookUi); - -var _provider = require('./provider'); - -var _provider2 = _interopRequireDefault(_provider); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* global document */ - -var rootEl = document.getElementById('root'); -(0, _storybookUi2.default)(rootEl, new _provider2.default()); \ No newline at end of file diff --git a/dist/client/manager/preview.js b/dist/client/manager/preview.js deleted file mode 100644 index 4fb70109ba6a..000000000000 --- a/dist/client/manager/preview.js +++ /dev/null @@ -1,80 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); - -var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require('babel-runtime/helpers/createClass'); - -var _createClass3 = _interopRequireDefault(_createClass2); - -var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); - -var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); - -var _inherits2 = require('babel-runtime/helpers/inherits'); - -var _inherits3 = _interopRequireDefault(_inherits2); - -var _react = require('react'); - -var _react2 = _interopRequireDefault(_react); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var iframeStyle = { - width: '100%', - height: '100%', - border: 0, - margin: 0, - padding: 0 -}; - -var Preview = function (_Component) { - (0, _inherits3.default)(Preview, _Component); - - function Preview() { - (0, _classCallCheck3.default)(this, Preview); - return (0, _possibleConstructorReturn3.default)(this, (Preview.__proto__ || (0, _getPrototypeOf2.default)(Preview)).apply(this, arguments)); - } - - (0, _createClass3.default)(Preview, [{ - key: 'shouldComponentUpdate', - - /* eslint-disable class-methods-use-this */ - value: function shouldComponentUpdate() { - // When the manager is re-rendered, due to changes in the layout (going full screen / changing - // addon panel to right) Preview section will update. If its re-rendered the whole html page - // inside the html is re-rendered making the story to re-mount. - // We dont have to re-render this component for any reason since changes are communicated to - // story using the channel and necessary changes are done by it. - return false; - } - /* eslint-enable class-methods-use-this */ - - }, { - key: 'render', - value: function render() { - return _react2.default.createElement('iframe', { - id: 'storybook-preview-iframe', - style: iframeStyle, - src: this.props.url - }); - } - }]); - return Preview; -}(_react.Component); - -Preview.propTypes = { - url: _react2.default.PropTypes.string -}; - -exports.default = Preview; \ No newline at end of file diff --git a/dist/client/manager/provider.js b/dist/client/manager/provider.js deleted file mode 100644 index a73cf6118e6d..000000000000 --- a/dist/client/manager/provider.js +++ /dev/null @@ -1,112 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of'); - -var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require('babel-runtime/helpers/createClass'); - -var _createClass3 = _interopRequireDefault(_createClass2); - -var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn'); - -var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2); - -var _inherits2 = require('babel-runtime/helpers/inherits'); - -var _inherits3 = _interopRequireDefault(_inherits2); - -var _qs = require('qs'); - -var _qs2 = _interopRequireDefault(_qs); - -var _react = require('react'); - -var _react2 = _interopRequireDefault(_react); - -var _storybookUi = require('@kadira/storybook-ui'); - -var _storybookAddons = require('@kadira/storybook-addons'); - -var _storybookAddons2 = _interopRequireDefault(_storybookAddons); - -var _storybookChannelPostmsg = require('@kadira/storybook-channel-postmsg'); - -var _storybookChannelPostmsg2 = _interopRequireDefault(_storybookChannelPostmsg); - -var _preview = require('./preview'); - -var _preview2 = _interopRequireDefault(_preview); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* global location */ -/* eslint class-methods-use-this: 0 */ - -var ReactProvider = function (_Provider) { - (0, _inherits3.default)(ReactProvider, _Provider); - - function ReactProvider() { - (0, _classCallCheck3.default)(this, ReactProvider); - - var _this = (0, _possibleConstructorReturn3.default)(this, (ReactProvider.__proto__ || (0, _getPrototypeOf2.default)(ReactProvider)).call(this)); - - _this.channel = (0, _storybookChannelPostmsg2.default)({ page: 'manager' }); - _storybookAddons2.default.setChannel(_this.channel); - return _this; - } - - (0, _createClass3.default)(ReactProvider, [{ - key: 'getPanels', - value: function getPanels() { - return _storybookAddons2.default.getPanels(); - } - }, { - key: 'renderPreview', - value: function renderPreview(selectedKind, selectedStory) { - var queryParams = { - selectedKind: selectedKind, - selectedStory: selectedStory - }; - - // Add the react-perf query string to the iframe if that present. - if (/react_perf/.test(location.search)) { - queryParams.react_perf = '1'; - } - - var queryString = _qs2.default.stringify(queryParams); - var url = 'iframe.html?' + queryString; - return _react2.default.createElement(_preview2.default, { url: url }); - } - }, { - key: 'handleAPI', - value: function handleAPI(api) { - var _this2 = this; - - api.onStory(function (kind, story) { - _this2.channel.emit('setCurrentStory', { kind: kind, story: story }); - }); - this.channel.on('setStories', function (data) { - api.setStories(data.stories); - }); - this.channel.on('selectStory', function (data) { - api.selectStory(data.kind, data.story); - }); - this.channel.on('applyShortcut', function (data) { - api.handleShortcut(data.event); - }); - _storybookAddons2.default.loadAddons(api); - } - }]); - return ReactProvider; -}(_storybookUi.Provider); - -exports.default = ReactProvider; \ No newline at end of file diff --git a/dist/client/preview/actions.js b/dist/client/preview/actions.js deleted file mode 100644 index 8b26a0e56a34..000000000000 --- a/dist/client/preview/actions.js +++ /dev/null @@ -1,43 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.setInitialStory = setInitialStory; -exports.setError = setError; -exports.clearError = clearError; -exports.selectStory = selectStory; -var types = exports.types = { - SET_ERROR: 'PREVIEW_SET_ERROR', - CLEAR_ERROR: 'PREVIEW_CLEAR_ERROR', - SELECT_STORY: 'PREVIEW_SELECT_STORY', - SET_INITIAL_STORY: 'PREVIEW_SET_INITIAL_STORY' -}; - -function setInitialStory(storyKindList) { - return { - type: types.SET_INITIAL_STORY, - storyKindList: storyKindList - }; -} - -function setError(error) { - return { - type: types.SET_ERROR, - error: error - }; -} - -function clearError() { - return { - type: types.CLEAR_ERROR - }; -} - -function selectStory(kind, story) { - return { - type: types.SELECT_STORY, - kind: kind, - story: story - }; -} \ No newline at end of file diff --git a/dist/client/preview/client_api.js b/dist/client/preview/client_api.js deleted file mode 100644 index 783ed4318eff..000000000000 --- a/dist/client/preview/client_api.js +++ /dev/null @@ -1,130 +0,0 @@ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _toConsumableArray2 = require("babel-runtime/helpers/toConsumableArray"); - -var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); - -var _keys = require("babel-runtime/core-js/object/keys"); - -var _keys2 = _interopRequireDefault(_keys); - -var _extends2 = require("babel-runtime/helpers/extends"); - -var _extends3 = _interopRequireDefault(_extends2); - -var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require("babel-runtime/helpers/createClass"); - -var _createClass3 = _interopRequireDefault(_createClass2); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var ClientApi = function () { - function ClientApi(_ref) { - var channel = _ref.channel, - storyStore = _ref.storyStore; - (0, _classCallCheck3.default)(this, ClientApi); - - // channel can be null when running in node - // always check whether channel is available - this._channel = channel; - this._storyStore = storyStore; - this._addons = {}; - this._globalDecorators = []; - } - - (0, _createClass3.default)(ClientApi, [{ - key: "setAddon", - value: function setAddon(addon) { - this._addons = (0, _extends3.default)({}, this._addons, addon); - } - }, { - key: "addDecorator", - value: function addDecorator(decorator) { - this._globalDecorators.push(decorator); - } - }, { - key: "clearDecorators", - value: function clearDecorators() { - this._globalDecorators = []; - } - }, { - key: "storiesOf", - value: function storiesOf(kind, m) { - var _this = this; - - if (m && m.hot) { - m.hot.dispose(function () { - _this._storyStore.removeStoryKind(kind); - }); - } - - var localDecorators = []; - var api = { - kind: kind - }; - - // apply addons - (0, _keys2.default)(this._addons).forEach(function (name) { - var addon = _this._addons[name]; - api[name] = function () { - for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - addon.apply(api, args); - return api; - }; - }); - - api.add = function (storyName, getStory) { - // Wrap the getStory function with each decorator. The first - // decorator will wrap the story function. The second will - // wrap the first decorator and so on. - var decorators = [].concat(localDecorators, (0, _toConsumableArray3.default)(_this._globalDecorators)); - - var fn = decorators.reduce(function (decorated, decorator) { - return function (context) { - return decorator(function () { - return decorated(context); - }, context); - }; - }, getStory); - - // Add the fully decorated getStory function. - _this._storyStore.addStory(kind, storyName, fn); - return api; - }; - - api.addDecorator = function (decorator) { - localDecorators.push(decorator); - return api; - }; - - return api; - } - }, { - key: "getStorybook", - value: function getStorybook() { - var _this2 = this; - - return this._storyStore.getStoryKinds().map(function (kind) { - var stories = _this2._storyStore.getStories(kind).map(function (name) { - var render = _this2._storyStore.getStory(kind, name); - return { name: name, render: render }; - }); - return { kind: kind, stories: stories }; - }); - } - }]); - return ClientApi; -}(); - -exports.default = ClientApi; \ No newline at end of file diff --git a/dist/client/preview/config_api.js b/dist/client/preview/config_api.js deleted file mode 100644 index 5d3536a05e2b..000000000000 --- a/dist/client/preview/config_api.js +++ /dev/null @@ -1,100 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require('babel-runtime/helpers/createClass'); - -var _createClass3 = _interopRequireDefault(_createClass2); - -var _actions = require('./actions'); - -var _ = require('./'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -/* globals location */ - -var ConfigApi = function () { - function ConfigApi(_ref) { - var channel = _ref.channel, - storyStore = _ref.storyStore, - reduxStore = _ref.reduxStore; - (0, _classCallCheck3.default)(this, ConfigApi); - - // channel can be null when running in node - // always check whether channel is available - this._channel = channel; - this._storyStore = storyStore; - this._reduxStore = reduxStore; - } - - (0, _createClass3.default)(ConfigApi, [{ - key: '_renderMain', - value: function _renderMain(loaders) { - if (loaders) loaders(); - - var stories = this._storyStore.dumpStoryBook(); - // send to the parent frame. - this._channel.emit('setStories', { stories: stories }); - - // clear the error if exists. - this._reduxStore.dispatch((0, _actions.clearError)()); - this._reduxStore.dispatch((0, _actions.setInitialStory)(stories)); - } - }, { - key: '_renderError', - value: function _renderError(e) { - var stack = e.stack, - message = e.message; - - var error = { stack: stack, message: message }; - this._reduxStore.dispatch((0, _actions.setError)(error)); - } - }, { - key: 'configure', - value: function configure(loaders, module) { - var _this = this; - - var render = function render() { - try { - _this._renderMain(loaders); - } catch (error) { - if (module.hot && module.hot.status() === 'apply') { - // We got this issue, after webpack fixed it and applying it. - // Therefore error message is displayed forever even it's being fixed. - // So, we'll detect it reload the page. - location.reload(); - } else { - // If we are accessing the site, but the error is not fixed yet. - // There we can render the error. - _this._renderError(error); - } - } - }; - - if (module.hot) { - module.hot.accept(function () { - setTimeout(render); - }); - module.hot.dispose(function () { - (0, _.clearDecorators)(); - }); - } - - if (this._channel) { - render(); - } else { - loaders(); - } - } - }]); - return ConfigApi; -}(); - -exports.default = ConfigApi; \ No newline at end of file diff --git a/dist/client/preview/error_display.js b/dist/client/preview/error_display.js deleted file mode 100644 index f95c22f6f083..000000000000 --- a/dist/client/preview/error_display.js +++ /dev/null @@ -1,65 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _react = require('react'); - -var _react2 = _interopRequireDefault(_react); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var mainStyle = { - position: 'fixed', - top: 0, - bottom: 0, - left: 0, - right: 0, - padding: 20, - backgroundColor: 'rgb(187, 49, 49)', - color: '#FFF', - WebkitFontSmoothing: 'antialiased' -}; - -var headingStyle = { - fontSize: 20, - fontWeight: 600, - letterSpacing: 0.2, - margin: '10px 0', - fontFamily: '\n -apple-system, ".SFNSText-Regular", "San Francisco", Roboto, "Segoe UI",\n "Helvetica Neue", "Lucida Grande", sans-serif\n ' -}; - -var codeStyle = { - fontSize: 14, - width: '100vw', - overflow: 'auto' -}; - -var ErrorDisplay = function ErrorDisplay(_ref) { - var error = _ref.error; - return _react2.default.createElement( - 'div', - { style: mainStyle }, - _react2.default.createElement( - 'div', - { style: headingStyle }, - error.message - ), - _react2.default.createElement( - 'pre', - { style: codeStyle }, - _react2.default.createElement( - 'code', - null, - error.stack - ) - ) - ); -}; - -ErrorDisplay.propTypes = { - error: _react2.default.PropTypes.object.isRequired -}; - -exports.default = ErrorDisplay; \ No newline at end of file diff --git a/dist/client/preview/index.js b/dist/client/preview/index.js deleted file mode 100644 index 9a2ca74f9cab..000000000000 --- a/dist/client/preview/index.js +++ /dev/null @@ -1,93 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.configure = exports.getStorybook = exports.clearDecorators = exports.addDecorator = exports.setAddon = exports.storiesOf = undefined; - -var _assign = require('babel-runtime/core-js/object/assign'); - -var _assign2 = _interopRequireDefault(_assign); - -var _redux = require('redux'); - -var _storybookAddons = require('@kadira/storybook-addons'); - -var _storybookAddons2 = _interopRequireDefault(_storybookAddons); - -var _storybookChannelPostmsg = require('@kadira/storybook-channel-postmsg'); - -var _storybookChannelPostmsg2 = _interopRequireDefault(_storybookChannelPostmsg); - -var _qs = require('qs'); - -var _qs2 = _interopRequireDefault(_qs); - -var _story_store = require('./story_store'); - -var _story_store2 = _interopRequireDefault(_story_store); - -var _client_api = require('./client_api'); - -var _client_api2 = _interopRequireDefault(_client_api); - -var _config_api = require('./config_api'); - -var _config_api2 = _interopRequireDefault(_config_api); - -var _render = require('./render'); - -var _render2 = _interopRequireDefault(_render); - -var _init = require('./init'); - -var _init2 = _interopRequireDefault(_init); - -var _actions = require('./actions'); - -var _reducer = require('./reducer'); - -var _reducer2 = _interopRequireDefault(_reducer); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// check whether we're running on node/browser -var _global = global, - navigator = _global.navigator; /* global window */ - -var isBrowser = navigator && navigator.userAgent !== 'storyshots' && !navigator.userAgent.includes('Node.js'); - -var storyStore = new _story_store2.default(); -var reduxStore = (0, _redux.createStore)(_reducer2.default); -var context = { storyStore: storyStore, reduxStore: reduxStore }; - -if (isBrowser) { - var queryParams = _qs2.default.parse(window.location.search.substring(1)); - var channel = (0, _storybookChannelPostmsg2.default)({ page: 'preview' }); - channel.on('setCurrentStory', function (data) { - reduxStore.dispatch((0, _actions.selectStory)(data.kind, data.story)); - }); - (0, _assign2.default)(context, { channel: channel, window: window, queryParams: queryParams }); - _storybookAddons2.default.setChannel(channel); - (0, _init2.default)(context); -} - -var clientApi = new _client_api2.default(context); -var configApi = new _config_api2.default(context); - -// do exports -var storiesOf = exports.storiesOf = clientApi.storiesOf.bind(clientApi); -var setAddon = exports.setAddon = clientApi.setAddon.bind(clientApi); -var addDecorator = exports.addDecorator = clientApi.addDecorator.bind(clientApi); -var clearDecorators = exports.clearDecorators = clientApi.clearDecorators.bind(clientApi); -var getStorybook = exports.getStorybook = clientApi.getStorybook.bind(clientApi); -var configure = exports.configure = configApi.configure.bind(configApi); - -// initialize the UI -var renderUI = function renderUI() { - if (isBrowser) { - (0, _render2.default)(context); - } -}; - -reduxStore.subscribe(renderUI); \ No newline at end of file diff --git a/dist/client/preview/init.js b/dist/client/preview/init.js deleted file mode 100644 index de3bf32d9acd..000000000000 --- a/dist/client/preview/init.js +++ /dev/null @@ -1,33 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -exports.default = function (context) { - var queryParams = context.queryParams, - reduxStore = context.reduxStore, - window = context.window, - channel = context.channel; - // set the story if correct params are loaded via the URL. - - if (queryParams.selectedKind) { - reduxStore.dispatch((0, _actions.selectStory)(queryParams.selectedKind, queryParams.selectedStory)); - } - - // Handle keyEvents and pass them to the parent. - window.onkeydown = function (e) { - var parsedEvent = (0, _key_events2.default)(e); - if (parsedEvent) { - channel.emit('applyShortcut', { event: parsedEvent }); - } - }; -}; - -var _key_events = require('@kadira/storybook-ui/dist/libs/key_events'); - -var _key_events2 = _interopRequireDefault(_key_events); - -var _actions = require('./actions'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/dist/client/preview/reducer.js b/dist/client/preview/reducer.js deleted file mode 100644 index e17517696086..000000000000 --- a/dist/client/preview/reducer.js +++ /dev/null @@ -1,59 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends2 = require('babel-runtime/helpers/extends'); - -var _extends3 = _interopRequireDefault(_extends2); - -exports.default = reducer; - -var _actions = require('./actions'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function reducer() { - var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - var action = arguments[1]; - - switch (action.type) { - case _actions.types.CLEAR_ERROR: - { - return (0, _extends3.default)({}, state, { - error: null - }); - } - - case _actions.types.SET_ERROR: - { - return (0, _extends3.default)({}, state, { - error: action.error - }); - } - - case _actions.types.SELECT_STORY: - { - return (0, _extends3.default)({}, state, { - selectedKind: action.kind, - selectedStory: action.story - }); - } - - case _actions.types.SET_INITIAL_STORY: - { - var newState = (0, _extends3.default)({}, state); - var storyKindList = action.storyKindList; - - if (!newState.selectedKind && storyKindList.length > 0) { - newState.selectedKind = storyKindList[0].kind; - newState.selectedStory = storyKindList[0].stories[0]; - } - return newState; - } - - default: - return state; - } -} \ No newline at end of file diff --git a/dist/client/preview/render.js b/dist/client/preview/render.js deleted file mode 100644 index 9ab679f40124..000000000000 --- a/dist/client/preview/render.js +++ /dev/null @@ -1,145 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _taggedTemplateLiteral2 = require('babel-runtime/helpers/taggedTemplateLiteral'); - -var _taggedTemplateLiteral3 = _interopRequireDefault(_taggedTemplateLiteral2); - -var _templateObject = (0, _taggedTemplateLiteral3.default)(['\n Did you forget to return the React element from the story?\n Use "() => ()" or "() => { return ; }" when defining the story.\n '], ['\n Did you forget to return the React element from the story?\n Use "() => ()" or "() => { return ; }" when defining the story.\n ']), - _templateObject2 = (0, _taggedTemplateLiteral3.default)(['\n Seems like you are not returning a correct React element form the story.\n Could you double check that?\n '], ['\n Seems like you are not returning a correct React element form the story.\n Could you double check that?\n ']); /* global document */ - -exports.renderError = renderError; -exports.renderException = renderException; -exports.renderMain = renderMain; -exports.default = renderPreview; - -var _react = require('react'); - -var _react2 = _interopRequireDefault(_react); - -var _reactDom = require('react-dom'); - -var _reactDom2 = _interopRequireDefault(_reactDom); - -var _commonTags = require('common-tags'); - -var _error_display = require('./error_display'); - -var _error_display2 = _interopRequireDefault(_error_display); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// check whether we're running on node/browser -var isBrowser = typeof window !== 'undefined'; - -var logger = console; - -var rootEl = null; -var previousKind = ''; -var previousStory = ''; - -if (isBrowser) { - rootEl = document.getElementById('root'); -} - -function renderError(error) { - var properError = new Error(error.title); - properError.stack = error.description; - - var redBox = _react2.default.createElement(_error_display2.default, { error: properError }); - _reactDom2.default.render(redBox, rootEl); -} - -function renderException(error) { - // We always need to render redbox in the mainPage if we get an error. - // Since this is an error, this affects to the main page as well. - var realError = new Error(error.message); - realError.stack = error.stack; - var redBox = _react2.default.createElement(_error_display2.default, { error: realError }); - _reactDom2.default.render(redBox, rootEl); - - // Log the stack to the console. So, user could check the source code. - logger.error(error.stack); -} - -function renderMain(data, storyStore) { - if (storyStore.size() === 0) return null; - - var NoPreview = function NoPreview() { - return _react2.default.createElement( - 'p', - null, - 'No Preview Available!' - ); - }; - var noPreview = _react2.default.createElement(NoPreview, null); - var selectedKind = data.selectedKind, - selectedStory = data.selectedStory; - - - var story = storyStore.getStory(selectedKind, selectedStory); - if (!story) { - _reactDom2.default.render(noPreview, rootEl); - return null; - } - - // Unmount the previous story only if selectedKind or selectedStory has changed. - // renderMain() gets executed after each action. Actions will cause the whole - // story to re-render without this check. - // https://github.com/storybooks/react-storybook/issues/116 - if (selectedKind !== previousKind || previousStory !== selectedStory) { - // We need to unmount the existing set of components in the DOM node. - // Otherwise, React may not recrease instances for every story run. - // This could leads to issues like below: - // https://github.com/storybooks/react-storybook/issues/81 - previousKind = selectedKind; - previousStory = selectedStory; - _reactDom2.default.unmountComponentAtNode(rootEl); - } - - var context = { - kind: selectedKind, - story: selectedStory - }; - - var element = story(context); - - if (!element) { - var error = { - title: 'Expecting a React element from the story: "' + selectedStory + '" of "' + selectedKind + '".', - /* eslint-disable */ - description: (0, _commonTags.stripIndents)(_templateObject) - }; - return renderError(error); - } - - if (element.type === undefined) { - var _error = { - title: 'Expecting a valid React element from the story: "' + selectedStory + '" of "' + selectedKind + '".', - description: (0, _commonTags.stripIndents)(_templateObject2) - }; - return renderError(_error); - } - - _reactDom2.default.render(element, rootEl); - return null; -} - -function renderPreview(_ref) { - var reduxStore = _ref.reduxStore, - storyStore = _ref.storyStore; - - var state = reduxStore.getState(); - if (state.error) { - return renderException(state.error); - } - - try { - return renderMain(state, storyStore); - } catch (ex) { - return renderException(ex); - } -} diff --git a/dist/client/preview/story_store.js b/dist/client/preview/story_store.js deleted file mode 100644 index db90c14d64ed..000000000000 --- a/dist/client/preview/story_store.js +++ /dev/null @@ -1,143 +0,0 @@ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _keys = require("babel-runtime/core-js/object/keys"); - -var _keys2 = _interopRequireDefault(_keys); - -var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); - -var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); - -var _createClass2 = require("babel-runtime/helpers/createClass"); - -var _createClass3 = _interopRequireDefault(_createClass2); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var cnt = 0; - -function getId() { - cnt += 1; - return cnt; -} - -var StoryStore = function () { - function StoryStore() { - (0, _classCallCheck3.default)(this, StoryStore); - - this._data = {}; - } - - (0, _createClass3.default)(StoryStore, [{ - key: "addStory", - value: function addStory(kind, name, fn) { - if (!this._data[kind]) { - this._data[kind] = { - kind: kind, - index: getId(), - stories: {} - }; - } - - this._data[kind].stories[name] = { - name: name, - index: getId(), - fn: fn - }; - } - }, { - key: "getStoryKinds", - value: function getStoryKinds() { - var _this = this; - - return (0, _keys2.default)(this._data).map(function (key) { - return _this._data[key]; - }).filter(function (kind) { - return (0, _keys2.default)(kind.stories).length > 0; - }).sort(function (info1, info2) { - return info1.index - info2.index; - }).map(function (info) { - return info.kind; - }); - } - }, { - key: "getStories", - value: function getStories(kind) { - var _this2 = this; - - if (!this._data[kind]) { - return []; - } - - return (0, _keys2.default)(this._data[kind].stories).map(function (name) { - return _this2._data[kind].stories[name]; - }).sort(function (info1, info2) { - return info1.index - info2.index; - }).map(function (info) { - return info.name; - }); - } - }, { - key: "getStory", - value: function getStory(kind, name) { - var storiesKind = this._data[kind]; - if (!storiesKind) { - return null; - } - - var storyInfo = storiesKind.stories[name]; - if (!storyInfo) { - return null; - } - - return storyInfo.fn; - } - }, { - key: "removeStoryKind", - value: function removeStoryKind(kind) { - this._data[kind].stories = {}; - } - }, { - key: "hasStoryKind", - value: function hasStoryKind(kind) { - return Boolean(this._data[kind]); - } - }, { - key: "hasStory", - value: function hasStory(kind, name) { - return Boolean(this.getStory(kind, name)); - } - }, { - key: "dumpStoryBook", - value: function dumpStoryBook() { - var _this3 = this; - - var data = this.getStoryKinds().map(function (kind) { - return { kind: kind, stories: _this3.getStories(kind) }; - }); - - return data; - } - }, { - key: "size", - value: function size() { - return (0, _keys2.default)(this._data).length; - } - }, { - key: "clean", - value: function clean() { - var _this4 = this; - - this.getStoryKinds().forEach(function (kind) { - return delete _this4._data[kind]; - }); - } - }]); - return StoryStore; -}(); - -exports.default = StoryStore; \ No newline at end of file diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 000000000000..0f87e07fd253 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,131 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Channel = function () { + function Channel(_ref) { + var transport = _ref.transport; + + _classCallCheck(this, Channel); + + this._sender = this._randomId(); + this._transport = transport; + this._transport.setHandler(this._handleEvent.bind(this)); + this._listeners = {}; + } + + _createClass(Channel, [{ + key: "addListener", + value: function addListener(type, listener) { + this.on(type, listener); + } + }, { + key: "emit", + value: function emit(type) { + for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + var event = { type: type, args: args, from: this._sender }; + this._transport.send(event); + } + }, { + key: "eventNames", + value: function eventNames() { + return Object.keys(this._listeners); + } + }, { + key: "listenerCount", + value: function listenerCount(type) { + var listeners = this._listeners[type]; + return listeners ? listeners.length : 0; + } + }, { + key: "listeners", + value: function listeners(type) { + return this._listeners[type]; + } + }, { + key: "on", + value: function on(type, listener) { + this._listeners[type] = this._listeners[type] || []; + this._listeners[type].push(listener); + } + }, { + key: "once", + value: function once(type, listener) { + var onceListener = this._onceListener(type, listener); + this.on(type, onceListener); + } + }, { + key: "prependListener", + value: function prependListener(type, listener) { + this._listeners[type] = this._listeners[type] || []; + this._listeners[type].unshift(listener); + } + }, { + key: "prependOnceListener", + value: function prependOnceListener(type, listener) { + var onceListener = this._onceListener(type, listener); + this.prependListener(type, onceListener); + } + }, { + key: "removeAllListeners", + value: function removeAllListeners(type) { + if (!type) { + this._listeners = {}; + } else if (this._listeners[type]) { + delete this._listeners[type]; + } + } + }, { + key: "removeListener", + value: function removeListener(type, listener) { + var listeners = this._listeners[type]; + if (listeners) { + this._listeners[type] = listeners.filter(function (l) { + return l !== listener; + }); + } + } + }, { + key: "_randomId", + value: function _randomId() { + // generates a random 13 character string + return Math.random().toString(16).slice(2); + } + }, { + key: "_handleEvent", + value: function _handleEvent(event) { + var listeners = this._listeners[event.type]; + if (event.from !== this._sender && listeners) { + listeners.forEach(function (fn) { + return fn.apply(undefined, _toConsumableArray(event.args)); + }); + } + } + }, { + key: "_onceListener", + value: function _onceListener(type, listener) { + var _this = this; + + var onceListener = function onceListener() { + _this.removeListener(type, onceListener); + return listener.apply(undefined, arguments); + }; + return onceListener; + } + }]); + + return Channel; +}(); + +exports.default = Channel; \ No newline at end of file diff --git a/dist/server/addons.js b/dist/server/addons.js deleted file mode 100644 index 652f0da2eef3..000000000000 --- a/dist/server/addons.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -require('@kadira/storybook-addon-actions/register'); - -require('@kadira/storybook-addon-links/register'); \ No newline at end of file diff --git a/dist/server/build.js b/dist/server/build.js deleted file mode 100644 index 75f3889ddb05..000000000000 --- a/dist/server/build.js +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -var _extends2 = require('babel-runtime/helpers/extends'); - -var _extends3 = _interopRequireDefault(_extends2); - -var _webpack = require('webpack'); - -var _webpack2 = _interopRequireDefault(_webpack); - -var _commander = require('commander'); - -var _commander2 = _interopRequireDefault(_commander); - -var _path = require('path'); - -var _path2 = _interopRequireDefault(_path); - -var _fs = require('fs'); - -var _fs2 = _interopRequireDefault(_fs); - -var _chalk = require('chalk'); - -var _chalk2 = _interopRequireDefault(_chalk); - -var _shelljs = require('shelljs'); - -var _shelljs2 = _interopRequireDefault(_shelljs); - -var _package = require('../../package.json'); - -var _package2 = _interopRequireDefault(_package); - -var _webpackConfig = require('./config/webpack.config.prod'); - -var _webpackConfig2 = _interopRequireDefault(_webpackConfig); - -var _config = require('./config'); - -var _config2 = _interopRequireDefault(_config); - -var _index = require('./index.html'); - -var _index2 = _interopRequireDefault(_index); - -var _iframe = require('./iframe.html'); - -var _iframe2 = _interopRequireDefault(_iframe); - -var _utils = require('./utils'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -process.env.NODE_ENV = process.env.NODE_ENV || 'production'; - -// avoid ESLint errors -var logger = console; - -_commander2.default.version(_package2.default.version).option('-s, --static-dir ', 'Directory where to load static files from', _utils.parseList).option('-o, --output-dir [dir-name]', 'Directory where to store built files').option('-c, --config-dir [dir-name]', 'Directory where to load Storybook configurations from').option('-d, --db-path [db-file]', 'DEPRECATED!').option('--enable-db', 'DEPRECATED!').parse(process.argv); - -logger.info(_chalk2.default.bold(_package2.default.name + ' v' + _package2.default.version + '\n')); - -if (_commander2.default.enableDb || _commander2.default.dbPath) { - logger.error(['Error: the experimental local database addon is no longer bundled with', 'react-storybook. Please remove these flags (-d,--db-path,--enable-db)', 'from the command or npm script and try again.'].join(' ')); - process.exit(1); -} - -// The key is the field created in `program` variable for -// each command line argument. Value is the env variable. -(0, _utils.getEnvConfig)(_commander2.default, { - staticDir: 'SBCONFIG_STATIC_DIR', - outputDir: 'SBCONFIG_OUTPUT_DIR', - configDir: 'SBCONFIG_CONFIG_DIR' -}); - -var configDir = _commander2.default.configDir || './.storybook'; -var outputDir = _commander2.default.outputDir || './storybook-static'; - -// create output directory (and the static dir) if not exists -_shelljs2.default.rm('-rf', outputDir); -_shelljs2.default.mkdir('-p', _path2.default.resolve(outputDir)); -_shelljs2.default.cp(_path2.default.resolve(__dirname, 'public/favicon.ico'), outputDir); - -// Build the webpack configuration using the `baseConfig` -// custom `.babelrc` file and `webpack.config.js` files -// NOTE changes to env should be done before calling `getBaseConfig` -var config = (0, _config2.default)('PRODUCTION', (0, _webpackConfig2.default)(), configDir); -config.output.path = outputDir; - -// copy all static files -if (_commander2.default.staticDir) { - _commander2.default.staticDir.forEach(function (dir) { - if (!_fs2.default.existsSync(dir)) { - logger.error('Error: no such directory to load static files: ' + dir); - process.exit(-1); - } - logger.log('=> Copying static files from: ' + dir); - _shelljs2.default.cp('-r', dir + '/*', outputDir); - }); -} - -// compile all resources with webpack and write them to the disk. -logger.log('Building storybook ...'); -(0, _webpack2.default)(config).run(function (err, stats) { - if (err) { - logger.error('Failed to build the storybook'); - logger.error(err.message); - process.exit(1); - } - - var data = { - publicPath: config.output.publicPath, - assets: stats.toJson().assetsByChunkName - }; - var headHtml = (0, _utils.getHeadHtml)(configDir); - - // Write both the storybook UI and IFRAME HTML files to destination path. - _fs2.default.writeFileSync(_path2.default.resolve(outputDir, 'index.html'), (0, _index2.default)(data)); - _fs2.default.writeFileSync(_path2.default.resolve(outputDir, 'iframe.html'), (0, _iframe2.default)((0, _extends3.default)({}, data, { headHtml: headHtml }))); -}); \ No newline at end of file diff --git a/dist/server/config.js b/dist/server/config.js deleted file mode 100644 index 7223fd32da10..000000000000 --- a/dist/server/config.js +++ /dev/null @@ -1,127 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray'); - -var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); - -var _extends2 = require('babel-runtime/helpers/extends'); - -var _extends3 = _interopRequireDefault(_extends2); - -exports.addJsonLoaderIfNotAvailable = addJsonLoaderIfNotAvailable; - -exports.default = function (configType, baseConfig, configDir) { - var config = baseConfig; - - var babelConfig = (0, _babel_config2.default)(configDir); - config.module.loaders[0].query = babelConfig; - - // Check whether a config.js file exists inside the storybook - // config directory and throw an error if it's not. - var storybookConfigPath = _path2.default.resolve(configDir, 'config.js'); - if (!_fs2.default.existsSync(storybookConfigPath)) { - var err = new Error('=> Create a storybook config file in "' + configDir + '/config.js".'); - throw err; - } - config.entry.preview.push(require.resolve(storybookConfigPath)); - - // Check whether addons.js file exists inside the storybook. - // Load the default addons.js file if it's missing. - var storybookDefaultAddonsPath = _path2.default.resolve(__dirname, 'addons.js'); - var storybookCustomAddonsPath = _path2.default.resolve(configDir, 'addons.js'); - if (_fs2.default.existsSync(storybookCustomAddonsPath)) { - logger.info('=> Loading custom addons config.'); - config.entry.manager.unshift(storybookCustomAddonsPath); - } else { - config.entry.manager.unshift(storybookDefaultAddonsPath); - } - - // Check whether user has a custom webpack config file and - // return the (extended) base configuration if it's not available. - var customConfigPath = _path2.default.resolve(configDir, 'webpack.config.js'); - if (!_fs2.default.existsSync(customConfigPath)) { - logger.info('=> Using default webpack setup based on "Create React App".'); - customConfigPath = _path2.default.resolve(__dirname, './config/defaults/webpack.config.js'); - } - - var customConfig = require(customConfigPath); - - if (typeof customConfig === 'function') { - logger.info('=> Loading custom webpack config (full-control mode).'); - return customConfig(config, configType); - } - - logger.info('=> Loading custom webpack config.'); - - customConfig.module = customConfig.module || {}; - - var newConfig = (0, _extends3.default)({}, customConfig, config, { - // Override with custom devtool if provided - devtool: customConfig.devtool || config.devtool, - // We need to use our and custom plugins. - plugins: [].concat((0, _toConsumableArray3.default)(config.plugins), (0, _toConsumableArray3.default)(customConfig.plugins || [])), - module: (0, _extends3.default)({}, config.module, customConfig.module, { - loaders: [].concat((0, _toConsumableArray3.default)(config.module.loaders), (0, _toConsumableArray3.default)(customConfig.module.loaders || [])) - }), - resolve: (0, _extends3.default)({}, config.resolve, customConfig.resolve, { - alias: (0, _extends3.default)({}, config.alias, customConfig.resolve && customConfig.resolve.alias) - }) - }); - - addJsonLoaderIfNotAvailable(newConfig); - - return newConfig; -}; - -var _fs = require('fs'); - -var _fs2 = _interopRequireDefault(_fs); - -var _path = require('path'); - -var _path2 = _interopRequireDefault(_path); - -var _babel_config = require('./babel_config'); - -var _babel_config2 = _interopRequireDefault(_babel_config); - -var _utils = require('./config/utils'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// avoid ESLint errors -/* eslint global-require: 0 */ - -var logger = console; - -function addJsonLoaderIfNotAvailable(config) { - var jsonLoaderExists = config.module.loaders.reduce(function (value, loader) { - return value || [].concat(loader.test).some(function (matcher) { - var isRegex = matcher instanceof RegExp; - var testString = 'my_package.json'; - if (isRegex) { - return matcher.test(testString); - } - if (typeof matcher === 'function') { - return matcher(testString); - } - return false; - }); - }, false); - - if (!jsonLoaderExists) { - config.module.loaders.push({ - test: /\.json$/, - include: _utils.includePaths, - loader: require.resolve('json-loader') - }); - } -} - -// `baseConfig` is a webpack configuration bundled with storybook. -// React Storybook will look in the `configDir` directory -// (inside working directory) if a config path is not provided. \ No newline at end of file diff --git a/dist/server/config/babel.js b/dist/server/config/babel.js deleted file mode 100644 index 3aab69543074..000000000000 --- a/dist/server/config/babel.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -var findCacheDir = require('find-cache-dir'); - -module.exports = { - // Don't try to find .babelrc because we want to force this configuration. - babelrc: false, - // This is a feature of `babel-loader` for webpack (not Babel itself). - // It enables a cache directory for faster-rebuilds - // `find-cache-dir` will create the cache directory under the node_modules directory. - cacheDirectory: findCacheDir({ name: 'react-storybook' }), - presets: [require.resolve('babel-preset-react-app')] -}; \ No newline at end of file diff --git a/dist/server/config/babel.prod.js b/dist/server/config/babel.prod.js deleted file mode 100644 index 59335a100ffb..000000000000 --- a/dist/server/config/babel.prod.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; - -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -module.exports = { - // Don't try to find .babelrc because we want to force this configuration. - babelrc: false, - presets: [require.resolve('babel-preset-react-app')] -}; \ No newline at end of file diff --git a/dist/server/config/defaults/webpack.config.js b/dist/server/config/defaults/webpack.config.js deleted file mode 100644 index 8afac3101dc2..000000000000 --- a/dist/server/config/defaults/webpack.config.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict'; - -var _toConsumableArray2 = require('babel-runtime/helpers/toConsumableArray'); - -var _toConsumableArray3 = _interopRequireDefault(_toConsumableArray2); - -var _extends2 = require('babel-runtime/helpers/extends'); - -var _extends3 = _interopRequireDefault(_extends2); - -var _autoprefixer = require('autoprefixer'); - -var _autoprefixer2 = _interopRequireDefault(_autoprefixer); - -var _utils = require('../utils'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// Add a default custom config which is similar to what React Create App does. -module.exports = function (storybookBaseConfig) { - var newConfig = (0, _extends3.default)({}, storybookBaseConfig); - newConfig.module.loaders = [].concat((0, _toConsumableArray3.default)(storybookBaseConfig.module.loaders), [{ - test: /\.css?$/, - include: _utils.includePaths, - loaders: [require.resolve('style-loader'), require.resolve('css-loader') + '?importLoaders=1', require.resolve('postcss-loader')] - }, { - test: /\.json$/, - include: _utils.includePaths, - loader: require.resolve('json-loader') - }, { - test: /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2)(\?.*)?$/, - include: _utils.includePaths, - loader: require.resolve('file-loader'), - query: { - name: 'static/media/[name].[hash:8].[ext]' - } - }, { - test: /\.(mp4|webm|wav|mp3|m4a|aac|oga)(\?.*)?$/, - include: _utils.includePaths, - loader: require.resolve('url-loader'), - query: { - limit: 10000, - name: 'static/media/[name].[hash:8].[ext]' - } - }]); - - newConfig.postcss = function () { - return [(0, _autoprefixer2.default)({ - browsers: ['>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9'] - })]; - }; - - newConfig.resolve.alias = (0, _extends3.default)({}, storybookBaseConfig.resolve.alias, { - // This is to support NPM2 - 'babel-runtime/regenerator': require.resolve('babel-runtime/regenerator') - }); - - // Return the altered config - return newConfig; -}; \ No newline at end of file diff --git a/dist/server/config/polyfills.js b/dist/server/config/polyfills.js deleted file mode 100644 index a57d4d333063..000000000000 --- a/dist/server/config/polyfills.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict'; - -require('airbnb-js-shims'); \ No newline at end of file diff --git a/dist/server/config/utils.js b/dist/server/config/utils.js deleted file mode 100644 index dade99544b10..000000000000 --- a/dist/server/config/utils.js +++ /dev/null @@ -1,68 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.nodePaths = exports.nodeModulesPaths = exports.excludePaths = exports.includePaths = exports.OccurenceOrderPlugin = undefined; - -var _stringify = require('babel-runtime/core-js/json/stringify'); - -var _stringify2 = _interopRequireDefault(_stringify); - -var _keys = require('babel-runtime/core-js/object/keys'); - -var _keys2 = _interopRequireDefault(_keys); - -exports.loadEnv = loadEnv; - -var _webpack = require('webpack'); - -var _webpack2 = _interopRequireDefault(_webpack); - -var _path = require('path'); - -var _path2 = _interopRequireDefault(_path); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var OccurenceOrderPlugin = -// for webpack 2 -exports.OccurenceOrderPlugin = _webpack2.default.optimize.OccurrenceOrderPlugin || -// for webpack 1 -_webpack2.default.optimize.OccurenceOrderPlugin; - -var includePaths = exports.includePaths = [_path2.default.resolve('./')]; - -var excludePaths = exports.excludePaths = [_path2.default.resolve('./node_modules')]; - -var nodeModulesPaths = exports.nodeModulesPaths = _path2.default.resolve('./node_modules'); - -var nodePaths = exports.nodePaths = (process.env.NODE_PATH || '').split(process.platform === 'win32' ? ';' : ':').filter(Boolean).map(function (p) { - return _path2.default.resolve('./', p); -}); - -// Load environment variables starts with STORYBOOK_ to the client side. -function loadEnv() { - var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - - var defaultNodeEnv = options.production ? 'production' : 'development'; - var env = { - NODE_ENV: process.env.NODE_ENV || defaultNodeEnv, - // This is to support CRA's public folder feature. - // In production we set this to dot(.) to allow the browser to access these assests - // even when deployed inside a subpath. (like in GitHub pages) - // In development this is just empty as we always serves from the root. - PUBLIC_URL: options.production ? '.' : '' - }; - - (0, _keys2.default)(process.env).filter(function (name) { - return (/^STORYBOOK_/.test(name) - ); - }).forEach(function (name) { - env[name] = process.env[name]; - }); - - return { - 'process.env': (0, _stringify2.default)(env) - }; -} \ No newline at end of file diff --git a/dist/server/config/webpack.config.js b/dist/server/config/webpack.config.js deleted file mode 100644 index 414776f9d611..000000000000 --- a/dist/server/config/webpack.config.js +++ /dev/null @@ -1,68 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -exports.default = function () { - var config = { - devtool: 'eval', - entry: { - manager: [require.resolve('./polyfills'), require.resolve('../../client/manager')], - preview: [require.resolve('./polyfills'), require.resolve('./globals'), require.resolve('webpack-hot-middleware/client') + '?reload=true'] - }, - output: { - path: _path2.default.join(__dirname, 'dist'), - filename: 'static/[name].bundle.js', - publicPath: '/' - }, - plugins: [new _webpack2.default.DefinePlugin((0, _utils.loadEnv)()), new _utils.OccurenceOrderPlugin(), new _webpack2.default.HotModuleReplacementPlugin(), new _caseSensitivePathsWebpackPlugin2.default(), new _WatchMissingNodeModulesPlugin2.default(_utils.nodeModulesPaths)], - module: { - loaders: [{ - test: /\.jsx?$/, - loader: require.resolve('babel-loader'), - query: _babel2.default, - include: _utils.includePaths, - exclude: _utils.excludePaths - }] - }, - resolve: { - // Since we ship with json-loader always, it's better to move extensions to here - // from the default config. - extensions: ['.js', '.json', '.jsx', ''], - // Add support to NODE_PATH. With this we could avoid relative path imports. - // Based on this CRA feature: https://github.com/facebookincubator/create-react-app/issues/253 - fallback: _utils.nodePaths, - alias: { - // This is to add addon support for NPM2 - '@kadira/storybook-addons': require.resolve('@kadira/storybook-addons') - } - } - }; - - return config; -}; - -var _path = require('path'); - -var _path2 = _interopRequireDefault(_path); - -var _webpack = require('webpack'); - -var _webpack2 = _interopRequireDefault(_webpack); - -var _caseSensitivePathsWebpackPlugin = require('case-sensitive-paths-webpack-plugin'); - -var _caseSensitivePathsWebpackPlugin2 = _interopRequireDefault(_caseSensitivePathsWebpackPlugin); - -var _WatchMissingNodeModulesPlugin = require('./WatchMissingNodeModulesPlugin'); - -var _WatchMissingNodeModulesPlugin2 = _interopRequireDefault(_WatchMissingNodeModulesPlugin); - -var _utils = require('./utils'); - -var _babel = require('./babel.js'); - -var _babel2 = _interopRequireDefault(_babel); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/dist/server/config/webpack.config.prod.js b/dist/server/config/webpack.config.prod.js deleted file mode 100644 index 6dc307dca3ab..000000000000 --- a/dist/server/config/webpack.config.prod.js +++ /dev/null @@ -1,83 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -exports.default = function () { - var entries = { - preview: [require.resolve('./polyfills'), require.resolve('./globals')], - manager: [require.resolve('./polyfills'), _path2.default.resolve(__dirname, '../../client/manager')] - }; - - var config = { - bail: true, - devtool: '#cheap-module-source-map', - entry: entries, - output: { - filename: 'static/[name].[chunkhash].bundle.js', - // Here we set the publicPath to ''. - // This allows us to deploy storybook into subpaths like GitHub pages. - // This works with css and image loaders too. - // This is working for storybook since, we don't use pushState urls and - // relative URLs works always. - publicPath: '' - }, - plugins: [new _webpack2.default.DefinePlugin((0, _utils.loadEnv)({ production: true })), new _webpack2.default.optimize.DedupePlugin(), new _webpack2.default.optimize.UglifyJsPlugin({ - compress: { - screw_ie8: true, - warnings: false - }, - mangle: false, - output: { - comments: false, - screw_ie8: true - } - })], - module: { - loaders: [{ - test: /\.jsx?$/, - loader: require.resolve('babel-loader'), - query: _babelProd2.default, - include: _utils.includePaths, - exclude: _utils.excludePaths - }] - }, - resolve: { - // Since we ship with json-loader always, it's better to move extensions to here - // from the default config. - extensions: ['.js', '.json', '.jsx', ''], - // Add support to NODE_PATH. With this we could avoid relative path imports. - // Based on this CRA feature: https://github.com/facebookincubator/create-react-app/issues/253 - fallback: _utils.nodePaths, - alias: { - // This is to add addon support for NPM2 - '@kadira/storybook-addons': require.resolve('@kadira/storybook-addons') - } - } - }; - - // Webpack 2 doesn't have a OccurenceOrderPlugin plugin in the production mode. - // But webpack 1 has it. That's why we do this. - if (_utils.OccurenceOrderPlugin) { - config.plugins.unshift(new _utils.OccurenceOrderPlugin()); - } - - return config; -}; - -var _path = require('path'); - -var _path2 = _interopRequireDefault(_path); - -var _webpack = require('webpack'); - -var _webpack2 = _interopRequireDefault(_webpack); - -var _babelProd = require('./babel.prod.js'); - -var _babelProd2 = _interopRequireDefault(_babelProd); - -var _utils = require('./utils'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/dist/server/iframe.html.js b/dist/server/iframe.html.js deleted file mode 100644 index d6a1ae8f352f..000000000000 --- a/dist/server/iframe.html.js +++ /dev/null @@ -1,58 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -exports.default = function (data) { - var assets = data.assets, - headHtml = data.headHtml, - publicPath = data.publicPath; - - - var previewUrls = previewUrlsFromAssets(assets); - - var previewCssTag = ''; - if (previewUrls.css) { - previewCssTag = ''; - } - - return '\n \n \n \n \n \n \n React Storybook\n ' + headHtml + '\n ' + previewCssTag + '\n \n \n
\n
\n \n \n \n '; -}; - -var _url = require('url'); - -var _url2 = _interopRequireDefault(_url); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// assets.preview will be: -// - undefined -// - string e.g. 'static/preview.9adbb5ef965106be1cc3.bundle.js' -// - array of strings e.g. -// [ 'static/preview.9adbb5ef965106be1cc3.bundle.js', -// 'preview.0d2d3d845f78399fd6d5e859daa152a9.css', -// 'static/preview.9adbb5ef965106be1cc3.bundle.js.map', -// 'preview.0d2d3d845f78399fd6d5e859daa152a9.css.map' ] -var previewUrlsFromAssets = function previewUrlsFromAssets(assets) { - if (!assets) { - return { - js: 'static/preview.bundle.js' - }; - } - - if (typeof assets.preview === 'string') { - return { - js: assets.preview - }; - } - - return { - js: assets.preview.find(function (filename) { - return filename.match(/\.js$/); - }), - css: assets.preview.find(function (filename) { - return filename.match(/\.css$/); - }) - }; -}; \ No newline at end of file diff --git a/dist/server/index.html.js b/dist/server/index.html.js deleted file mode 100644 index fb15c51fb35e..000000000000 --- a/dist/server/index.html.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -exports.default = function (data) { - var assets = data.assets, - publicPath = data.publicPath; - - - var managerUrls = managerUrlsFromAssets(assets); - - return '\n \n \n \n \n \n \n React Storybook\n \n \n \n
\n \n \n \n '; -}; - -var _url = require('url'); - -var _url2 = _interopRequireDefault(_url); - -var _package = require('../../package.json'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -// assets.manager will be: -// - undefined -// - string e.g. 'static/manager.9adbb5ef965106be1cc3.bundle.js' -// - array of strings e.g. -// assets.manager will be something like: -// [ 'static/manager.c6e6350b6eb01fff8bad.bundle.js', -// 'static/manager.c6e6350b6eb01fff8bad.bundle.js.map' ] -var managerUrlsFromAssets = function managerUrlsFromAssets(assets) { - if (!assets || !assets.manager) { - return { - js: 'static/manager.bundle.js' - }; - } - - if (typeof assets.manager === 'string') { - return { - js: assets.manager - }; - } - - return { - js: assets.manager.find(function (filename) { - return filename.match(/\.js$/); - }), - css: assets.manager.find(function (filename) { - return filename.match(/\.css$/); - }) - }; -}; \ No newline at end of file diff --git a/dist/server/index.js b/dist/server/index.js deleted file mode 100755 index 64e5d4a223b7..000000000000 --- a/dist/server/index.js +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env node -'use strict'; - -var _server; - -var _express = require('express'); - -var _express2 = _interopRequireDefault(_express); - -var _https = require('https'); - -var _https2 = _interopRequireDefault(_https); - -var _serveFavicon = require('serve-favicon'); - -var _serveFavicon2 = _interopRequireDefault(_serveFavicon); - -var _commander = require('commander'); - -var _commander2 = _interopRequireDefault(_commander); - -var _path = require('path'); - -var _path2 = _interopRequireDefault(_path); - -var _fs = require('fs'); - -var _fs2 = _interopRequireDefault(_fs); - -var _chalk = require('chalk'); - -var _chalk2 = _interopRequireDefault(_chalk); - -var _shelljs = require('shelljs'); - -var _shelljs2 = _interopRequireDefault(_shelljs); - -var _middleware = require('./middleware'); - -var _middleware2 = _interopRequireDefault(_middleware); - -var _package = require('../../package.json'); - -var _package2 = _interopRequireDefault(_package); - -var _utils = require('./utils'); - -var _track_usage = require('./track_usage'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -process.env.NODE_ENV = process.env.NODE_ENV || 'development'; - -var logger = console; -_commander2.default.version(_package2.default.version).option('-p, --port [number]', 'Port to run Storybook (Required)', parseInt).option('-h, --host [string]', 'Host to run Storybook').option('-s, --static-dir ', 'Directory where to load static files from').option('-c, --config-dir [dir-name]', 'Directory where to load Storybook configurations from').option('--dont-track', 'Do not send anonymous usage stats.').option('--https', 'Serve Storybook over HTTPS. Note: You must provide your own certificate information.').option('--ssl-ca ', 'Provide an SSL certificate authority. (Optional with --https, required if using a self-signed certificate)', _utils.parseList).option('--ssl-cert ', 'Provide an SSL certificate. (Required with --https)').option('--ssl-key ', 'Provide an SSL key. (Required with --https)').option('-d, --db-path [db-file]', 'DEPRECATED!').option('--enable-db', 'DEPRECATED!').parse(process.argv); - -logger.info(_chalk2.default.bold(_package2.default.name + ' v' + _package2.default.version + '\n')); - -if (_commander2.default.enableDb || _commander2.default.dbPath) { - logger.error(['Error: the experimental local database addon is no longer bundled with', 'react-storybook. Please remove these flags (-d,--db-path,--enable-db)', 'from the command or npm script and try again.'].join(' ')); - process.exit(1); -} - -// The key is the field created in `program` variable for -// each command line argument. Value is the env variable. -(0, _utils.getEnvConfig)(_commander2.default, { - port: 'SBCONFIG_PORT', - host: 'SBCONFIG_HOSTNAME', - staticDir: 'SBCONFIG_STATIC_DIR', - configDir: 'SBCONFIG_CONFIG_DIR', - dontTrack: 'SBCONFIG_DO_NOT_TRACK' -}); - -if (_commander2.default.dontTrack) { - (0, _track_usage.dontTrack)(); -} - -if (!_commander2.default.port) { - logger.error('Error: port to run Storybook is required!\n'); - _commander2.default.help(); - process.exit(-1); -} - -// Used with `app.listen` below -var listenAddr = [_commander2.default.port]; - -if (_commander2.default.host) { - listenAddr.push(_commander2.default.host); -} - -var app = (0, _express2.default)(); -var server = app; - -if (_commander2.default.https) { - if (!_commander2.default.sslCert) { - logger.error('Error: --ssl-cert is required with --https'); - process.exit(-1); - } - if (!_commander2.default.sslKey) { - logger.error('Error: --ssl-key is required with --https'); - process.exit(-1); - } - - var sslOptions = { - ca: (_commander2.default.sslCa || []).map(function (ca) { - return _fs2.default.readFileSync(ca, 'utf-8'); - }), - cert: _fs2.default.readFileSync(_commander2.default.sslCert, 'utf-8'), - key: _fs2.default.readFileSync(_commander2.default.sslKey, 'utf-8') - }; - - server = _https2.default.createServer(sslOptions, app); -} - -var hasCustomFavicon = false; - -if (_commander2.default.staticDir) { - _commander2.default.staticDir = (0, _utils.parseList)(_commander2.default.staticDir); - _commander2.default.staticDir.forEach(function (dir) { - var staticPath = _path2.default.resolve(dir); - if (!_fs2.default.existsSync(staticPath)) { - logger.error('Error: no such directory to load static files: ' + staticPath); - process.exit(-1); - } - logger.log('=> Loading static files from: ' + staticPath + ' .'); - app.use(_express2.default.static(staticPath, { index: false })); - - var faviconPath = _path2.default.resolve(staticPath, 'favicon.ico'); - if (_fs2.default.existsSync(faviconPath)) { - hasCustomFavicon = true; - app.use((0, _serveFavicon2.default)(faviconPath)); - } - }); -} - -if (!hasCustomFavicon) { - app.use((0, _serveFavicon2.default)(_path2.default.resolve(__dirname, 'public/favicon.ico'))); -} - -// Build the webpack configuration using the `baseConfig` -// custom `.babelrc` file and `webpack.config.js` files -var configDir = _commander2.default.configDir || './.storybook'; - -// The repository info is sent to the storybook while running on -// development mode so it'll be easier for tools to integrate. -var exec = function exec(cmd) { - return _shelljs2.default.exec(cmd, { silent: true }).stdout.trim(); -}; -process.env.STORYBOOK_GIT_ORIGIN = process.env.STORYBOOK_GIT_ORIGIN || exec('git remote get-url origin'); -process.env.STORYBOOK_GIT_BRANCH = process.env.STORYBOOK_GIT_BRANCH || exec('git symbolic-ref HEAD --short'); - -// NOTE changes to env should be done before calling `getBaseConfig` -// `getBaseConfig` function which is called inside the middleware -app.use((0, _middleware2.default)(configDir)); - -(_server = server).listen.apply(_server, listenAddr.concat([function (error) { - if (error) { - throw error; - } else { - var address = 'http' + (_commander2.default.https ? 's' : '') + '://' + (_commander2.default.host || 'localhost') + ':' + _commander2.default.port + '/'; - logger.info('\nReact Storybook started on => ' + _chalk2.default.cyan(address) + '\n'); - (0, _track_usage.track)(); - } -}])); \ No newline at end of file diff --git a/dist/server/middleware.js b/dist/server/middleware.js deleted file mode 100644 index 8ab9fb4d5541..000000000000 --- a/dist/server/middleware.js +++ /dev/null @@ -1,81 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _extends2 = require('babel-runtime/helpers/extends'); - -var _extends3 = _interopRequireDefault(_extends2); - -exports.default = function (configDir) { - // Build the webpack configuration using the `getBaseConfig` - // custom `.babelrc` file and `webpack.config.js` files - var config = (0, _config2.default)('DEVELOPMENT', (0, _webpack4.default)(), configDir); - var middlewareFn = (0, _utils.getMiddleware)(configDir); - - // remove the leading '/' - var publicPath = config.output.publicPath; - if (publicPath[0] === '/') { - publicPath = publicPath.slice(1); - } - - var compiler = (0, _webpack2.default)(config); - var devMiddlewareOptions = (0, _extends3.default)({ - noInfo: true, - publicPath: config.output.publicPath, - watchOptions: config.watchOptions || {} - }, config.devServer); - - var router = new _express.Router(); - router.use((0, _webpackDevMiddleware2.default)(compiler, devMiddlewareOptions)); - router.use((0, _webpackHotMiddleware2.default)(compiler)); - - // custom middleware - middlewareFn(router); - - router.get('/', function (req, res) { - res.send((0, _index2.default)({ publicPath: publicPath })); - }); - - router.get('/iframe.html', function (req, res) { - var headHtml = (0, _utils.getHeadHtml)(configDir); - res.send((0, _iframe2.default)({ headHtml: headHtml, publicPath: publicPath })); - }); - - return router; -}; - -var _express = require('express'); - -var _webpack = require('webpack'); - -var _webpack2 = _interopRequireDefault(_webpack); - -var _webpackDevMiddleware = require('webpack-dev-middleware'); - -var _webpackDevMiddleware2 = _interopRequireDefault(_webpackDevMiddleware); - -var _webpackHotMiddleware = require('webpack-hot-middleware'); - -var _webpackHotMiddleware2 = _interopRequireDefault(_webpackHotMiddleware); - -var _webpack3 = require('./config/webpack.config'); - -var _webpack4 = _interopRequireDefault(_webpack3); - -var _config = require('./config'); - -var _config2 = _interopRequireDefault(_config); - -var _index = require('./index.html'); - -var _index2 = _interopRequireDefault(_index); - -var _iframe = require('./iframe.html'); - -var _iframe2 = _interopRequireDefault(_iframe); - -var _utils = require('./utils'); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } \ No newline at end of file diff --git a/dist/server/track_usage.js b/dist/server/track_usage.js deleted file mode 100644 index 514d95d9e8bd..000000000000 --- a/dist/server/track_usage.js +++ /dev/null @@ -1,106 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.getStore = getStore; -exports.track = track; -exports.dontTrack = dontTrack; - -var _configstore = require('configstore'); - -var _configstore2 = _interopRequireDefault(_configstore); - -var _uuid = require('uuid'); - -var _uuid2 = _interopRequireDefault(_uuid); - -var _request = require('request'); - -var _request2 = _interopRequireDefault(_request); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -var logger = console; /* eslint global-require: 0 */ - -// ### WHAT? -// -// We will track anonymous usage of how you use storybook. -// We don't want any personal information. -// We just need to collect following information -// -// * How many time a user runs start-storybook a day -// -// We will send a ping to our server when you run storybook with above information. - -// ### WHY? -// -// We are maintaining React Storybook and we want to improve it. -// We also working on storybooks.io which is storybook related service. -// In order to get a real picture about the storybook usage, -// we need to get some real usage stats, not the amount of NPM downloads. -// This is why we do this. - -// ### CAN I STOP THIS? -// -// You(or your company) may have certain policies. -// If so, you can stop sending these metrics. -// To do that, use --dont-track flag when running React Storybook. -// start-storybook --dont-track -p 9001 - -// ### HELP US? -// -// Maintaining a open source project is hard. -// It's even harder for a startup like us (Kadira) -// Help us to make storybook better by sending these few metrics. -// Based on these metrics, we could improve storybook and build a profitable -// service around it. With that, we could continue to maintain and -// improve Storybook. - -var DONT_TRACK = false; - -function getStore() { - var key = 'react-storybook-usage'; - var store = new _configstore2.default(key); - return store; -} - -function track() { - if (DONT_TRACK) return; - - var store = getStore(); - - // Just a hash to aggregate metrics. Don't use any personal info. - var userId = store.get('userId'); - if (!userId) { - userId = _uuid2.default.v4(); - store.set('userId', userId); - } - - var pkg = require('../../package.json'); - - // We don't wanna worry about the success or failure of this. - _request2.default.post('https://ping.getstorybook.io/react-storybook-usage', { - json: { - userId: userId, - version: pkg.version - } - }, function () {}); - - if (!store.get('startTrackingOn')) { - store.set('startTrackingOn', Date.now()); - } - - var pingsSent = store.get('pingsSent') || 0; - store.set('pingsSent', pingsSent + 1); - - if (pingsSent < 5) { - logger.log(' We will collect some anonymous usage stats of how you use storybook.'); - logger.log(' See why?: https://getstorybook.io/tracking'); - logger.log(); - } -} - -function dontTrack() { - DONT_TRACK = true; -} \ No newline at end of file diff --git a/dist/server/utils.js b/dist/server/utils.js deleted file mode 100644 index 81c27d962245..000000000000 --- a/dist/server/utils.js +++ /dev/null @@ -1,60 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); - -var _keys = require('babel-runtime/core-js/object/keys'); - -var _keys2 = _interopRequireDefault(_keys); - -exports.parseList = parseList; -exports.getHeadHtml = getHeadHtml; -exports.getEnvConfig = getEnvConfig; -exports.getMiddleware = getMiddleware; - -var _path = require('path'); - -var _path2 = _interopRequireDefault(_path); - -var _fs = require('fs'); - -var _fs2 = _interopRequireDefault(_fs); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - -function parseList(str) { - return str.split(','); -} - -function getHeadHtml(configDirPath) { - var headHtmlPath = _path2.default.resolve(configDirPath, 'head.html'); - var headHtml = ''; - if (_fs2.default.existsSync(headHtmlPath)) { - headHtml = _fs2.default.readFileSync(headHtmlPath, 'utf8'); - } - - return headHtml; -} - -function getEnvConfig(program, configEnv) { - (0, _keys2.default)(configEnv).forEach(function (fieldName) { - var envVarName = configEnv[fieldName]; - var envVarValue = process.env[envVarName]; - if (envVarValue) { - program[fieldName] = envVarValue; // eslint-disable-line no-param-reassign - } - }); -} - -function getMiddleware(configDir) { - var middlewarePath = _path2.default.resolve(configDir, 'middleware.js'); - if (_fs2.default.existsSync(middlewarePath)) { - var middlewareModule = require(middlewarePath); // eslint-disable-line global-require - if (middlewareModule.__esModule) { - middlewareModule = middlewareModule.default; - } - return middlewareModule; - } - return function () {}; -} \ No newline at end of file diff --git a/docs/.DS_Store b/docs/.DS_Store deleted file mode 100644 index dcc732d74d64..000000000000 Binary files a/docs/.DS_Store and /dev/null differ diff --git a/lerna.json b/lerna.json new file mode 100644 index 000000000000..d056fa4189b5 --- /dev/null +++ b/lerna.json @@ -0,0 +1,7 @@ +{ + "lerna": "2.0.0-beta.38", + "packages": [ + "packages/*" + ], + "version": "0.0.0" +} diff --git a/package.json b/package.json index 2836b293eedf..c9cff6725965 100644 --- a/package.json +++ b/package.json @@ -1,98 +1,17 @@ { - "name": "@kadira/storybook", - "version": "2.35.3", - "description": "React Storybook: Isolate React Component Development with Hot Reloading.", - "repository": { - "type": "git", - "url": "https://github.com/storybooks/react-storybook.git" - }, - "typings": "./config/storybook.d.ts", - "license": "MIT", - "options": { - "mocha": "--require scripts/mocha_runner src/**/__tests__/**/*.js" - }, - "scripts": { - "prepublish": "sh scripts/prepublish.sh", - "lint": "eslint src", - "lintfix": "eslint src --fix", - "testonly": "mocha $npm_package_options_mocha", - "test": "npm run lint && npm run testonly", - "test-watch": "npm run testonly -- --watch --watch-extensions js", - "dev": "DEV_BUILD=1 nodemon --watch src --exec 'npm run prepublish'", - "postpublish": "greenkeeper-postpublish" - }, - "dependencies": { - "@kadira/react-split-pane": "^1.4.0", - "@kadira/storybook-addon-actions": "^1.0.2", - "@kadira/storybook-addon-links": "^1.0.0", - "@kadira/storybook-addons": "^1.5.0", - "@kadira/storybook-channel-postmsg": "^2.0.1", - "@kadira/storybook-ui": "^3.10.1", - "airbnb-js-shims": "^1.0.1", - "autoprefixer": "^6.3.7", - "babel-core": "^6.11.4", - "babel-loader": "^6.2.4", - "babel-plugin-react-docgen": "^1.4.2", - "babel-preset-react-app": "^1.0.0", - "babel-runtime": "^6.9.2", - "case-sensitive-paths-webpack-plugin": "^1.1.2", - "chalk": "^1.1.3", - "commander": "^2.9.0", - "common-tags": "^1.3.1", - "configstore": "^2.0.0", - "css-loader": "^0.26.1", - "express": "^4.13.3", - "file-loader": "^0.9.0", - "find-cache-dir": "^0.1.1", - "json-loader": "^0.5.4", - "json-stringify-safe": "^5.0.1", - "json5": "^0.5.0", - "lodash.pick": "^4.2.0", - "postcss-loader": "1.1.0", - "qs": "^6.1.0", - "react-modal": "^1.2.0", - "redux": "^3.5.2", - "request": "^2.74.0", - "serve-favicon": "^2.3.0", - "shelljs": "^0.7.4", - "style-loader": "0.13.1", - "url-loader": "^0.5.7", - "uuid": "^2.0.3", - "webpack": "^1.13.1", - "webpack-dev-middleware": "^1.6.0", - "webpack-hot-middleware": "^2.13.2" - }, - "peerDependencies": { - "react": "^0.14.7 || ^15.0.0", - "react-dom": "^0.14.7 || ^15.0.0" - }, + "name": "storybook", "devDependencies": { - "babel-cli": "^6.11.4", - "babel-eslint": "^6.1.2", - "babel-preset-stage-0": "^6.5.0", - "chai": "^3.5.0", - "deep-equal": "^1.0.1", - "enzyme": "^2.2.0", - "eslint": "^3.5.0", - "eslint-config-airbnb": "^11.1.0", - "eslint-plugin-import": "^1.13.0", - "eslint-plugin-jsx-a11y": "^2.1.0", - "eslint-plugin-react": "^6.1.2", - "expect": "^1.6.0", - "greenkeeper-postpublish": "^1.0.1", - "jsdom": "^9.5.0", - "mocha": "^3.0.2", - "mock-fs": "^3.8.0", - "nodemon": "^1.9.1", - "react": "^15.0.0", - "react-addons-test-utils": "^15.0.1", - "react-dom": "^15.0.0", - "sinon": "^1.17.3" + "babel-eslint": "^7.2.2", + "eslint": "^3.19.0", + "eslint-config-airbnb-base": "^11.1.3", + "eslint-plugin-import": "^2.2.0", + "eslint-plugin-prettier": "^2.0.1", + "lerna": "2.0.0-rc.2", + "prettier": "^1.1.0" }, - "main": "dist/client/index.js", - "bin": { - "start-storybook": "./dist/server/index.js", - "build-storybook": "./dist/server/build.js", - "storybook-server": "./dist/server/index.js" + "scripts": { + "postinstall": "lerna bootstrap", + "test": "lerna run test", + "lint": "eslint ." } } diff --git a/packages/addon-actions/.babelrc b/packages/addon-actions/.babelrc new file mode 100644 index 000000000000..9b7d435ad38f --- /dev/null +++ b/packages/addon-actions/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["es2015", "stage-0", "react"] +} diff --git a/packages/addon-actions/.scripts/npm-prepublish.js b/packages/addon-actions/.scripts/npm-prepublish.js new file mode 100644 index 000000000000..bb13fdba9872 --- /dev/null +++ b/packages/addon-actions/.scripts/npm-prepublish.js @@ -0,0 +1,6 @@ +var path = require('path'); +var shell = require('shelljs'); +var babel = ['node_modules', '.bin', 'babel'].join(path.sep); + +shell.rm('-rf', 'dist') +shell.exec(babel + ' --ignore __tests__ src --out-dir dist') diff --git a/packages/addon-actions/.storybook/addons.js b/packages/addon-actions/.storybook/addons.js new file mode 100644 index 000000000000..ec80e21eeaa2 --- /dev/null +++ b/packages/addon-actions/.storybook/addons.js @@ -0,0 +1,6 @@ +// Uncomment to register defaults +// import '@kadira/storybook/addons'; + +// Use the line below to register this addon +// import '@kadira/storybook-addon-actions/register'; +import '../register'; diff --git a/packages/addon-actions/.storybook/config.js b/packages/addon-actions/.storybook/config.js new file mode 100644 index 000000000000..c4434721049e --- /dev/null +++ b/packages/addon-actions/.storybook/config.js @@ -0,0 +1,2 @@ +import * as storybook from '@kadira/storybook'; +storybook.configure(() => require('./stories'), module); diff --git a/packages/addon-actions/.storybook/stories.js b/packages/addon-actions/.storybook/stories.js new file mode 100644 index 000000000000..b19b2acb6d51 --- /dev/null +++ b/packages/addon-actions/.storybook/stories.js @@ -0,0 +1,27 @@ +import React from 'react'; +import { storiesOf } from '@kadira/storybook'; +import { action, decorateAction } from '../src'; + +const pickFirst = decorateAction([ + args => args.slice(0, 1) +]); + +storiesOf('Button', module) + .add('Hello World', () => ( + + )) + .add('Decorated Action', () => ( + + )) + .add('Circular Payload', () => { + const circular = {foo: {}}; + circular.foo.circular = circular; + return ; + }) + .add('Function Name', () => { + const fn = action('fnName'); + return + }); diff --git a/packages/addon-actions/CHANGELOG.md b/packages/addon-actions/CHANGELOG.md new file mode 100644 index 000000000000..4877d027d590 --- /dev/null +++ b/packages/addon-actions/CHANGELOG.md @@ -0,0 +1,39 @@ +## Changelog + +### v1.1.3 +22 Mar 2017 + +* Fix issue caused by `v1.1.2` where storybook crashes when actions are used without names [PR30](https://github.com/storybooks/storybook-addon-actions/pull/30). + +### v1.1.2 +21 Mar 2017 + +* Document `decorateAction` function (action decorator). [PR28](https://github.com/storybooks/storybook-addon-actions/pull/28) + +* Set correct Function.name for action handlers [PR24](https://github.com/storybooks/storybook-addon-actions/pull/24) + +### v1.1.1 +11 Sep 2016 + +* Support arguments with circular references [PR6](https://github.com/kadirahq/storybook-addon-actions/pull/6) + +### v1.1.0 +11 Sep 2016 + +* Support action decorators [PR3](https://github.com/kadirahq/storybook-addon-actions/pull/3) + +### v1.0.4 + +* Refactor source code (use separate files) + +### v1.0.3 + +* Log all arguments (only the first argument was logged previously) + +### v1.0.2 + +* Style tweak: center counter and inspector elements + +### v1.0.1 + +* First stable release with all features from the storybook action logger such as `action` function, react inspector and grouping log messages. diff --git a/packages/addon-actions/README.md b/packages/addon-actions/README.md new file mode 100644 index 000000000000..ebaa9326e34c --- /dev/null +++ b/packages/addon-actions/README.md @@ -0,0 +1,46 @@ +# Storybook Addon Actions + +The Action Logger addon can be used to display data received by event handlers. This addon works with both [React Storybook](https://github.com/kadirahq/react-storybook) and [React Native Storybook](https://github.com/kadirahq/react-native-storybook) (included by default). + +![](docs/screenshot.png) + +## Getting Started + +You can use this addon without installing it manually. + +Import the `action` function and use it to create actions handlers. When creating action handlers, provide a **name** to make it easier to identify. + +> *Note: Make sure NOT to use reserved words as function names. [issues#29](https://github.com/storybooks/storybook-addon-actions/issues/29#issuecomment-288274794)* + +```js +import { storiesOf, action } from '@kadira/storybook' +// or import { action } from '@kadira/storybook-addon-actions' + +storiesOf('Button', module) + .add('default view', () => ( + + )) +``` + +## Action Decorators + +If you wish to process action data before sending them over to the logger, you can do it with action decorators. + +`decorateAction` takes an array of decorator functions. Each decorator function is passed an array of arguments, and should return a new arguments array to use. `decorateAction` returns a function that can be used like `action` but will log the modified arguments instead of the original arguments. + +```js +import { action, decorateAction } from '@kadira/storybook-addon-actions' + +const firstArgAction = decorateAction([ + args => args.slice(0, 1) +]); + +storiesOf('Button', module) + .add('default view', () => ( + + )) +``` diff --git a/packages/addon-actions/docs/screenshot.png b/packages/addon-actions/docs/screenshot.png new file mode 100644 index 000000000000..f3b6abaf9166 Binary files /dev/null and b/packages/addon-actions/docs/screenshot.png differ diff --git a/packages/addon-actions/package.json b/packages/addon-actions/package.json new file mode 100644 index 000000000000..40f1977ff4cc --- /dev/null +++ b/packages/addon-actions/package.json @@ -0,0 +1,48 @@ +{ + "name": "@kadira/storybook-addon-actions", + "version": "1.1.3", + "description": "Action Logger addon for storybook", + "main": "dist/index.js", + "scripts": { + "deploy-storybook": "storybook-to-ghpages", + "prepublish": "node .scripts/npm-prepublish.js", + "storybook": "start-storybook -p 9001", + "test": "echo \"Error: no test specified\" && exit 0" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/kadirahq/storybook-addon-actions.git" + }, + "keywords": [ + "storybook" + ], + "license": "MIT", + "bugs": { + "url": "https://github.com/kadirahq/storybook-addon-actions/issues" + }, + "homepage": "https://github.com/kadirahq/storybook-addon-actions#readme", + "devDependencies": { + "@kadira/storybook": "^2.20.1", + "@kadira/storybook-addons": "^1.3.0", + "@kadira/storybook-ui": "^3.0.0", + "babel-cli": "^6.11.4", + "babel-preset-es2015": "^6.9.0", + "babel-preset-react": "^6.11.1", + "babel-preset-stage-0": "^6.5.0", + "react": "^15.5.4", + "react-dom": "^15.5.4", + "react-test-renderer": "^15.5.4", + "shelljs": "^0.7.3" + }, + "dependencies": { + "deep-equal": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "prop-types": "^15.5.7", + "react-inspector": "^1.1.0" + }, + "peerDependencies": { + "@kadira/storybook-addons": "^1.3.0", + "react": "*", + "react-dom": "*" + } +} diff --git a/packages/addon-actions/register.js b/packages/addon-actions/register.js new file mode 100644 index 000000000000..e69edbea3ed1 --- /dev/null +++ b/packages/addon-actions/register.js @@ -0,0 +1 @@ +require('./dist').register(); diff --git a/packages/addon-actions/src/components/ActionLogger/index.js b/packages/addon-actions/src/components/ActionLogger/index.js new file mode 100644 index 000000000000..203d2f1bf4d8 --- /dev/null +++ b/packages/addon-actions/src/components/ActionLogger/index.js @@ -0,0 +1,56 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import Inspector from 'react-inspector'; +import style from './style'; + +class ActionLogger extends Component { + componentDidUpdate() { + const latest = this.refs.latest; + if (latest) { + const borderLeft = style.action.borderLeft; + latest.style.borderLeft = 'solid 5px #aaa'; + setTimeout(() => { + latest.style.borderLeft = borderLeft; + }, 300); + } + } + + renderAction(action, i) { + const ref = i ? '' : 'latest'; + const counter =
{action.count}
; + return ( +
+
+ {action.count > 1 && counter} +
+
+ +
+
+ ); + } + + getActionData() { + return this.props.actions.map((action, i) => this.renderAction(action, i)); + } + + render() { + return ( +
+
{this.getActionData()}
+ +
+ ); + } +} + +ActionLogger.propTypes = { + onClear: PropTypes.func, + actions: PropTypes.array, +}; + +export default ActionLogger; diff --git a/packages/addon-actions/src/components/ActionLogger/style.js b/packages/addon-actions/src/components/ActionLogger/style.js new file mode 100644 index 000000000000..d82497e1adad --- /dev/null +++ b/packages/addon-actions/src/components/ActionLogger/style.js @@ -0,0 +1,49 @@ +export default { + wrapper: { + flex: 1, + display: 'flex', + position: 'relative', + }, + actions: { + flex: 1, + margin: 0, + padding: '8px 2px 20px 0', + overflowY: 'auto', + color: '#666', + }, + action: { + display: 'flex', + padding: '3px 3px 3px 0', + borderLeft: '5px solid white', + borderBottom: '1px solid #fafafa', + transition: 'all 0.1s', + alignItems: 'center', + }, + countwrap: { + paddingBottom: 2, + }, + counter: { + margin: '0 5px 0 5px', + backgroundColor: '#777777', + color: '#ffffff', + padding: '1px 5px', + borderRadius: '20px', + }, + inspector: { + flex: 1, + padding: '0 0 0 5px', + }, + button: { + position: 'absolute', + bottom: 0, + right: 0, + border: 'none', + borderTop: 'solid 1px rgba(0, 0, 0, 0.2)', + borderLeft: 'solid 1px rgba(0, 0, 0, 0.2)', + background: 'rgba(255, 255, 255, 0.5)', + padding: '5px 10px', + borderRadius: '4px 0 0 0', + color: 'rgba(0, 0, 0, 0.5)', + outline: 'none', + }, +}; diff --git a/packages/addon-actions/src/containers/ActionLogger/index.js b/packages/addon-actions/src/containers/ActionLogger/index.js new file mode 100644 index 000000000000..a4668784b059 --- /dev/null +++ b/packages/addon-actions/src/containers/ActionLogger/index.js @@ -0,0 +1,45 @@ +import React from 'react'; +import deepEqual from 'deep-equal'; +import ActionLoggerComponent from '../../components/ActionLogger/'; +import { EVENT_ID } from '../../'; + +export default class ActionLogger extends React.Component { + constructor(props, ...args) { + super(props, ...args); + this.state = { actions: [] }; + this._actionListener = action => this.addAction(action); + } + + addAction(action) { + action.data.args = action.data.args.map(arg => JSON.parse(arg)); + const actions = [...this.state.actions]; + const previous = actions.length && actions[0]; + if (previous && deepEqual(previous.data, action.data)) { + previous.count++; + } else { + action.count = 1; + actions.unshift(action); + } + this.setState({ actions }); + } + + clearActions() { + this.setState({ actions: [] }); + } + + componentDidMount() { + this.props.channel.on(EVENT_ID, this._actionListener); + } + + componentWillUnmount() { + this.props.channel.removeListener(EVENT_ID, this._actionListener); + } + + render() { + const props = { + actions: this.state.actions, + onClear: () => this.clearActions(), + }; + return ; + } +} diff --git a/packages/addon-actions/src/index.js b/packages/addon-actions/src/index.js new file mode 100644 index 000000000000..15db14d506a7 --- /dev/null +++ b/packages/addon-actions/src/index.js @@ -0,0 +1,7 @@ +// addons, panels and events get unique names using a prefix +export const ADDON_ID = 'kadirahq/storybook-addon-actions'; +export const PANEL_ID = `${ADDON_ID}/actions-panel`; +export const EVENT_ID = `${ADDON_ID}/action-event`; + +export { register } from './manager'; +export { action, decorateAction } from './preview'; diff --git a/packages/addon-actions/src/manager.js b/packages/addon-actions/src/manager.js new file mode 100644 index 000000000000..4728e7ac6d3d --- /dev/null +++ b/packages/addon-actions/src/manager.js @@ -0,0 +1,14 @@ +import React from 'react'; +import addons from '@kadira/storybook-addons'; +import ActionLogger from './containers/ActionLogger'; +import { ADDON_ID, PANEL_ID } from './'; + +export function register() { + addons.register(ADDON_ID, api => { + const channel = addons.getChannel(); + addons.addPanel(PANEL_ID, { + title: 'Action Logger', + render: () => , + }); + }); +} diff --git a/packages/addon-actions/src/preview.js b/packages/addon-actions/src/preview.js new file mode 100644 index 000000000000..a2dfd1b31a0f --- /dev/null +++ b/packages/addon-actions/src/preview.js @@ -0,0 +1,42 @@ +import addons from '@kadira/storybook-addons'; +import stringify from 'json-stringify-safe'; +import { EVENT_ID } from './'; + +function _format(arg) { + if (arg && typeof arg.preventDefault !== 'undefined') { + return stringify('[SyntheticEvent]'); + } + return stringify(arg); +} + +export function action(name) { + const handler = function(..._args) { + const args = Array.from(_args).map(_format); + const channel = addons.getChannel(); + const randomId = Math.random().toString(16).slice(2); + channel.emit(EVENT_ID, { + id: randomId, + data: { name, args }, + }); + }; + + // some day when {[name]: function() {}} syntax is not transpiled by babel + // we can get rid of this eval as by ES2015 spec the above function gets the + // name `name`, but babel transpiles to Object.defineProperty which doesn't do + // the same. + // + // Ref: https://bocoup.com/weblog/whats-in-a-function-name + const fnName = name ? name.replace(/\W+/g, '_') : 'action'; + const named = eval(`(function ${fnName}() { return handler.apply(this, arguments) })`); + return named; +} + +export function decorateAction(decorators) { + return function(name) { + const callAction = action(name); + return function(..._args) { + const decorated = decorators.reduce((args, fn) => fn(args), _args); + callAction(...decorated); + }; + }; +} diff --git a/packages/addon-comments/.babelrc b/packages/addon-comments/.babelrc new file mode 100644 index 000000000000..4fbded95d44e --- /dev/null +++ b/packages/addon-comments/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["es2015", "stage-0", "react", "react-app"] +} diff --git a/packages/addon-comments/.scripts/get_gh_pages_url.js b/packages/addon-comments/.scripts/get_gh_pages_url.js new file mode 100644 index 000000000000..062c690d8bea --- /dev/null +++ b/packages/addon-comments/.scripts/get_gh_pages_url.js @@ -0,0 +1,11 @@ +// IMPORTANT +// --------- +// This is an auto generated file with React CDK. +// Do not modify this file. + +const parse = require('git-url-parse'); +var ghUrl = process.argv[2]; +const parsedUrl = parse(ghUrl); + +const ghPagesUrl = 'https://' + parsedUrl.owner + '.github.io/' + parsedUrl.name; +console.log(ghPagesUrl); diff --git a/packages/addon-comments/.scripts/mocha_runner.js b/packages/addon-comments/.scripts/mocha_runner.js new file mode 100644 index 000000000000..bc08ecc38ec8 --- /dev/null +++ b/packages/addon-comments/.scripts/mocha_runner.js @@ -0,0 +1,34 @@ +// IMPORTANT +// --------- +// This is an auto generated file with React CDK. +// Do not modify this file. +// Use `.scripts/user/pretest.js instead`. + +process.env.NODE_ENV = 'development'; +require('babel-core/register'); +require('babel-polyfill'); + +// Add jsdom support, which is required for enzyme. +var jsdom = require('jsdom').jsdom; + +var exposedProperties = ['window', 'navigator', 'document']; + +global.document = jsdom(''); +global.window = document.defaultView; +Object.keys(document.defaultView).forEach((property) => { + if (typeof global[property] === 'undefined') { + exposedProperties.push(property); + global[property] = document.defaultView[property]; + } +}); + +global.navigator = { + userAgent: 'node.js' +}; + +process.on('unhandledRejection', function (error) { + console.error('Unhandled Promise Rejection:'); + console.error(error && error.stack || error); +}); + +require('./user/pretest.js'); diff --git a/packages/addon-comments/.scripts/prepublish.sh b/packages/addon-comments/.scripts/prepublish.sh new file mode 100644 index 000000000000..8feda1abef38 --- /dev/null +++ b/packages/addon-comments/.scripts/prepublish.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# IMPORTANT +# --------- +# This is an auto generated file with React CDK. +# Do not modify this file. +# Use `.scripts/user/prepublish.sh instead`. + +echo "=> Transpiling 'src' into ES5 ..." +echo "" +rm -rf ./dist +NODE_ENV=production ./node_modules/.bin/babel --ignore tests,stories --plugins "transform-runtime" ./src --out-dir ./dist +echo "" +echo "=> Transpiling completed." + +. .scripts/user/prepublish.sh diff --git a/packages/addon-comments/.scripts/publish_storybook.sh b/packages/addon-comments/.scripts/publish_storybook.sh new file mode 100644 index 000000000000..f8457308528e --- /dev/null +++ b/packages/addon-comments/.scripts/publish_storybook.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# IMPORTANT +# --------- +# This is an auto generated file with React CDK. +# Do not modify this file. + +set -e # exit with nonzero exit code if anything fails + +# get GIT url + +GIT_URL=`git config --get remote.origin.url` +if [[ $GIT_URL == "" ]]; then + echo "This project is not configured with a remote git repo". + exit 1 +fi + +# clear and re-create the out directory +rm -rf .out || exit 0; +mkdir .out; + +# run our compile script, discussed above +build-storybook -o .out + +# go to the out directory and create a *new* Git repo +cd .out +git init + +# inside this git repo we'll pretend to be a new user +git config user.name "GH Pages Bot" +git config user.email "hello@ghbot.com" + +# The first and only commit to this new Git repo contains all the +# files present with the commit message "Deploy to GitHub Pages". +git add . +git commit -m "Deploy Storybook to GitHub Pages" + +# Force push from the current repo's master branch to the remote +# repo's gh-pages branch. (All previous history on the gh-pages branch +# will be lost, since we are overwriting it.) We redirect any output to +# /dev/null to hide any sensitive credential data that might otherwise be exposed. +git push --force --quiet $GIT_URL master:gh-pages > /dev/null 2>&1 +cd .. +rm -rf .out + +echo "" +echo "=> Storybook deployed to: `node .scripts/get_gh_pages_url.js $GIT_URL`" diff --git a/packages/addon-comments/.scripts/user/prepublish.sh b/packages/addon-comments/.scripts/user/prepublish.sh new file mode 100644 index 000000000000..fdb64997963e --- /dev/null +++ b/packages/addon-comments/.scripts/user/prepublish.sh @@ -0,0 +1 @@ +# Use this file to your own code to run at NPM `prepublish` event. diff --git a/packages/addon-comments/.scripts/user/pretest.js b/packages/addon-comments/.scripts/user/pretest.js new file mode 100644 index 000000000000..a81bd36c2255 --- /dev/null +++ b/packages/addon-comments/.scripts/user/pretest.js @@ -0,0 +1 @@ +// Use this file to setup any test utilities. diff --git a/packages/addon-comments/.storybook/addons.js b/packages/addon-comments/.storybook/addons.js new file mode 100644 index 000000000000..f777561483fe --- /dev/null +++ b/packages/addon-comments/.storybook/addons.js @@ -0,0 +1,9 @@ +// Uncomment to register defaults +// import '@kadira/storybook/addons'; + +// Use the line below to register this addon +// import '@kadira/storybook-addon-comments/register'; +import '@kadira/storybook-addon-actions/register'; +import '@kadira/storybook-database-cloud/register'; +import { init } from '../src/manager'; +init(); diff --git a/packages/addon-comments/.storybook/config.js b/packages/addon-comments/.storybook/config.js new file mode 100644 index 000000000000..d279dbf59011 --- /dev/null +++ b/packages/addon-comments/.storybook/config.js @@ -0,0 +1,12 @@ +// IMPORTANT +// --------- +// This is an auto generated file with React CDK. +// Do not modify this file. + +import { configure } from '@kadira/storybook'; + +function loadStories() { + require('../src/stories'); +} + +configure(loadStories, module); diff --git a/packages/addon-comments/CHANGELOG.md b/packages/addon-comments/CHANGELOG.md new file mode 100644 index 000000000000..18f26e279ec8 --- /dev/null +++ b/packages/addon-comments/CHANGELOG.md @@ -0,0 +1,97 @@ +## Changelog + +### v1.9.1 +27-October-2016 + +* Fix comment delete button [PR48](https://github.com/kadirahq/storybook-addon-comments/pull/48) +* Remove app not found console error [PR49](https://github.com/kadirahq/storybook-addon-comments/pull/49) + +### v1.9.0 +20-October-2016 + +* Show comments for public apps without logging in [PR46](https://github.com/kadirahq/storybook-addon-comments/pull/46) + +### v1.8.0 +17-October-2016 + +* Add border-radius for comment form [PR44](https://github.com/kadirahq/storybook-addon-comments/pull/44) + +### v1.7.2 +18-October-2016 + +* Add a loading icon for loading comments for the first time. [PR43](https://github.com/kadirahq/storybook-addon-comments/pull/43) +* Fix some minor bugs. + +### v1.7.1 +18-October-2016 + +Load comments just after we found the current user. +This fixes the issue of not loading comments for the current story just after reloaded. + +### v1.7.0 +14-October-2016 + +Improve console errors and signIn process when the user is loggedOut. + +### v1.7.0 +14-October-2016 + +* Add a confirm box when deleting components. [#38](https://github.com/kadirahq/storybook-addon-comments/pull/38) +* Add the user to the local cache when adding a comment. [#40](https://github.com/kadirahq/storybook-addon-comments/pull/40) + +### v1.6.1 +12-October-2016 + +Move a few packages from dev-deps to deps. + +### v1.6.0 +12-October-2016 + +* Implement a better workflow for local users [PR31](https://github.com/kadirahq/storybook-addon-comments/pull/31) +* Set the protected field to true. [PR30](https://github.com/kadirahq/storybook-addon-comments/pull/30) + +### v1.5.1 +12-October-2016 + +Fix a regression in the latest master. [PR33](https://github.com/kadirahq/storybook-addon-comments/pull/33) + +### v1.5.0 +12-October-2016 + +Add comment delete feature [PR23](https://github.com/kadirahq/storybook-addon-comments/pull/23) + +### v1.4.0 +12-October-2016 + +Add a cache invalidation system. [PR28](https://github.com/kadirahq/storybook-addon-comments/pull/28) + +### v1.3.0 +11-October-2016 + +Add markdown support. [PR24](https://github.com/kadirahq/storybook-addon-comments/pull/24) + +### v1.2.0 +11-October-2016 + +Add multiline comment support. [PR22](https://github.com/kadirahq/storybook-addon-comments/pull/22) + +### v1.1.1 + +Fix user info bug and remove unused files + +* Remove unused local addon-db files [PR19](https://github.com/kadirahq/storybook-addon-comments/pull/19) +* Update storybook dev dependency to auto export repo info [PR20](https://github.com/kadirahq/storybook-addon-comments/pull/20) +* Fix getUserInfo error by correcting method name [PR21](https://github.com/kadirahq/storybook-addon-comments/pull/21) + +### v1.1.0 + +Add some usability improvements. + +* Change login links to Storybook Hub. [PR12](https://github.com/kadirahq/storybook-addon-comments/pull/12) +* Remove full date text. [PR13](https://github.com/kadirahq/storybook-addon-comments/pull/13) +* Increase font size a bit. [PR14](https://github.com/kadirahq/storybook-addon-comments/pull/14) +* Implement a local comments cache. [PR16](https://github.com/kadirahq/storybook-addon-comments/pull/16) + +### v1.0.0 + +* First stable release diff --git a/packages/addon-comments/CONTRIBUTING.md b/packages/addon-comments/CONTRIBUTING.md new file mode 100644 index 000000000000..cfad20935a60 --- /dev/null +++ b/packages/addon-comments/CONTRIBUTING.md @@ -0,0 +1,12 @@ +# How to Contribute + +First of all, start the Storybook Hub Backend and get logged in. + +> Storybook Hub Backend is a private app and we'll update how to setup this addon for development without that dependency. + +Then start the storybook inside this app. + +```sh +npm run storybook +``` +Now you'll see a comments tab and you can start contrubuting. diff --git a/packages/addon-comments/LICENSE b/packages/addon-comments/LICENSE new file mode 100644 index 000000000000..c2d2a91d0e89 --- /dev/null +++ b/packages/addon-comments/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Your Name. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/addon-comments/README.md b/packages/addon-comments/README.md new file mode 100644 index 000000000000..814d23ff0488 --- /dev/null +++ b/packages/addon-comments/README.md @@ -0,0 +1,19 @@ +# Comments Addon + +This Storybook addon allows you to add comments for your stories. This addon works on [React Storybook](https://github.com/kadirahq/react-storybook). + +![](docs/screenshot.png) + +## Getting Started + +First, install the addon + +```shell +npm install -D @kadira/storybook-addon-comments +``` + +Add this line to your `addons.js` file (create this file inside your storybook config directory if needed). + +```js +import '@kadira/storybook-addon-comments/register'; +``` diff --git a/packages/addon-comments/docs/screenshot.png b/packages/addon-comments/docs/screenshot.png new file mode 100644 index 000000000000..edf3c999cf4a Binary files /dev/null and b/packages/addon-comments/docs/screenshot.png differ diff --git a/packages/addon-comments/manager.js b/packages/addon-comments/manager.js new file mode 100644 index 000000000000..68d13f4d0bf1 --- /dev/null +++ b/packages/addon-comments/manager.js @@ -0,0 +1,2 @@ +const manager = require('./dist/manager'); +manager.init(); diff --git a/packages/addon-comments/package.json b/packages/addon-comments/package.json new file mode 100644 index 000000000000..e8e1fe32c6de --- /dev/null +++ b/packages/addon-comments/package.json @@ -0,0 +1,69 @@ +{ + "name": "@kadira/storybook-addon-comments", + "version": "1.9.1", + "description": "Comments addon for Storybook", + "main": "preview.js", + "scripts": { + "prepublish": ". ./.scripts/prepublish.sh", + "test": "mocha --require .scripts/mocha_runner src/**/tests/**/*.js", + "storybook": "start-storybook -p 3006", + "storybook-local": "STORYBOOK_CLOUD_SERVER='http://localhost:3003/graphql' start-storybook -p 9010", + "storybook-remote": "start-storybook -p 3006", + "publish-storybook": "bash .scripts/publish_storybook.sh" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/kadirahq/storybook-addon-comments.git" + }, + "keywords": [ + "storybook" + ], + "license": "MIT", + "bugs": { + "url": "https://github.com/kadirahq/storybook-addon-comments/issues" + }, + "homepage": "https://github.com/kadirahq/storybook-addon-comments#readme", + "devDependencies": { + "react": "^15.5.4", + "react-dom": "^15.5.4", + "react-test-renderer": "^15.5.4", + "babel-loader": "^6.2.5", + "babel-polyfill": "^6.13.0", + "babel-preset-react-app": "^0.2.1", + "babel-cli": "^6.14.0", + "babel-core": "^6.14.0", + "babel-plugin-transform-runtime": "^6.15.0", + "babel-preset-es2015": "^6.14.0", + "babel-preset-react": "^6.11.1", + "babel-preset-stage-0": "^6.5.0", + "mocha": "^3.0.2", + "chai": "^3.5.0", + "sinon": "^1.17.6", + "enzyme": "^2.2.0", + "jsdom": "^9.5.0", + "git-url-parse": "^6.0.1", + "@kadira/storybook": "^2.24.1", + "@kadira/storybook-addons": "^1.5.0", + "@kadira/storybook-database-cloud": "^2.3.1", + "@kadira/storybook-deployer": "^1.2.0", + "@kadira/storybook-ui": "^3.4.1", + "chokidar": "^1.6.0", + "shelljs": "^0.7.4" + }, + "peerDependencies": { + "@kadira/storybook-addons": "^1.5.0", + "react": "*", + "react-dom": "*" + }, + "dependencies": { + "babel-runtime": "^6.11.6", + "deep-equal": "^1.0.1", + "events": "^1.1.1", + "insert-css": "^1.0.0", + "marked": "^0.3.6", + "moment": "^2.15.1", + "prop-types": "^15.5.7", + "react-render-html": "^0.1.6", + "react-textarea-autosize": "^4.0.5" + } +} diff --git a/packages/addon-comments/preview.js b/packages/addon-comments/preview.js new file mode 100644 index 000000000000..06f2f2a7e5bd --- /dev/null +++ b/packages/addon-comments/preview.js @@ -0,0 +1,2 @@ +const preview = require('./dist/preview'); +preview.init(); diff --git a/packages/addon-comments/register.js b/packages/addon-comments/register.js new file mode 100644 index 000000000000..94af5ec3ba83 --- /dev/null +++ b/packages/addon-comments/register.js @@ -0,0 +1,3 @@ +// NOTE: loading addons using this file is deprecated! +// please use manager.js and preview.js files instead +require('./manager'); diff --git a/packages/addon-comments/src/index.js b/packages/addon-comments/src/index.js new file mode 100644 index 000000000000..4a7863a01254 --- /dev/null +++ b/packages/addon-comments/src/index.js @@ -0,0 +1,25 @@ +import PropTypes from 'prop-types'; +import React from 'react'; + +const buttonStyles = { + border: '1px solid #eee', + borderRadius: 3, + backgroundColor: '#FFFFFF', + cursor: 'pointer', + fontSize: 15, + padding: '3px 10px', +}; + +const Button = ({ children, onClick, style = {} }) => ( + +); + +Button.propTypes = { + children: PropTypes.string.isRequired, + onClick: PropTypes.func, + style: PropTypes.object, +}; + +export default Button; diff --git a/packages/addon-comments/src/manager/components/CommentForm/index.js b/packages/addon-comments/src/manager/components/CommentForm/index.js new file mode 100644 index 000000000000..c2259db8fdcb --- /dev/null +++ b/packages/addon-comments/src/manager/components/CommentForm/index.js @@ -0,0 +1,89 @@ +import PropTypes from 'prop-types'; +import React, { Component } from 'react'; +import Textarea from 'react-textarea-autosize'; +import marked from 'marked'; +import style from './style'; + +const renderer = new marked.Renderer(); +renderer.heading = function(text) { + return text; +}; + +marked.setOptions({ + renderer, + gfm: true, + tables: false, + breaks: true, + pedantic: false, + sanitize: true, + smartLists: true, + smartypants: false, +}); + +export default class CommentForm extends Component { + constructor(props, ...args) { + super(props, ...args); + this.state = { text: '' }; + } + + onChange(e) { + const text = e.target.value; + this.setState({ text }); + } + + onSubmit() { + const { addComment } = this.props; + const text = this.state.text.trim(); + if (!text || text === '') { + return; + } + + addComment(marked(text)); + this.setState({ text: '' }); + } + + openLogin() { + const signInUrl = `https://hub.getstorybook.io/sign-in?redirectUrl=${encodeURIComponent(location.href)}`; + location.href = signInUrl; + } + + handleKeyDown(e) { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + this.onSubmit(); + } + } + + render() { + if (!this.props.user) { + return ( +
+