diff --git a/bower.json b/bower.json index 0532d32..f984e4d 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "ei", - "version": "1.1.0", + "version": "1.2.0", "authors": [ "ludafa@outlook.com" ], @@ -22,7 +22,7 @@ "output" ], "dependencies": { - "react": "~0.13.3", + "react": "0.14.0", "underscore": "~1.8.3", "es6-promise": "~2.2.0" } diff --git a/dist/App.js b/dist/App.js index 04f0004..182b448 100644 --- a/dist/App.js +++ b/dist/App.js @@ -5,7 +5,6 @@ define('ei/App', [ 'es6-promise', 'underscore', './util/invariant', - './locator', './events', './Router', './env' @@ -13,7 +12,6 @@ define('ei/App', [ var Promise = require('es6-promise').Promise; var u = require('underscore'); var invariant = require('./util/invariant'); - var locator = require('./locator'); var events = require('./events'); var Router = require('./Router'); var env = require('./env'); @@ -23,81 +21,41 @@ define('ei/App', [ u.extend(this, options); this.router = new Router(this.routes); } - App.prototype.bootstrap = function (initialState) { - invariant(env.isClient, 'app-should bootstrap on client only'); - events.emit('app-bootstrap'); - locator.init(this.mode).start().on('redirect', u.bind(this.onLocatorRedirect, this)); + App.prototype.execute = function (request, initialState, needRawState) { + events.emit('app-request'); var me = this; - var request = locator.createRequestFromLocation(); - var route = this.route(request); + var route = me.route(request); if (!route) { return Promise.reject({ status: 404 }); } return me.loadPage(route.page).then(function (Page) { - var page = new Page(initialState); - return initialState == null ? Promise.resolve(page.getInitialState(request)).then(function (state) { - page.init(state); - return page; - }) : page; - }).then(function (page) { - me.page = page; - page.render(me.main); - events.emit('app-ready'); - })['catch'](function (error) { - events.emit('app-execute-error', error); - throw error; - }); - }; - App.prototype.onLocatorRedirect = function (path, query) { - var request = { - path: path, - query: query - }; - var me = this; - var route = this.route(request); - if (!route) { - return; - } - return me.loadPage(route.page).then(function (Page) { - var page = me.page instanceof Page ? me.page : new Page(); - return Promise.resolve(page.getInitialState(request)).then(function (state) { - return page.init(state); - }); - }).then(function (page) { - if (me.page && me.page !== page) { - me.page.dispose(); - me.page = page; - } - page.render(me.main); - events.emit('app-page-switch-succeed'); - }); - }; - App.prototype.execute = function (request) { - events.emit('app-request'); - var route = this.route(request); - if (!route) { - return Promise.reject({ status: 404 }); - } - var page; - return this.loadPage(route.page).then(function (Page) { - page = new Page(); - return page.getInitialState(request); - }).then(function (state) { - if (env.isServer && request.xhr) { - events.emit('app-response-in-json'); + var page = env.isClient && me.page instanceof Page ? me.page : new Page(initialState); + return Promise.resolve(initialState == null ? page.getInitialState(request) : initialState).then(function (state) { + if (needRawState) { + events.emit('app-response-in-json'); + return { + state: state, + route: route + }; + } + events.emit('app-response-in-html'); + if (initialState == null) { + page.init(state); + events.emit('app-page-bootstrap'); + } + if (env.isClient) { + if (me.page && me.page !== page) { + me.page.dispose(); + events.emit('app-page-switch-succeed'); + } + me.page = page; + } + events.emit('app-page-entered'); return { - state: state, + page: page, route: route }; - } - events.emit('app-response-in-html'); - events.emit('app-page-bootstrap'); - page.init(state); - events.emit('app-page-bootstrap-succeed'); - return { - page: page, - route: route - }; + }); })['catch'](function (error) { events.emit('app-execute-error', error); throw error; @@ -145,7 +103,7 @@ define('ei/App', [ if (config) { events.emit('app-route-succeed'); } else { - events.emit('app-route-failed'); + events.emit('app-route-failed', request); } return config; }; diff --git a/dist/Container.js b/dist/Container.js index e944c88..9b443c2 100644 --- a/dist/Container.js +++ b/dist/Container.js @@ -5,7 +5,7 @@ define('ei/Container', [ 'underscore' ], function (require, exports, module) { var u = require('underscore'); - var Container = function () { + var Container = function Container() { this.boundCallbacks = {}; this.singletonCallbacks = {}; this.instantiatedSingletons = {}; diff --git a/dist/Emitter.js b/dist/Emitter.js index ac27280..f160aad 100644 --- a/dist/Emitter.js +++ b/dist/Emitter.js @@ -10,7 +10,7 @@ define('ei/Emitter', [ function Emitter() { } var mixins = { - on: function (name, handler) { + on: function on(name, handler) { var pool = this[EMITTER_LISTENER_POOL_ATTR]; if (!pool) { pool = this[EMITTER_LISTENER_POOL_ATTR] = {}; @@ -22,7 +22,7 @@ define('ei/Emitter', [ listeners.push(handler); return this; }, - off: function (name, handler) { + off: function off(name, handler) { var pool = this[EMITTER_LISTENER_POOL_ATTR]; if (!pool) { return this; @@ -47,16 +47,16 @@ define('ei/Emitter', [ } return this; }, - once: function (name, handler) { + once: function once(name, handler) { var me = this; - var onceHandler = function () { + var onceHandler = function onceHandler() { me.off(name, onceHandler); return handler.apply(me, arguments); }; me.on(name, onceHandler); return this; }, - emit: function (name) { + emit: function emit(name) { var pool = this[EMITTER_LISTENER_POOL_ATTR]; if (!pool) { return this; @@ -72,10 +72,10 @@ define('ei/Emitter', [ this[EMITTER_CURRENT_EVENT_ATTR] = null; return this; }, - getCurrentEvent: function () { + getCurrentEvent: function getCurrentEvent() { return this[EMITTER_CURRENT_EVENT_ATTR]; }, - destroyEvents: function () { + destroyEvents: function destroyEvents() { var pool = this[EMITTER_LISTENER_POOL_ATTR]; if (pool) { for (var type in pool) { diff --git a/dist/Page.js b/dist/Page.js index 0d90709..6cab3fa 100644 --- a/dist/Page.js +++ b/dist/Page.js @@ -4,7 +4,6 @@ define('ei/Page', [ 'module', 'underscore', 'react', - 'react-dom', './component/ConextProvider', './Context', './util/composeReducer', @@ -14,7 +13,6 @@ define('ei/Page', [ ], function (require, exports, module) { var u = require('underscore'); var React = require('react'); - var ReactDOM = require('react-dom'); var ContextProvider = require('./component/ConextProvider'); var Context = require('./Context'); var componseReducer = require('./util/composeReducer'); @@ -25,45 +23,42 @@ define('ei/Page', [ } Page.prototype = { constructor: Page, - initialize: function (initialState) { + initialize: function initialize(initialState) { this.context = new Context(initialState, componseReducer(this.reducer), u.map(this.middlewares, function (middlewareCreator) { return middlewareCreator(this); }, this)); }, middlewares: [], - init: function (initialState) { + init: function init(initialState) { this.dispatch({ type: 'INIT', payload: initialState }); return this; }, - createElement: function () { + createElement: function createElement() { var view = this.view; return React.createElement(ContextProvider, { ei: this.context }, function () { return React.createElement(view); }); }, - render: function (target) { - ReactDOM.render(this.createElement(), target); - return this; - }, - renderToString: function () { - return ReactDOM.renderToString(this.createElement()); - }, - getState: function () { + getState: function getState() { return this.context.getState(); }, - dispatch: function (action) { + setState: function setState(state) { + this.context.setState(state); + return this; + }, + dispatch: function dispatch(action) { events.emit('page-dispatch', action); this.emit('dispatch'); this.context.dispatch(action); return action; }, - getInitialState: function (request) { + getInitialState: function getInitialState(request) { return {}; }, - dispose: function () { + dispose: function dispose() { events.emit('page-dispose'); this.emit('dispose'); return this; diff --git a/dist/Reducer.js b/dist/Reducer.js index 6fcea96..2f0c2e7 100644 --- a/dist/Reducer.js +++ b/dist/Reducer.js @@ -8,7 +8,7 @@ define('ei/Reducer', [ var u = require('underscore'); var Dispatcher = require('./Dispatcher'); var mixins = { - bindAction: function (ActionCreator) { + bindAction: function bindAction(ActionCreator) { Dispatcher.addActionListener(ActionCreator.type, this); return this; } diff --git a/dist/Router.js b/dist/Router.js index 11923ed..671c62e 100644 --- a/dist/Router.js +++ b/dist/Router.js @@ -9,7 +9,7 @@ define('ei/Router', [ Router.prototype.route = function (request) { for (var i = this.routes.length - 1; i >= 0; i--) { var route = this.routes[i]; - if (route.path === request.path) { + if (route.path === request.pathname) { return route; } } diff --git a/dist/babelHelpers.js b/dist/babelHelpers.js index f47e940..a117a9d 100644 --- a/dist/babelHelpers.js +++ b/dist/babelHelpers.js @@ -3,15 +3,69 @@ define('ei/babelHelpers', [ 'exports', 'module' ], function (require, exports, module) { - (function (root, factory) { - if (typeof define === 'function' && define.amd) { - define(['exports'], factory); - } else if (typeof exports === 'object') { - factory(exports); + var babelHelpers = {}; + babelHelpers.inherits = function (subClass, superClass) { + if (typeof superClass !== 'function' && superClass !== null) { + throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); + } + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + enumerable: false, + writable: true, + configurable: true + } + }); + if (superClass) + Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; + }; + babelHelpers.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; + }; + }(); + babelHelpers.interopRequireDefault = function (obj) { + return obj && obj.__esModule ? obj : { 'default': obj }; + }; + babelHelpers.get = function get(object, property, receiver) { + if (object === null) + object = Function.prototype; + var desc = Object.getOwnPropertyDescriptor(object, property); + if (desc === undefined) { + var parent = Object.getPrototypeOf(object); + if (parent === null) { + return undefined; + } else { + return get(parent, property, receiver); + } + } else if ('value' in desc) { + return desc.value; } else { - factory(root.babelHelpers = {}); + var getter = desc.get; + if (getter === undefined) { + return undefined; + } + return getter.call(receiver); + } + }; + babelHelpers.classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError('Cannot call a class as a function'); } - }(this, function (global) { - var babelHelpers = global; - })); + }; + module.exports = babelHelpers; }); \ No newline at end of file diff --git a/dist/component/App.js b/dist/component/App.js new file mode 100644 index 0000000..eb35b3a --- /dev/null +++ b/dist/component/App.js @@ -0,0 +1,49 @@ +define('ei/component/App', [ + 'require', + 'exports', + 'module', + '../babelHelpers', + 'react', + '../App' +], function (require, exports, module) { + var babelHelpers = require('../babelHelpers'); + Object.defineProperty(exports, '__esModule', { value: true }); + var _react = require('react'); + var _react2 = babelHelpers.interopRequireDefault(_react); + var _App = require('../App'); + var _App2 = babelHelpers.interopRequireDefault(_App); + var App = function (_React$Component) { + babelHelpers.inherits(App, _React$Component); + function App(props) { + babelHelpers.classCallCheck(this, App); + babelHelpers.get(Object.getPrototypeOf(App.prototype), 'constructor', this).call(this, props); + this.app = new _App2['default']({ routes: this.props.routes }); + } + babelHelpers.createClass(App, [ + { + key: 'getChildContext', + value: function getChildContext() { + return { app: this.app }; + } + }, + { + key: 'render', + value: function render() { + return this.props.children; + } + }, + { + key: 'componentWillUnmount', + value: function componentWillUnmount() { + this.app = null; + } + } + ]); + return App; + }(_react2['default'].Component); + var PropTypes = _react2['default'].PropTypes; + App.propTypes = { routes: PropTypes.array.isRequired }; + App.childContextTypes = { app: PropTypes.object.isRequired }; + exports['default'] = App; + module.exports = exports['default']; +}); \ No newline at end of file diff --git a/dist/component/ConextProvider.js b/dist/component/ConextProvider.js index 73d128d..da0f640 100644 --- a/dist/component/ConextProvider.js +++ b/dist/component/ConextProvider.js @@ -6,12 +6,13 @@ define('ei/component/ConextProvider', [ ], function (require, exports, module) { var React = require('react'); var ContextProvider = React.createClass({ + displayName: 'ContextProvider', childContextTypes: { ei: React.PropTypes.object.isRequired }, propTypes: { ei: React.PropTypes.object.isRequired }, - getChildContext: function () { + getChildContext: function getChildContext() { return { ei: this.props.ei }; }, - render: function () { + render: function render() { var ei = this.props.ei; return this.props.children(ei.store, ei.dispatch); } diff --git a/dist/component/ContextConnector.js b/dist/component/ContextConnector.js index 968e0a8..f7bc637 100644 --- a/dist/component/ContextConnector.js +++ b/dist/component/ContextConnector.js @@ -12,25 +12,25 @@ define('ei/component/ContextConnector', [ children: React.PropTypes.func.isRequired, select: React.PropTypes.func.isRequired }, - getDataFromContext: function () { + getDataFromContext: function getDataFromContext() { return this.props.select(this.context.ei.store); }, - getInitialState: function () { + getInitialState: function getInitialState() { return { data: this.getDataFromContext() }; }, - componentDidMount: function () { + componentDidMount: function componentDidMount() { this.context.ei.addChangeListener(this.onStoreChange); }, - componentWillUnmount: function () { + componentWillUnmount: function componentWillUnmount() { this.context.ei.removeChangeListener(this.onStoreChange); }, - shouldComponentUpdate: function (nextProps, nextState) { + shouldComponentUpdate: function shouldComponentUpdate(nextProps, nextState) { return this.state.data !== nextState; }, - onStoreChange: function () { + onStoreChange: function onStoreChange() { this.setState({ data: this.getDataFromContext() }); }, - render: function () { + render: function render() { return this.props.children(this.state.data, this.context.ei.dispatch); } }); diff --git a/dist/component/Page.js b/dist/component/Page.js new file mode 100644 index 0000000..31cdc4b --- /dev/null +++ b/dist/component/Page.js @@ -0,0 +1,161 @@ +define('ei/component/Page', [ + 'require', + 'exports', + 'module', + '../babelHelpers', + 'react', + 'es6-promise' +], function (require, exports, module) { + var babelHelpers = require('../babelHelpers'); + Object.defineProperty(exports, '__esModule', { value: true }); + var _react = require('react'); + var _react2 = babelHelpers.interopRequireDefault(_react); + var _es6Promise = require('es6-promise'); + var Page = function (_React$Component) { + babelHelpers.inherits(Page, _React$Component); + function Page(props) { + babelHelpers.classCallCheck(this, Page); + babelHelpers.get(Object.getPrototypeOf(Page.prototype), 'constructor', this).call(this, props); + this.state = { + pendding: false, + ready: false, + error: null + }; + } + babelHelpers.createClass(Page, [ + { + key: 'render', + value: function render() { + var _state = this.state; + var ready = _state.ready; + var page = _state.page; + var error = _state.error; + var content = ''; + if (error) { + content = error.message; + } else if (ready) { + content = page.createElement(); + } else { + content = this.renderLoading(); + } + return _react2['default'].createElement('div', { className: 'ui-page' }, content); + } + }, + { + key: 'renderLoading', + value: function renderLoading() { + return _react2['default'].createElement('span', null, 'loading...'); + } + }, + { + key: 'componentDidMount', + value: function componentDidMount() { + var _props = this.props; + var initialState = _props.initialState; + var request = _props.request; + var app = this.context.app; + this.renderPage(app, request, initialState); + } + }, + { + key: 'renderPage', + value: function renderPage(app, request, initialState) { + var _this = this, _arguments = arguments; + var currentPage = this.state.page; + this.setState({ + pendding: true, + error: null + }); + var route = app.route(request); + if (!route) { + this.setState({ + ready: false, + error: { status: 404 }, + pendding: false, + page: null + }); + return; + } + app.loadPage(route.page).then(function (Page) { + var page = undefined; + if (currentPage && currentPage instanceof Page) { + page = currentPage; + } else { + page = new Page(); + page.on('*', function () { + var eventName = page.getCurrentEvent().split(/[\-_]/).map(function (term) { + return term.charAt(0).toUpperCase() + term.slice(1).toLowerCase(); + }).join(''); + var handlerName = 'on' + eventName; + var handler = _this.props[handlerName]; + if (typeof handler === 'function') { + handler.apply(null, _arguments); + } + }); + } + page.route = route; + return page; + }).then(function (page) { + if (initialState) { + page.setState(initialState); + return page; + } + return _es6Promise.Promise.resolve(page.getInitialState(request)).then(function (state) { + page.init(state); + return page; + }); + }).then(function (page) { + if (currentPage && currentPage !== page) { + currentPage.dispose(); + } + _this.setState({ + page: page, + ready: true, + pendding: false, + error: null + }); + })['catch'](function (error) { + _this.setState({ + error: error, + ready: false, + pendding: false, + page: null + }); + }); + } + }, + { + key: 'componentWillReceiveProps', + value: function componentWillReceiveProps(nextProps) { + var request = this.props.request; + var nextRequest = nextProps.request; + if (request.pathname !== nextRequest.pathname || request.search !== nextRequest.search) { + this.renderPage(this.context.app, nextRequest, null); + } + } + }, + { + key: 'componentWillUnmount', + value: function componentWillUnmount() { + var page = this.state.page; + if (page) { + page.dispose(); + } + } + } + ]); + return Page; + }(_react2['default'].Component); + var PropTypes = _react2['default'].PropTypes; + Page.contextTypes = { app: PropTypes.object.isRequired }; + Page.propTypes = { + request: PropTypes.shape({ + pathname: PropTypes.string.isRequired, + query: PropTypes.object, + search: PropTypes.string + }).isRequired, + initialState: PropTypes.any + }; + exports['default'] = Page; + module.exports = exports['default']; +}); \ No newline at end of file diff --git a/dist/locator.js b/dist/locator.js deleted file mode 100644 index 82235d5..0000000 --- a/dist/locator.js +++ /dev/null @@ -1,105 +0,0 @@ -define('ei/locator', [ - 'require', - 'exports', - 'module', - 'underscore', - './events', - './env', - './Emitter', - './util/invariant', - './url' -], function (require, exports, module) { - var u = require('underscore'); - var events = require('./events'); - var env = require('./env'); - var Emitter = require('./Emitter'); - var invariant = require('./util/invariant'); - var url = require('./url'); - function isHistorySupported() { - return !!window.history; - } - var hashLocator = { - getLocation: function () { - var href = location.href; - var index = href.indexOf('#'); - return index > 0 ? href.slice(index + 1) : ''; - }, - start: function () { - window.onhashchange = u.bind(onRequest, null, this.getLocation); - }, - stop: function () { - window.onhashchange = null; - }, - updateURL: function (url) { - if (this.getLocation() !== url) { - location.hash = url; - return true; - } - return false; - } - }; - var historyLocator = { - getLocation: function () { - return location.href; - }, - start: function () { - window.onpopstate = u.bind(onRequest, null, this.getLocation); - }, - stop: function () { - window.onpopstate = null; - }, - updateURL: function (url) { - var originUrl = location.pathname + location.search; - if (originUrl !== url) { - history.pushState(null, window.title, url); - onRequest(this.getLocation); - return true; - } - return false; - } - }; - var locator = { - init: function (mode) { - invariant(env.isClient, 'locator cannot run on server'); - if (env.isClient) { - this.mode = isHistorySupported() ? mode || 'history' : 'hash'; - } - return this; - }, - start: function () { - invariant(env.isClient, 'locator cannot run on server'); - var locator = this.mode === 'hash' ? hashLocator : historyLocator; - locator.start(); - this.locator = locator; - return this; - }, - stop: function () { - this.locator.stop(); - return this; - }, - redirect: function (path, query, force) { - invariant(env.isClient, 'redirect cannot run on server'); - events.emit('locator.redirect'); - var changed = this.locator.updateURL(url.makeUrl(path, query)); - var shouldEmitRedirect = changed || force; - if (shouldEmitRedirect) { - this.emit('redirect', path, query); - } - return shouldEmitRedirect; - }, - reload: function () { - var uri = this.createRequestFromLocation(); - this.redirect(uri.path, uri.query, true); - }, - createRequestFromLocation: function () { - var uri = this.mode === 'hash' ? location.hash.slice(1) : location.href; - return url.parse(uri); - } - }; - function onRequest(getLocation) { - var loc = getLocation(); - var uri = url.parse(loc); - locator.emit('redirect', uri.path, uri.query); - } - module.exports = Emitter.enable(locator); -}); \ No newline at end of file diff --git a/dist/main.js b/dist/main.js index 4878a5a..5e801bd 100644 --- a/dist/main.js +++ b/dist/main.js @@ -3,31 +3,16 @@ define('ei/main', [ 'exports', 'module', './App', - './env', './Page', './Container', - './locator', './events', './resource', './util/composeReducer', './util/connect' ], function (require, exports, module) { - var App = require('./App'); - var env = require('./env'); - var app; - exports.getApp = function (options) { - if (env.isServer) { - return new App(); - } - if (!app) { - app = new App(options); - } - return app; - }; exports.App = require('./App'); exports.Page = require('./Page'); exports.Container = require('./Container'); - exports.locator = require('./locator'); exports.events = require('./events'); exports.resource = require('./resource'); exports.composeReducer = require('./util/composeReducer'); diff --git a/dist/util/composeMiddleware.js b/dist/util/composeMiddleware.js index 06ab1c0..8c3efe9 100644 --- a/dist/util/composeMiddleware.js +++ b/dist/util/composeMiddleware.js @@ -13,6 +13,5 @@ define('ei/util/composeMiddleware', [ }; }, dispatch) : dispatch; } - ; module.exports = composeMiddleware; }); \ No newline at end of file diff --git a/dist/util/composeReducer.js b/dist/util/composeReducer.js index 0993794..16541f4 100644 --- a/dist/util/composeReducer.js +++ b/dist/util/composeReducer.js @@ -16,10 +16,12 @@ define('ei/util/composeReducer', [ var nextState = u.clone(state); var isChanged = false; for (var name in reducers) { - var value = state[name]; - var nextValue = nextState[name] = reducers[name](value, action); - if (nextValue !== value) { - isChanged = true; + if (reducers.hasOwnProperty(name)) { + var value = state[name]; + var nextValue = nextState[name] = reducers[name](value, action); + if (nextValue !== value) { + isChanged = true; + } } } return isChanged ? nextState : state; diff --git a/dist/util/connect.js b/dist/util/connect.js index 02635f7..bc2f2a1 100644 --- a/dist/util/connect.js +++ b/dist/util/connect.js @@ -17,7 +17,7 @@ define('ei/util/connect', [ var ContextFixer = React.createClass({ displayName: 'ContextFixer', select: bindSelectors(selector), - render: function () { + render: function render() { var props = this.props; return React.createElement(ContextConnector, { select: this.select }, function (state, dispatch) { return React.createElement(Component, u.extendOwn({}, state, props, actions ? bindActions(dispatch, actions) : null)); diff --git a/dist/util/invariant.js b/dist/util/invariant.js index 388f20b..1f11265 100644 --- a/dist/util/invariant.js +++ b/dist/util/invariant.js @@ -3,7 +3,7 @@ define('ei/util/invariant', [ 'exports', 'module' ], function (require, exports, module) { - var invariant = function (condition, format, a, b, c, d, e, f) { + var invariant = function invariant(condition, format, a, b, c, d, e, f) { if (condition) { return; } diff --git a/package.json b/package.json index 43491e5..054dc03 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ei", - "version": "1.1.0", + "version": "1.2.0", "main": "lib/main.js", "scripts": { "lint": "./node_modules/.bin/fecs lib --type=js", @@ -14,10 +14,12 @@ "repository": "https://github.com/jinzhubaofu/ei", "license": "ISC", "peerDependencies": { - "react": "0.13.3" + "react": "0.14.0" }, "dependencies": { "es6-promise": "^2.3.0", + "react": "^0.14.0", + "react-dom": "^0.14.0", "underscore": "^1.8.3" }, "readme": "readme.md", diff --git a/test/AppSpec.js b/test/AppSpec.js index d5cec90..fc8a0f6 100644 --- a/test/AppSpec.js +++ b/test/AppSpec.js @@ -53,14 +53,14 @@ describe('App', function () { }); var request = { - path: '/a' + pathname: '/a' }; var route = app.route(request); expect(route.name).toBe('a'); - request.path = '/b'; + request.pathname = '/b'; route = app.route(request); @@ -144,7 +144,7 @@ describe('App', function () { }, function (error) { - console.error(error); + // console.error(error); }); diff --git a/test/PageSpec.js b/test/PageSpec.js index 6c874ef..79a8e02 100644 --- a/test/PageSpec.js +++ b/test/PageSpec.js @@ -94,55 +94,55 @@ describe('Page', function () { expect(spy).toHaveBeenCalled(); }); + // TODO: 补充新的render测试 + // it('`renderToString`', function () { - it('`renderToString`', function () { + // var spy = jasmine.createSpy('reducer'); - var spy = jasmine.createSpy('reducer'); - - var SomePage = Page.extend({ + // var SomePage = Page.extend({ - reducer: spy, + // reducer: spy, - view: connect( - React.createClass({ + // view: connect( + // React.createClass({ - render: function () { + // render: function () { - expect(u.isFunction(this.props.add)).toBe(true); + // expect(u.isFunction(this.props.add)).toBe(true); - return React.createElement( - 'div', - null, - this.props.name - ); + // return React.createElement( + // 'div', + // null, + // this.props.name + // ); - } + // } - }), - true, - { - add: function () { - return { - type: 'add' - }; - } - } - ) + // }), + // true, + // { + // add: function () { + // return { + // type: 'add' + // }; + // } + // } + // ) - }); + // }); - var page = new SomePage({ + // var page = new SomePage({ - name: 'ludafa' + // name: 'ludafa' - }); + // }); - var string = page.renderToString(); + // var string = page.renderToString(); - expect(string).toMatch(/]*?>ludafa<\/div>/); + // expect(string).toMatch(/]*?>ludafa<\/div>/); - }); + // }); }); diff --git a/test/RouterSpec.js b/test/RouterSpec.js index d68cba5..a60b357 100644 --- a/test/RouterSpec.js +++ b/test/RouterSpec.js @@ -25,18 +25,18 @@ describe('Router', function () { var router = new Router(routes); - var route = router.route({path: '/a'}); + var route = router.route({pathname: '/a'}); expect(u.isObject(route)).toBe(true); expect(route.name).toBe('aaaa'); - route = router.route({path: '/b'}); + route = router.route({pathname: '/b'}); expect(route).toBe(void 0); route = router .addRoute({path: '/b', name: 'bbbb'}) - .route({path: '/b'}); + .route({pathname: '/b'}); expect(u.isObject(route)).toBe(true); expect(route.name).toBe('bbbb'); diff --git a/test/component/ConextProviderSpec.js b/test/component/ConextProviderSpec.js index 4c7e18a..9181113 100644 --- a/test/component/ConextProviderSpec.js +++ b/test/component/ConextProviderSpec.js @@ -5,6 +5,7 @@ var ContextProvider = require('../../lib/component/ConextProvider.js'); var React = require('react'); +var ReactDOM = require('react-dom/server'); describe('ContextProvider', function () { @@ -43,7 +44,7 @@ describe('ContextProvider', function () { } ); - var string = React.renderToStaticMarkup(provider); + var string = ReactDOM.renderToStaticMarkup(provider); expect(string).toBe('
'); diff --git a/test/component/ContextConnectorSpec.js b/test/component/ContextConnectorSpec.js index 3bb0848..4852ed5 100644 --- a/test/component/ContextConnectorSpec.js +++ b/test/component/ContextConnectorSpec.js @@ -6,6 +6,7 @@ var ConextProvider = require('../../lib/component/ConextProvider.js'); var ContextConnector = require('../../lib/component/ContextConnector.js'); var React = require('react'); +var ReactDOM = require('react-dom/server'); describe('ContextConnector', function () { @@ -48,7 +49,7 @@ describe('ContextConnector', function () { } ); - var string = React.renderToStaticMarkup(provider); + var string = ReactDOM.renderToStaticMarkup(provider); expect(string).toBe('
ludafa
'); diff --git a/test/locatorSpec.js b/test/locatorSpec.js deleted file mode 100644 index 64325eb..0000000 --- a/test/locatorSpec.js +++ /dev/null @@ -1,130 +0,0 @@ -/** - * @file locator spec - * @author Leon(leon@outlook.com) - */ - -var locator = require('../lib/locator.js'); -var u = require('underscore'); - -describe('locator', function () { - - beforeEach(function () { - - var history = { - pushState: function () { - } - }; - - global.window = { - title: 'ei', - history: history - }; - - global.location = { - href: 'http://www.baidu.com/test?a=1#b=2' - }; - - global.history = history; - - }); - - afterEach(function () { - - global.window = global.location = global.history = null; - - }); - - it('start/stop will take over the window.onpopstate handler', function () { - - locator.start(); - - expect(u.isFunction(window.onpopstate)).toBe(true); - - locator.stop(); - - expect(u.isFunction(window.onpopstate)).toBe(false); - - }); - - it('will fire redirect event while history changed', function () { - - locator.start(); - - var spy = jasmine.createSpy(); - - locator.on('redirect', spy); - - window.onpopstate(); - - expect(spy).toHaveBeenCalledWith('/test', {a: '1'}); - - }); - - it('redirect will trigger error thrown on server', function () { - - expect(function () { - - locator.redirect('/a'); - - }).toThrow(); - - }); - - it('' - + 'redirect will push a new record in history ' - + 'and trigger a `redirect` event on a history supported browser.', - function () { - - var env = require('../lib/env'); - - var isServer = env.isServer; - - env.isServer = false; - env.isClient = true; - - var spy = jasmine.createSpy(); - - global.history = { - pushState: spy - }; - - var redirectSpy = jasmine.createSpy('redirect'); - - locator.on('redirect', redirectSpy); - - locator.redirect('/test', {a: 1}); - - expect(spy).toHaveBeenCalledWith(null, window.title, '/test?a=1'); - expect(redirectSpy).toHaveBeenCalledWith('/test', {a: 1}); - - env.isServer = isServer; - env.isClient = !isServer; - - } - ); - - it('redirect will redirect the browser on a history unsupported browser', function () { - - var env = require('../lib/env'); - - var isServer = env.isServer; - - env.isServer = false; - env.isClient = true; - - var spy = jasmine.createSpy(); - - window.history = null; - - locator.on('redirect', spy); - - locator.redirect('/test', {a: 1}); - - expect(spy).toHaveBeenCalled(); - - env.isServer = isServer; - env.isClient = !isServer; - - }); - -}); diff --git a/test/util/connectSpec.js b/test/util/connectSpec.js index 3862eb7..6921d47 100644 --- a/test/util/connectSpec.js +++ b/test/util/connectSpec.js @@ -18,43 +18,45 @@ describe('connect', function () { }); - it('will connect to the context', function () { + // TODO: 补充新的render测试 - var spy = jasmine.createSpy('reducer'); + // it('will connect to the context', function () { - var SomePage = Page.extend({ + // var spy = jasmine.createSpy('reducer'); - reducer: spy, + // var SomePage = Page.extend({ - view: connect( - React.createClass({ + // reducer: spy, - render: function () { + // view: connect( + // React.createClass({ - return React.createElement( - 'div', - null, - this.props.name - ); + // render: function () { - } + // return React.createElement( + // 'div', + // null, + // this.props.name + // ); - }), - true - ) + // } - }); + // }), + // true + // ) - var page = new SomePage({ - name: 'ludafa' - }); + // }); - var string = page.renderToString(); + // var page = new SomePage({ + // name: 'ludafa' + // }); - expect(string).toMatch(/]*?>ludafa<\/div>/); + // var string = page.renderToString(); + // expect(string).toMatch(/]*?>ludafa<\/div>/); - }); + + // }); diff --git a/tool/BabelProcessor.js b/tool/BabelProcessor.js index 96a96b4..9358041 100644 --- a/tool/BabelProcessor.js +++ b/tool/BabelProcessor.js @@ -42,17 +42,19 @@ Babel.prototype.process = function (file, processContext, callback) { } ); + var code = result.code; + if (result.metadata.usedHelpers.length) { - var prefix = 'var babelHelpers = require("' + babelHelperRelativePath + '");\n' - file.setData(prefix + result.code); + var prefix = 'var babelHelpers = require("' + babelHelperRelativePath + '");\n'; + code = prefix + code; processContext.usedHelpers = _.union( processContext.usedHelpers, result.metadata.usedHelpers ); - - console.log(processContext.usedHelpers); } + file.setData(code); + processContext.addFileLink(filePath, file.outputPath); callback(); @@ -61,9 +63,13 @@ Babel.prototype.process = function (file, processContext, callback) { Babel.prototype.afterAll = function (processContext) { + if (!processContext.usedHelpers.length) { + return; + } + var usedHelpers = babel.buildExternalHelpers( processContext.usedHelpers, - 'umd' + 'var' ); var baseDir = processContext.baseDir; @@ -71,7 +77,9 @@ Babel.prototype.afterAll = function (processContext) { var fullPath = path.join(baseDir, relativePath); var helperFile = new FileInfo({ - data: usedHelpers, + data: '' + + usedHelpers + + '\nmodule.exports = babelHelpers;', extname: 'js', path: relativePath, fullPath: fullPath, diff --git a/tool/build-amd.sh b/tool/build-amd.sh index 2cb9e41..6668711 100755 --- a/tool/build-amd.sh +++ b/tool/build-amd.sh @@ -3,3 +3,4 @@ rm -rf dist edp build -f mv output/dist dist +rm -rf output