Working React+Redux template

This commit is contained in:
SteveSandersonMS
2016-03-07 14:32:36 +00:00
parent ec9337754f
commit cf7a519919
26 changed files with 1475 additions and 131 deletions

View File

@@ -1,15 +1,24 @@
import 'bootstrap';
import 'bootstrap/dist/css/bootstrap.css';
import './css/site.css';
import 'bootstrap/dist/css/bootstrap.css';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { browserHistory, Router } from 'react-router';
import { Provider } from 'react-redux';
import { syncHistoryWithStore } from 'react-router-redux';
import routes from './routes';
import configureStore from './configureStore';
import { ApplicationState } from './store';
// Get the application-wide store instance, prepopulating with state from the server where available.
const initialState = (window as any).initialReduxState as ApplicationState;
const store = configureStore(initialState);
const history = syncHistoryWithStore(browserHistory, store);
// This code starts up the React app when it runs in a browser. It sets up the routing configuration
// and injects the app into a DOM element.
ReactDOM.render(
<Router history={ browserHistory } children={ routes } />,
<Provider store={ store }>
<Router history={ history } children={ routes } />
</Provider>,
document.getElementById('react-app')
);

View File

@@ -1,30 +1,27 @@
import * as React from 'react';
import { Link } from 'react-router';
import { provide } from 'redux-typed';
import { ApplicationState } from '../store';
import * as CounterStore from '../store/Counter';
interface CounterState {
currentCount: number;
}
export class Counter extends React.Component<any, CounterState> {
constructor() {
super();
this.state = { currentCount: 0 };
}
class Counter extends React.Component<CounterProps, void> {
public render() {
return <div>
<h1>Counter</h1>
<p>This is a simple example of a React component.</p>
<p>Current count: <strong>{ this.state.currentCount }</strong></p>
<p>Current count: <strong>{ this.props.count }</strong></p>
<button onClick={ () => { this.incrementCounter() } }>Increment</button>
<button onClick={ () => { this.props.increment() } }>Increment</button>
</div>;
}
incrementCounter() {
this.setState({
currentCount: this.state.currentCount + 1
});
}
}
// Build the CounterProps type, which allows the component to be strongly typed
const provider = provide(
(state: ApplicationState) => state.counter, // Select which part of global state maps to this component
CounterStore.actionCreators // Select which action creators should be exposed to this component
);
type CounterProps = typeof provider.allProps;
export default provider.connect(Counter);

View File

@@ -1,36 +1,36 @@
import * as React from 'react';
import { Link } from 'react-router';
import { provide } from 'redux-typed';
import { ApplicationState } from '../store';
import * as WeatherForecastsState from '../store/WeatherForecasts';
interface FetchDataExampleState {
forecasts: WeatherForecast[];
loading: boolean;
interface RouteParams {
startDateIndex: string;
}
export class FetchData extends React.Component<any, FetchDataExampleState> {
constructor() {
super();
this.state = { forecasts: [], loading: true };
class FetchData extends React.Component<WeatherForecastProps, void> {
componentWillMount() {
// This method runs when the component is first added to the page
let startDateIndex = parseInt(this.props.params.startDateIndex) || 0;
this.props.requestWeatherForecasts(startDateIndex);
}
fetch('/api/SampleData/WeatherForecasts')
.then(response => response.json())
.then((data: WeatherForecast[]) => {
this.setState({ forecasts: data, loading: false });
});
componentWillReceiveProps(nextProps: WeatherForecastProps) {
// This method runs when incoming props (e.g., route params) change
let startDateIndex = parseInt(nextProps.params.startDateIndex) || 0;
this.props.requestWeatherForecasts(startDateIndex);
}
public render() {
let contents = this.state.loading
? <p><em>Loading...</em></p>
: FetchData.renderForecastsTable(this.state.forecasts);
return <div>
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from the server.</p>
{ contents }
<p>For more sophisticated applications, consider an architecture such as Redux or Flux for managing state. You can generate an ASP.NET Core application with React and Redux using <code>dotnet new aspnet/spa/reactredux</code> instead of using this template.</p>
<p>This component demonstrates fetching data from the server and working with URL parameters.</p>
{ this.renderForecastsTable() }
{ this.renderPagination() }
</div>;
}
private static renderForecastsTable(forecasts: WeatherForecast[]) {
private renderForecastsTable() {
return <table className='table'>
<thead>
<tr>
@@ -41,7 +41,7 @@ export class FetchData extends React.Component<any, FetchDataExampleState> {
</tr>
</thead>
<tbody>
{forecasts.map(forecast =>
{this.props.forecasts.map(forecast =>
<tr key={ forecast.dateFormatted }>
<td>{ forecast.dateFormatted }</td>
<td>{ forecast.temperatureC }</td>
@@ -52,11 +52,23 @@ export class FetchData extends React.Component<any, FetchDataExampleState> {
</tbody>
</table>;
}
private renderPagination() {
let prevStartDateIndex = this.props.startDateIndex - 5;
let nextStartDateIndex = this.props.startDateIndex + 5;
return <p className='clearfix text-center'>
<Link className='btn btn-default pull-left' to={ `/fetchdata/${ prevStartDateIndex }` }>Previous</Link>
<Link className='btn btn-default pull-right' to={ `/fetchdata/${ nextStartDateIndex }` }>Next</Link>
{ this.props.isLoading ? <span>Loading...</span> : [] }
</p>;
}
}
interface WeatherForecast {
dateFormatted: string;
temperatureC: number;
temperatureF: number;
summary: string;
}
// Build the WeatherForecastProps type, which allows the component to be strongly typed
const provider = provide(
(state: ApplicationState) => state.weatherForecasts, // Select which part of global state maps to this component
WeatherForecastsState.actionCreators // Select which action creators should be exposed to this component
).withExternalProps<{ params: RouteParams }>(); // Also include a 'params' property on WeatherForecastProps
type WeatherForecastProps = typeof provider.allProps;
export default provider.connect(FetchData);

View File

@@ -1,13 +1,13 @@
import * as React from 'react';
export class Home extends React.Component<any, void> {
export default class Home extends React.Component<any, void> {
public render() {
return <div>
<h1>Hello, world!</h1>
<p>Welcome to your new single-page application, built with:</p>
<ul>
<li><a href='https://get.asp.net/'>ASP.NET Core</a> and <a href='https://msdn.microsoft.com/en-us/library/67ef8sbd.aspx'>C#</a> for cross-platform server-side code</li>
<li><a href='https://facebook.github.io/react/'>React</a> and <a href='http://www.typescriptlang.org/'>TypeScript</a> for client-side code</li>
<li><a href='https://facebook.github.io/react/'>React</a>, <a href='http://redux.js.org'>Redux</a>, and <a href='http://www.typescriptlang.org/'>TypeScript</a> for client-side code</li>
<li><a href='https://webpack.github.io/'>Webpack</a> for building and bundling client-side resources</li>
<li><a href='http://getbootstrap.com/'>Bootstrap</a> for layout and styling</li>
</ul>
@@ -18,11 +18,6 @@ export class Home extends React.Component<any, void> {
<li><strong>Hot module replacement</strong>. In development mode, you don't even need to reload the page after making most changes. Within seconds of saving changes to files, rebuilt CSS and React components will be injected directly into your running application, preserving its live state.</li>
<li><strong>Efficient production builds</strong>. In production mode, development-time features are disabled, and the <code>webpack</code> build tool produces minified static CSS and JavaScript files.</li>
</ul>
<h4>Going further</h4>
<p>
For larger applications, or for server-side prerendering (i.e., for <em>isomorphic</em> or <em>universal</em> applications), you should consider using a Flux/Redux-like architecture.
You can generate an ASP.NET Core application with React and Redux using <code>dotnet new aspnet/spa/reactredux</code> instead of using this template.
</p>
</div>;
}
}

View File

@@ -0,0 +1,33 @@
import { createStore, applyMiddleware, compose, combineReducers } from 'redux';
import * as thunkModule from 'redux-thunk';
import { routerReducer } from 'react-router-redux';
import * as Store from './store';
import { typedToPlain } from 'redux-typed';
export default function configureStore(initialState?: Store.ApplicationState) {
// Build middleware. These are functions that can process the actions before they reach the store.
const thunk = (thunkModule as any).default; // Workaround for TypeScript not importing thunk module as expected
const devToolsExtension = (window as any).devToolsExtension; // If devTools is installed, connect to it
const createStoreWithMiddleware = compose(
applyMiddleware(thunk, typedToPlain),
devToolsExtension ? devToolsExtension() : f => f
)(createStore);
// Combine all reducers and instantiate the app-wide store instance
const allReducers = buildRootReducer(Store.reducers);
const store = createStoreWithMiddleware(allReducers, initialState) as Redux.Store;
// Enable Webpack hot module replacement for reducers
if (module.hot) {
module.hot.accept('./store', () => {
const nextRootReducer = require<typeof Store>('./store');
store.replaceReducer(buildRootReducer(nextRootReducer.reducers));
});
}
return store;
}
function buildRootReducer(allReducers) {
return combineReducers(Object.assign({}, allReducers, { routing: routerReducer })) as Redux.Reducer;
}

View File

@@ -1,12 +1,14 @@
import * as React from 'react';
import { Router, Route, HistoryBase } from 'react-router';
import { Layout } from './components/Layout';
import { Home } from './components/Home';
import { FetchData } from './components/FetchData';
import { Counter } from './components/Counter';
import Home from './components/Home';
import FetchData from './components/FetchData';
import Counter from './components/Counter';
export default <Route component={ Layout }>
<Route path='/' components={{ body: Home }} />
<Route path='/counter' components={{ body: Counter }} />
<Route path='/fetchdata' components={{ body: FetchData }} />
<Route path='/fetchdata' components={{ body: FetchData }}>
<Route path='(:startDateIndex)' /> { /* Optional route segment that does not affect NavMenu highlighting */ }
</Route>
</Route>;

View File

@@ -0,0 +1,40 @@
import { typeName, isActionType, Action, Reducer } from 'redux-typed';
import { ActionCreator } from './';
// -----------------
// STATE - This defines the type of data maintained in the Redux store.
export interface CounterState {
count: number;
}
// -----------------
// ACTIONS - These are serializable (hence replayable) descriptions of state transitions.
// They do not themselves have any side-effects; they just describe something that is going to happen.
// Use @typeName and isActionType for type detection that works even after serialization/deserialization.
@typeName("INCREMENT_COUNT")
class IncrementCount extends Action {
}
// ----------------
// ACTION CREATORS - These are functions exposed to UI components that will trigger a state transition.
// They don't directly mutate state, but they can have external side-effects (such as loading data).
export const actionCreators = {
increment: (): ActionCreator => (dispatch, getState) => {
dispatch(new IncrementCount());
}
};
// ----------------
// REDUCER - For a given state and action, returns the new state. To support time travel, this must not mutate the old state.
export const reducer: Reducer<CounterState> = (state, action) => {
if (isActionType(action, IncrementCount)) {
return { count: state.count + 1 };
}
// For unrecognized actions (or in cases where actions have no effect), must return the existing state
// (or default initial state if none was supplied)
return state || { count: 0 };
};

View File

@@ -0,0 +1,76 @@
import { fetch } from 'domain-task/fetch';
import { typeName, isActionType, Action, Reducer } from 'redux-typed';
import { ActionCreator } from './';
// -----------------
// STATE - This defines the type of data maintained in the Redux store.
export interface WeatherForecastsState {
isLoading: boolean;
startDateIndex: number;
forecasts: WeatherForecast[];
}
export interface WeatherForecast {
dateFormatted: string;
temperatureC: number;
temperatureF: number;
summary: string;
}
// -----------------
// ACTIONS - These are serializable (hence replayable) descriptions of state transitions.
// They do not themselves have any side-effects; they just describe something that is going to happen.
// Use @typeName and isActionType for type detection that works even after serialization/deserialization.
@typeName("REQUEST_WEATHER_FORECASTS")
class RequestWeatherForecasts extends Action {
constructor(public startDateIndex: number) {
super();
}
}
@typeName("RECEIVE_WEATHER_FORECASTS")
class ReceiveWeatherForecasts extends Action {
constructor(public startDateIndex: number, public forecasts: WeatherForecast[]) {
super();
}
}
// ----------------
// ACTION CREATORS - These are functions exposed to UI components that will trigger a state transition.
// They don't directly mutate state, but they can have external side-effects (such as loading data).
export const actionCreators = {
requestWeatherForecasts: (startDateIndex: number): ActionCreator => (dispatch, getState) => {
// Only load data if it's something we don't already have (and are not already loading)
if (startDateIndex !== getState().weatherForecasts.startDateIndex) {
fetch(`/api/SampleData/WeatherForecasts?startDateIndex=${ startDateIndex }`)
.then(response => response.json())
.then((data: WeatherForecast[]) => {
dispatch(new ReceiveWeatherForecasts(startDateIndex, data));
});
dispatch(new RequestWeatherForecasts(startDateIndex));
}
}
};
// ----------------
// REDUCER - For a given state and action, returns the new state. To support time travel, this must not mutate the old state.
const unloadedState: WeatherForecastsState = { startDateIndex: null, forecasts: [], isLoading: false };
export const reducer: Reducer<WeatherForecastsState> = (state, action) => {
if (isActionType(action, RequestWeatherForecasts)) {
return { startDateIndex: action.startDateIndex, isLoading: true, forecasts: state.forecasts };
} else if (isActionType(action, ReceiveWeatherForecasts)) {
// Only accept the incoming data if it matches the most recent request. This ensures we correctly
// handle out-of-order responses.
if (action.startDateIndex === state.startDateIndex) {
return { startDateIndex: action.startDateIndex, forecasts: action.forecasts, isLoading: false };
}
}
// For unrecognized actions (or in cases where actions have no effect), must return the existing state
// (or default initial state if none was supplied)
return state || unloadedState;
};

View File

@@ -0,0 +1,21 @@
import { ActionCreatorGeneric } from 'redux-typed';
import * as WeatherForecasts from './WeatherForecasts';
import * as Counter from './Counter';
// The top-level state object
export interface ApplicationState {
counter: Counter.CounterState,
weatherForecasts: WeatherForecasts.WeatherForecastsState
}
// Whenever an action is dispatched, Redux will update each top-level application state property using
// the reducer with the matching name. It's important that the names match exactly, and that the reducer
// acts on the corresponding ApplicationState property type.
export const reducers = {
counter: Counter.reducer,
weatherForecasts: WeatherForecasts.reducer
};
// This type can be used as a hint on action creators so that its 'dispatch' and 'getState' params are
// correctly typed to match your store.
export type ActionCreator = ActionCreatorGeneric<ApplicationState>;

View File

@@ -15,12 +15,12 @@ namespace WebApplicationBasic.Controllers
};
[HttpGet, Route("[action]")]
public IEnumerable<WeatherForecast> WeatherForecasts()
public IEnumerable<WeatherForecast> WeatherForecasts(int startDateIndex)
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
DateFormatted = DateTime.Now.AddDays(index).ToString("d"),
DateFormatted = DateTime.Now.AddDays(index + startDateIndex).ToString("d"),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
});

View File

@@ -28,6 +28,11 @@
"domain-task": "^1.0.0",
"react": "^0.14.7",
"react-dom": "^0.14.7",
"react-router": "^2.0.0"
"react-redux": "^4.4.0",
"react-router": "^2.0.0",
"react-router-redux": "^4.0.0",
"redux": "^3.3.1",
"redux-thunk": "^2.0.1",
"redux-typed": "^1.0.0"
}
}

View File

@@ -3,6 +3,7 @@
"moduleResolution": "node",
"target": "es6",
"jsx": "preserve",
"experimentalDecorators": true,
"sourceMap": true,
"skipDefaultLibCheck": true
},

View File

@@ -6,19 +6,40 @@
"bundle": "typings/tsd.d.ts",
"installed": {
"react/react.d.ts": {
"commit": "dade4414712ce84e3c63393f1aae407e9e7e6af7"
"commit": "9f0f926a12026287b5a4a229e5672c01e7549313"
},
"react-router/react-router.d.ts": {
"commit": "dade4414712ce84e3c63393f1aae407e9e7e6af7"
"commit": "9f0f926a12026287b5a4a229e5672c01e7549313"
},
"react/react-dom.d.ts": {
"commit": "dade4414712ce84e3c63393f1aae407e9e7e6af7"
},
"react-router/history.d.ts": {
"commit": "dade4414712ce84e3c63393f1aae407e9e7e6af7"
"commit": "9f0f926a12026287b5a4a229e5672c01e7549313"
},
"whatwg-fetch/whatwg-fetch.d.ts": {
"commit": "dade4414712ce84e3c63393f1aae407e9e7e6af7"
},
"react-redux/react-redux.d.ts": {
"commit": "9f0f926a12026287b5a4a229e5672c01e7549313"
},
"redux/redux.d.ts": {
"commit": "9f0f926a12026287b5a4a229e5672c01e7549313"
},
"react-router-redux/react-router-redux.d.ts": {
"commit": "9f0f926a12026287b5a4a229e5672c01e7549313"
},
"redux-thunk/redux-thunk.d.ts": {
"commit": "9f0f926a12026287b5a4a229e5672c01e7549313"
},
"uglify-js/uglify-js.d.ts": {
"commit": "9f0f926a12026287b5a4a229e5672c01e7549313"
},
"source-map/source-map.d.ts": {
"commit": "9f0f926a12026287b5a4a229e5672c01e7549313"
},
"webpack/webpack-env.d.ts": {
"commit": "9f0f926a12026287b5a4a229e5672c01e7549313"
}
}
}

View File

@@ -0,0 +1,68 @@
// Type definitions for react-redux 4.4.0
// Project: https://github.com/rackt/react-redux
// Definitions by: Qubo <https://github.com/tkqubo>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
/// <reference path="../react/react.d.ts" />
/// <reference path="../redux/redux.d.ts" />
declare module "react-redux" {
import { ComponentClass, Component, StatelessComponent } from 'react';
import { Store, Dispatch, ActionCreator } from 'redux';
export interface ComponentConstructDecorator<P> {
<TComponentConstruct extends (ComponentClass<P>|StatelessComponent<P>)>(component: TComponentConstruct): TComponentConstruct
}
/**
* Connects a React component to a Redux store.
* @param mapStateToProps
* @param mapDispatchToProps
* @param mergeProps
* @param options
*/
export function connect<P>(mapStateToProps?: MapStateToProps,
mapDispatchToProps?: MapDispatchToPropsFunction|MapDispatchToPropsObject,
mergeProps?: MergeProps,
options?: Options): ComponentConstructDecorator<P>;
interface MapStateToProps {
(state: any, ownProps?: any): any;
}
interface MapDispatchToPropsFunction {
(dispatch: Dispatch, ownProps?: any): any;
}
interface MapDispatchToPropsObject {
[name: string]: ActionCreator;
}
interface MergeProps {
(stateProps: any, dispatchProps: any, ownProps: any): any;
}
interface Options {
/**
* If true, implements shouldComponentUpdate and shallowly compares the result of mergeProps,
* preventing unnecessary updates, assuming that the component is a “pure” component
* and does not rely on any input or state other than its props and the selected Redux stores state.
* Defaults to true.
* @default true
*/
pure: boolean;
}
export interface Property {
/**
* The single Redux store in your application.
*/
store?: Store;
children?: Function;
}
/**
* Makes the Redux store available to the connect() calls in the component hierarchy below.
*/
export class Provider extends Component<Property, {}> { }
}

View File

@@ -0,0 +1,62 @@
// Type definitions for react-router-redux v4.0.0
// Project: https://github.com/rackt/react-router-redux
// Definitions by: Isman Usoh <http://github.com/isman-usoh>, Noah Shipley <https://github.com/noah79>, Dimitri Rosenberg <https://github.com/rosendi>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
/// <reference path="../redux/redux.d.ts" />
/// <reference path="../react-router/react-router.d.ts"/>
declare namespace ReactRouterRedux {
import R = Redux;
import H = HistoryModule;
const CALL_HISTORY_METHOD: string;
const LOCATION_CHANGE: string;
const push: PushAction;
const replace: ReplaceAction;
const go: GoAction;
const goBack: GoForwardAction;
const goForward: GoBackAction;
const routerActions: RouteActions;
type LocationDescriptor = H.Location | H.Path;
type PushAction = (nextLocation: LocationDescriptor) => RouterAction;
type ReplaceAction = (nextLocation: LocationDescriptor) => RouterAction;
type GoAction = (n: number) => RouterAction;
type GoForwardAction = () => RouterAction;
type GoBackAction = () => RouterAction;
type RouterAction = {
type: string
payload?: any
}
interface RouteActions {
push: PushAction;
replace: ReplaceAction;
go: GoAction;
goForward: GoForwardAction;
goBack: GoBackAction;
}
interface ReactRouterReduxHistory extends H.History {
unsubscribe(): void;
}
interface DefaultSelectLocationState extends Function {
(state: any): any;
}
interface SyncHistoryWithStoreOptions {
selectLocationState?: DefaultSelectLocationState;
adjustUrlOnReplay?: boolean;
}
function routerReducer(state?: any, options?: any): R.Reducer;
function syncHistoryWithStore(history: H.History, store: R.Store, options?: SyncHistoryWithStoreOptions): ReactRouterReduxHistory;
function routerMiddleware(history: H.History): R.Middleware;
}
declare module "react-router-redux" {
export = ReactRouterRedux;
}

View File

@@ -1,6 +1,6 @@
// Type definitions for history v1.13.1
// Type definitions for history v2.0.0
// Project: https://github.com/rackt/history
// Definitions by: Sergey Buturlakin <http://github.com/sergey-buturlakin>
// Definitions by: Sergey Buturlakin <https://github.com/sergey-buturlakin>, Nathan Brown <https://github.com/ngbrown>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
@@ -17,21 +17,25 @@ declare namespace HistoryModule {
type CreateHistoryEnhancer<T, E> = (createHistory: CreateHistory<T>) => CreateHistory<T & E>
interface History {
listenBefore(hook: TransitionHook): Function
listen(listener: LocationListener): Function
listenBefore(hook: TransitionHook): () => void
listen(listener: LocationListener): () => void
transitionTo(location: Location): void
pushState(state: LocationState, path: Path): void
replaceState(state: LocationState, path: Path): void
push(path: Path): void
replace(path: Path): void
push(path: LocationDescriptor): void
replace(path: LocationDescriptor): void
go(n: number): void
goBack(): void
goForward(): void
createKey(): LocationKey
createPath(path: Path): Path
createHref(path: Path): Href
createLocation(path?: Path, state?: LocationState, action?: Action, key?: LocationKey): Location
createPath(path: LocationDescriptor): Path
createHref(path: LocationDescriptor): Href
createLocation(path?: LocationDescriptor, action?: Action, key?: LocationKey): Location
/** @deprecated use a location descriptor instead */
createLocation(path?: Path, state?: LocationState, action?: Action, key?: LocationKey): Location
/** @deprecated use location.key to save state instead */
pushState(state: LocationState, path: Path): void
/** @deprecated use location.key to save state instead */
replaceState(state: LocationState, path: Path): void
/** @deprecated use location.key to save state instead */
setState(state: LocationState): void
/** @deprecated use listenBefore instead */
@@ -40,19 +44,42 @@ declare namespace HistoryModule {
unregisterTransitionHook(hook: TransitionHook): void
}
type HistoryOptions = Object
type HistoryOptions = {
getCurrentLocation?: () => Location
finishTransition?: (nextLocation: Location) => boolean
saveState?: (key: LocationKey, state: LocationState) => void
go?: (n: number) => void
getUserConfirmation?: (message: string, callback: (result: boolean) => void) => void
keyLength?: number
queryKey?: string | boolean
stringifyQuery?: (obj: any) => string
parseQueryString?: (str: string) => any
basename?: string
entries?: string | [any]
current?: number
}
type Href = string
type Location = {
pathname: Pathname
search: QueryString
search: Search
query: Query
state: LocationState
action: Action
key: LocationKey
basename?: string
}
type LocationDescriptorObject = {
pathname?: Pathname
search?: Search
query?: Query
state?: LocationState
}
type LocationDescriptor = LocationDescriptorObject | Path
type LocationKey = string
type LocationListener = (location: Location) => void
@@ -67,11 +94,13 @@ declare namespace HistoryModule {
type QueryString = string
type TransitionHook = (location: Location, callback: Function) => any
type Search = string
type TransitionHook = (location: Location, callback: (result: any) => void) => any
interface HistoryBeforeUnload {
listenBeforeUnload(hook: BeforeUnloadHook): Function
listenBeforeUnload(hook: BeforeUnloadHook): () => void
}
interface HistoryQueries {
@@ -168,6 +197,18 @@ declare module "history/lib/actions" {
}
declare module "history/lib/DOMUtils" {
export function addEventListener(node: EventTarget, event: string, listener: EventListenerOrEventListenerObject): void;
export function removeEventListener(node: EventTarget, event: string, listener: EventListenerOrEventListenerObject): void;
export function getHashPath(): string;
export function replaceHashPath(path: string): void;
export function getWindowPath(): string;
export function go(n: number): void;
export function getUserConfirmation(message: string, callback: (result: boolean) => void): void;
export function supportsHistory(): boolean;
export function supportsGoWithoutReloadUsingHash(): boolean;
}
declare module "history" {

View File

@@ -1,6 +1,6 @@
// Type definitions for react-router v2.0.0-rc5
// Type definitions for react-router v2.0.0
// Project: https://github.com/rackt/react-router
// Definitions by: Sergey Buturlakin <http://github.com/sergey-buturlakin>, Yuichi Murata <https://github.com/mrk21>, Václav Ostrožlík <https://github.com/vasek17>
// Definitions by: Sergey Buturlakin <https://github.com/sergey-buturlakin>, Yuichi Murata <https://github.com/mrk21>, Václav Ostrožlík <https://github.com/vasek17>, Nathan Brown <https://github.com/ngbrown>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
@@ -195,6 +195,10 @@ declare namespace ReactRouter {
interface IndexRedirectElement extends React.ReactElement<IndexRedirectProps> {}
const IndexRedirect: IndexRedirect
interface RouterOnContext extends H.History {
setRouteLeaveHook(route: PlainRoute, hook?: RouteHook): () => void;
isActive(pathOrLoc: H.LocationDescriptor, indexOnly?: boolean): boolean;
}
/* mixins */
@@ -220,6 +224,7 @@ declare namespace ReactRouter {
listenBeforeLeavingRoute(route: PlainRoute, hook: RouteHook): void
match(location: H.Location, callback: (error: any, nextState: RouterState, nextLocation: H.Location) => void): void
isActive(pathname: H.Pathname, query?: H.Query, indexOnly?: boolean): boolean
setRouteLeaveHook(route: PlainRoute, callback: RouteHook): void
}
function useRoutes<T>(createHistory: HistoryModule.CreateHistory<T>): HistoryModule.CreateHistory<T & HistoryRoutes>
@@ -447,6 +452,7 @@ declare module "react-router" {
export type RouterListener = ReactRouter.RouterListener
export type RouterState = ReactRouter.RouterState
export type HistoryBase = ReactRouter.HistoryBase
export type RouterOnContext = ReactRouter.RouterOnContext
export {
Router,

View File

@@ -10,30 +10,32 @@ declare namespace __React {
// ----------------------------------------------------------------------
type ReactType = string | ComponentClass<any> | StatelessComponent<any>;
type Key = string | number;
type Ref<T> = string | ((instance: T) => any);
interface ReactElement<P extends Props<any>> {
type: string | ComponentClass<P> | StatelessComponent<P>;
props: P;
key: string | number;
ref: string | ((component: Component<P, any> | Element) => any);
key: Key;
ref: Ref<Component<P, any> | Element>;
}
interface ClassicElement<P> extends ReactElement<P> {
type: ClassicComponentClass<P>;
ref: string | ((component: ClassicComponent<P, any>) => any);
ref: Ref<ClassicComponent<P, any>>;
}
interface DOMElement<P extends Props<Element>> extends ReactElement<P> {
type: string;
ref: string | ((element: Element) => any);
ref: Ref<Element>;
}
interface ReactHTMLElement extends DOMElement<HTMLProps<HTMLElement>> {
ref: string | ((element: HTMLElement) => any);
ref: Ref<HTMLElement>;
}
interface ReactSVGElement extends DOMElement<SVGProps> {
ref: string | ((element: SVGElement) => any);
ref: Ref<SVGElement>;
}
//
@@ -90,17 +92,21 @@ declare namespace __React {
props?: P,
...children: ReactNode[]): ReactElement<P>;
function cloneElement<P>(
element: DOMElement<P>,
props?: P,
...children: ReactNode[]): DOMElement<P>;
function cloneElement<P>(
function cloneElement(
element: ReactHTMLElement,
props?: HTMLProps<HTMLElement>,
...children: ReactNode[]): ReactHTMLElement;
function cloneElement(
element: ReactSVGElement,
props?: SVGProps,
...children: ReactNode[]): ReactSVGElement;
function cloneElement<P extends Q, Q>(
element: ClassicElement<P>,
props?: P,
props?: Q,
...children: ReactNode[]): ClassicElement<P>;
function cloneElement<P>(
function cloneElement<P extends Q, Q>(
element: ReactElement<P>,
props?: P,
props?: Q,
...children: ReactNode[]): ReactElement<P>;
function isValidElement(object: {}): boolean;
@@ -321,8 +327,8 @@ declare namespace __React {
interface Props<T> {
children?: ReactNode;
key?: string | number;
ref?: string | ((component: T) => any);
key?: Key;
ref?: Ref<T>;
}
interface HTMLProps<T> extends HTMLAttributes, Props<T> {
@@ -427,31 +433,7 @@ declare namespace __React {
// This interface is not complete. Only properties accepting
// unitless numbers are listed here (see CSSProperty.js in React)
interface CSSProperties {
boxFlex?: number;
boxFlexGroup?: number;
columnCount?: number;
flex?: number | string;
flexGrow?: number;
flexShrink?: number;
fontWeight?: number | string;
lineClamp?: number;
lineHeight?: number | string;
opacity?: number;
order?: number;
orphans?: number;
widows?: number;
zIndex?: number;
zoom?: number;
fontSize?: number | string;
// SVG-related properties
fillOpacity?: number;
strokeOpacity?: number;
strokeWidth?: number;
// Remaining properties auto-extracted from http://docs.webplatform.org.
// License: http://docs.webplatform.org/wiki/Template:CC-by-3.0
/**
* Aligns a flex container's lines within the flex container when there is extra space in the cross-axis, similar to how justify-content aligns individual items within the main-axis.
*/
@@ -509,12 +491,30 @@ declare namespace __React {
*/
backfaceVisibility?: any;
/**
* Shorthand property to set the values for one or more of:
* background-clip, background-color, background-image,
* background-origin, background-position, background-repeat,
* background-size, and background-attachment.
*/
background?: any;
/**
* If a background-image is specified, this property determines
* whether that image's position is fixed within the viewport,
* or scrolls along with its containing block.
*/
backgroundAttachment?: "scroll" | "fixed" | "local";
/**
* This property describes how the element's background images should blend with each other and the element's background color.
* The value is a list of blend modes that corresponds to each background image. Each element in the list will apply to the corresponding element of background-image. If a property doesnt have enough comma-separated values to match the number of layers, the UA must calculate its used value by repeating the list of values until there are enough.
*/
backgroundBlendMode?: any;
/**
* Sets the background color of an element.
*/
backgroundColor?: any;
backgroundComposite?: any;
@@ -530,9 +530,9 @@ declare namespace __React {
backgroundOrigin?: any;
/**
* Sets the horizontal position of a background image.
* Sets the position of a background image.
*/
backgroundPositionX?: any;
backgroundPosition?: any;
/**
* Background-repeat defines if and how background images will be repeated after they have been sized and positioned
@@ -554,6 +554,17 @@ declare namespace __React {
*/
border?: any;
/**
* Shorthand that sets the values of border-bottom-color,
* border-bottom-style, and border-bottom-width.
*/
borderBottom?: any;
/**
* Sets the color of the bottom border of an element.
*/
borderBottomColor?: any;
/**
* Defines the shape of the border of the bottom-left corner.
*/
@@ -564,6 +575,11 @@ declare namespace __React {
*/
borderBottomRightRadius?: any;
/**
* Sets the line style of the bottom border of a box.
*/
borderBottomStyle?: any;
/**
* Sets the width of an element's bottom border. To set all four borders, use the border-width shorthand property which sets the values simultaneously for border-top-width, border-right-width, border-bottom-width, and border-left-width.
*/
@@ -724,6 +740,16 @@ declare namespace __React {
*/
boxOrdinalGroup?: any;
/**
* Deprecated.
*/
boxFlex?: number;
/**
* Deprecated.
*/
boxFlexGroup?: number;
/**
* The CSS break-after property allows you to force a break on multi-column layouts. More specifically, it allows you to force a break after an element. It allows you to determine if a break should occur, and what type of break it should be. The break-after CSS property describes how the page, column or region break behaves after the generated box. If there is no generated box, the property is ignored.
*/
@@ -760,6 +786,11 @@ declare namespace __React {
*/
color?: any;
/**
* Describes the number of columns of the element.
*/
columnCount?: number;
/**
* Specifies how to fill columns (balanced or sequential).
*/
@@ -820,6 +851,11 @@ declare namespace __React {
*/
cueAfter?: any;
/**
* Specifies the mouse cursor displayed when the mouse pointer is over an element.
*/
cursor?: any;
/**
* The direction CSS property specifies the text direction/writing direction. The rtl is used for Hebrew or Arabic text, the ltr is for other languages.
*/
@@ -835,6 +871,11 @@ declare namespace __React {
*/
fill?: any;
/**
* SVG: Specifies the opacity of the color or the content the current object is filled with.
*/
fillOpacity?: number;
/**
* The fill-rule property indicates the algorithm which is to be used to determine what parts of the canvas are included inside the shape. For a simple, non-intersecting path, it is intuitively clear what region lies "inside"; however, for a more complex path, such as a path that intersects itself or where one subpath encloses another, the interpretation of "inside" is not so obvious.
* The fill-rule property provides two options for how the inside of a shape is determined:
@@ -846,6 +887,11 @@ declare namespace __React {
*/
filter?: any;
/**
* Shorthand for `flex-grow`, `flex-shrink`, and `flex-basis`.
*/
flex?: number | string;
/**
* Obsolete, do not use. This property has been renamed to align-items.
* Specifies the alignment (perpendicular to the layout axis defined by the flex-direction property) of child elements of the object.
@@ -867,6 +913,11 @@ declare namespace __React {
*/
flexFlow?: any;
/**
* Specifies the flex grow factor of a flex item.
*/
flexGrow?: number;
/**
* Do not use. This property has been renamed to align-self
* Specifies the alignment (perpendicular to the layout axis defined by flex-direction) of child elements of the object.
@@ -884,6 +935,11 @@ declare namespace __React {
*/
flexOrder?: any;
/**
* Specifies the flex shrink factor of a flex item.
*/
flexShrink?: number;
/**
* Elements which have the style float are floated horizontally. These elements can move as far to the left or right of the containing element. All elements after the floating element will flow around it, but elements before the floating element are not impacted. If several floating elements are placed after each other, they will float next to each other as long as there is room.
*/
@@ -909,6 +965,11 @@ declare namespace __React {
*/
fontKerning?: any;
/**
* Specifies the size of the font. Used to compute em and ex units.
*/
fontSize?: number | string;
/**
* The font-size-adjust property adjusts the font-size of the fallback fonts defined with font-family, so that the x-height is the same no matter what font is used. This preserves the readability of the text when fallback happens.
*/
@@ -939,6 +1000,11 @@ declare namespace __React {
*/
fontVariantAlternates?: any;
/**
* Specifies the weight or boldness of the font.
*/
fontWeight?: "normal" | "bold" | "lighter" | "bolder" | number;
/**
* Lays out one or more grid items bound by 4 grid lines. Shorthand for setting grid-column-start, grid-column-end, grid-row-start, and grid-row-end in a single declaration.
*/
@@ -1044,6 +1110,13 @@ declare namespace __React {
*/
lineBreak?: any;
lineClamp?: number;
/**
* Specifies the height of an inline block level element.
*/
lineHeight?: number | string;
/**
* Shorthand property that sets the list-style-type, list-style-position and list-style-image properties in one declaration.
*/
@@ -1164,6 +1237,23 @@ declare namespace __React {
*/
minWidth?: any;
/**
* Specifies the transparency of an element.
*/
opacity?: number;
/**
* Specifies the order used to lay out flex items in their flex container.
* Elements are laid out in the ascending order of the order value.
*/
order?: number;
/**
* In paged media, this property defines the minimum number of lines in
* a block container that must be left at the bottom of the page.
*/
orphans?: number;
/**
* The CSS outline property is a shorthand property for setting one or more of the individual outline properties outline-style, outline-width and outline-color in a single rule. In most cases the use of this shortcut is preferable and more convenient.
* Outlines differ from borders in the following ways: • Outlines do not take up space, they are drawn above the content.
@@ -1192,10 +1282,15 @@ declare namespace __React {
overflowStyle?: any;
/**
* The overflow-x property is a specific case of the generic overflow property. It controls how extra content exceeding the x-axis of the bounding box of an element is rendered.
* Controls how extra content exceeding the x-axis of the bounding box of an element is rendered.
*/
overflowX?: any;
/**
* Controls how extra content exceeding the y-axis of the bounding box of an element is rendered.
*/
overflowY?: any;
/**
* The padding optional CSS property sets the required padding space on one to four sides of an element. The padding area is the space between an element and its border. Negative values are not allowed but decimal values are permitted. The element size is treated as fixed, and the content of the element shifts toward the center as padding is increased.
* The padding property is a shorthand to avoid setting each side separately (padding-top, padding-right, padding-bottom, padding-left).
@@ -1341,6 +1436,16 @@ declare namespace __React {
*/
speakAs?: any;
/**
* SVG: Specifies the opacity of the outline on the current object.
*/
strokeOpacity?: number;
/**
* SVG: Specifies the width of the outline on the current object.
*/
strokeWidth?: number;
/**
* The tab-size CSS property is used to customise the width of a tab (U+0009) character.
*/
@@ -1649,6 +1754,12 @@ declare namespace __React {
*/
whiteSpaceTreatment?: any;
/**
* In paged media, this property defines the mimimum number of lines
* that must be left at the top of the second page.
*/
widows?: number;
/**
* Specifies the width of the content area of an element. The content area of the element width does not include the padding, border, and margin of the element.
*/
@@ -1690,6 +1801,16 @@ declare namespace __React {
*/
writingMode?: any;
/**
* The z-index property specifies the z-order of an element and its descendants.
* When elements overlap, z-order determines which one covers the other.
*/
zIndex?: "auto" | number;
/**
* Sets the initial zoom factor of a document defined by @viewport.
*/
zoom?: "auto" | number;
[propertyName: string]: any;
}
@@ -1843,6 +1964,9 @@ declare namespace __React {
results?: number;
security?: string;
unselectable?: boolean;
// Allows aria- and data- Attributes
[key: string]: any;
}
interface SVGAttributes extends HTMLAttributes {
@@ -2133,11 +2257,11 @@ declare namespace JSX {
interface ElementAttributesProperty { props: {}; }
interface IntrinsicAttributes {
key?: string | number;
key?: React.Key;
}
interface IntrinsicClassAttributes<T> {
ref?: string | ((classInstance: T) => void);
ref?: React.Ref<T>;
}
interface IntrinsicElements {

View File

@@ -0,0 +1,18 @@
// Type definitions for redux-thunk
// Project: https://github.com/gaearon/redux-thunk
// Definitions by: Qubo <https://github.com/tkqubo>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
/// <reference path="../redux/redux.d.ts" />
declare module ReduxThunk {
export interface Thunk extends Redux.Middleware {}
export interface ThunkInterface {
<T>(dispatch: Redux.Dispatch, getState?: () => T): any;
}
}
declare module "redux-thunk" {
var thunk: ReduxThunk.Thunk;
export = thunk;
}

View File

@@ -0,0 +1,52 @@
// Type definitions for Redux v1.0.0
// Project: https://github.com/rackt/redux
// Definitions by: William Buchwalter <https://github.com/wbuchwalter/>, Vincent Prouillet <https://github.com/Keats/>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
declare module Redux {
interface ActionCreator extends Function {
(...args: any[]): any;
}
interface Reducer extends Function {
(state: any, action: any): any;
}
interface Dispatch extends Function {
(action: any): any;
}
interface StoreMethods {
dispatch: Dispatch;
getState(): any;
}
interface MiddlewareArg {
dispatch: Dispatch;
getState: Function;
}
interface Middleware extends Function {
(obj: MiddlewareArg): Function;
}
class Store {
getReducer(): Reducer;
replaceReducer(nextReducer: Reducer): void;
dispatch(action: any): any;
getState(): any;
subscribe(listener: Function): Function;
}
function createStore(reducer: Reducer, initialState?: any, enhancer?: ()=>any): Store;
function bindActionCreators<T>(actionCreators: T, dispatch: Dispatch): T;
function combineReducers(reducers: any): Reducer;
function applyMiddleware(...middlewares: Middleware[]): Function;
function compose<T extends Function>(...functions: Function[]): T;
}
declare module "redux" {
export = Redux;
}

View File

@@ -0,0 +1,90 @@
// Type definitions for source-map v0.1.38
// Project: https://github.com/mozilla/source-map
// Definitions by: Morten Houston Ludvigsen <https://github.com/MortenHoustonLudvigsen>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
declare module SourceMap {
interface StartOfSourceMap {
file?: string;
sourceRoot?: string;
}
interface RawSourceMap extends StartOfSourceMap {
version: string;
sources: Array<string>;
names: Array<string>;
sourcesContent?: string[];
mappings: string;
}
interface Position {
line: number;
column: number;
}
interface MappedPosition extends Position {
source: string;
name?: string;
}
interface MappingItem {
source: string;
generatedLine: number;
generatedColumn: number;
originalLine: number;
originalColumn: number;
name: string;
}
interface Mapping {
generated: Position;
original: Position;
source: string;
name?: string;
}
interface CodeWithSourceMap {
code: string;
map: SourceMapGenerator;
}
class SourceMapConsumer {
public static GENERATED_ORDER: number;
public static ORIGINAL_ORDER: number;
constructor(rawSourceMap: RawSourceMap);
public originalPositionFor(generatedPosition: Position): MappedPosition;
public generatedPositionFor(originalPosition: MappedPosition): Position;
public sourceContentFor(source: string): string;
public eachMapping(callback: (mapping: MappingItem) => void, context?: any, order?: number): void;
}
class SourceMapGenerator {
constructor(startOfSourceMap?: StartOfSourceMap);
public static fromSourceMap(sourceMapConsumer: SourceMapConsumer): SourceMapGenerator;
public addMapping(mapping: Mapping): void;
public setSourceContent(sourceFile: string, sourceContent: string): void;
public applySourceMap(sourceMapConsumer: SourceMapConsumer, sourceFile?: string, sourceMapPath?: string): void;
public toString(): string;
}
class SourceNode {
constructor();
constructor(line: number, column: number, source: string);
constructor(line: number, column: number, source: string, chunk?: string, name?: string);
public static fromStringWithSourceMap(code: string, sourceMapConsumer: SourceMapConsumer, relativePath?: string): SourceNode;
public add(chunk: any): SourceNode;
public prepend(chunk: any): SourceNode;
public setSourceContent(sourceFile: string, sourceContent: string): void;
public walk(fn: (chunk: string, mapping: MappedPosition) => void): void;
public walkSourceContents(fn: (file: string, content: string) => void): void;
public join(sep: string): SourceNode;
public replaceRight(pattern: string, replacement: string): SourceNode;
public toString(): string;
public toStringWithSourceMap(startOfSourceMap?: StartOfSourceMap): CodeWithSourceMap;
}
}
declare module 'source-map' {
export = SourceMap;
}

View File

@@ -4,3 +4,10 @@
/// <reference path="react-router/react-router.d.ts" />
/// <reference path="react/react-dom.d.ts" />
/// <reference path="whatwg-fetch/whatwg-fetch.d.ts" />
/// <reference path="react-redux/react-redux.d.ts" />
/// <reference path="react-router-redux/react-router-redux.d.ts" />
/// <reference path="redux-thunk/redux-thunk.d.ts" />
/// <reference path="redux/redux.d.ts" />
/// <reference path="source-map/source-map.d.ts" />
/// <reference path="uglify-js/uglify-js.d.ts" />
/// <reference path="webpack/webpack-env.d.ts" />

View File

@@ -0,0 +1,430 @@
// Type definitions for UglifyJS 2 v2.6.1
// Project: https://github.com/mishoo/UglifyJS2
// Definitions by: Tanguy Krotoff <https://github.com/tkrotoff>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
/// <reference path="../source-map/source-map.d.ts" />
declare module 'uglify-js' {
import * as MOZ_SourceMap from 'source-map';
namespace UglifyJS {
interface Tokenizer {
/**
* The type of this token.
* Can be "num", "string", "regexp", "operator", "punc", "atom", "name", "keyword", "comment1" or "comment2".
* "comment1" and "comment2" are for single-line, respectively multi-line comments.
*/
type: string;
/**
* The name of the file where this token originated from. Useful when compressing multiple files at once to generate the proper source map.
*/
file: string;
/**
* The "value" of the token.
* That's additional information and depends on the token type: "num", "string" and "regexp" tokens you get their literal value.
* - For "operator" you get the operator.
* - For "punc" it's the punctuation sign (parens, comma, semicolon etc).
* - For "atom", "name" and "keyword" it's the name of the identifier
* - For comments it's the body of the comment (excluding the initial "//" and "/*".
*/
value: string;
/**
* The line number of this token in the original code.
* 1-based index.
*/
line: number;
/**
* The column number of this token in the original code.
* 0-based index.
*/
col: number;
/**
* Short for "newline before", it's a boolean that tells us whether there was a newline before this node in the original source. It helps for automatic semicolon insertion.
* For multi-line comments in particular this will be set to true if there either was a newline before this comment, or * * if this comment contains a newline.
*/
nlb: boolean;
/**
* This doesn't apply for comment tokens, but for all other token types it will be an array of comment tokens that were found before.
*/
comments_before: string[];
}
interface AST_Node {
// The first token of this node
start: AST_Node;
// The last token of this node
end: AST_Node;
transform(tt: TreeTransformer): AST_Toplevel;
}
interface AST_Toplevel extends AST_Node {
// UglifyJS contains a scope analyzer which figures out variable/function definitions, references etc.
// You need to call it manually before compression or mangling.
// The figure_out_scope method is defined only on the AST_Toplevel node.
figure_out_scope(): void;
// Get names that are optimized for GZip compression (names will be generated using the most frequent characters first)
compute_char_frequency(): void;
mangle_names(): void;
print(stream: OutputStream): void;
print_to_string(options?: BeautifierOptions): string;
}
interface MinifyOptions {
spidermonkey?: boolean;
outSourceMap?: string;
sourceRoot?: string;
inSourceMap?: string;
fromString?: boolean;
warnings?: boolean;
mangle?: Object;
output?: MinifyOutput,
compress?: Object;
}
interface MinifyOutput {
code: string;
map: string;
}
function minify(files: string | Array<string>, options?: MinifyOptions): MinifyOutput;
interface ParseOptions {
// Default is false
strict?: boolean;
// Input file name, default is null
filename?: string;
// Default is null
toplevel?: AST_Toplevel;
}
/**
* The parser creates a custom abstract syntax tree given a piece of JavaScript code.
* Perhaps you should read about the AST first.
*/
function parse(code: string, options?: ParseOptions): AST_Toplevel;
interface BeautifierOptions {
/**
* Start indentation on every line (only when `beautify`)
*/
indent_start?: number;
/**
* Indentation level (only when `beautify`)
*/
indent_level?: number;
/**
* Quote all keys in object literals?
*/
quote_keys?: boolean;
/**
* Add a space after colon signs?
*/
space_colon?: boolean;
/**
* Output ASCII-safe? (encodes Unicode characters as ASCII)
*/
ascii_only?: boolean;
/**
* Escape "</script"?
*/
inline_script?: boolean;
/**
* Informative maximum line width (for beautified output)
*/
width?: number;
/**
* Maximum line length (for non-beautified output)
*/
max_line_len?: number;
/**
* Output IE-safe code?
*/
ie_proof?: boolean;
/**
* Beautify output?
*/
beautify?: boolean;
/**
* Output a source map
*/
source_map?: SourceMapOptions;
/**
* Use brackets every time?
*/
bracketize?: boolean;
/**
* Output comments?
*/
comments?: boolean;
/**
* Use semicolons to separate statements? (otherwise, newlines)
*/
semicolons?: boolean;
}
interface OutputStream {
// Return the output so far as a string
get(): string;
toString(): string;
// Insert one indentation string (usually 4 characters).
// Optionally pass true to indent half the width (I'm using that for case and default lines in switch blocks.
// If beautify is off, this function does nothing.
indent(half?: boolean): void;
// Return the current indentation width (not level; for example if we're in level 2 and indent_level is 4, this method would return 8.
indentation(): number;
// return the width of the current line text minus indentation.
current_width(): number
// Return true if current_width() is bigger than options.width (assuming options.width is non-null, non-zero).
should_break(): boolean;
// If beautification is on, this inserts a newline. Otherwise it does nothing.
newline(): void;
// Include the given string into the output, adjusting current_line, current_col and current_pos accordingly.
print(str: string): void;
// If beautification is on this always includes a space character.
// Otherwise it saves a hint somewhere that a space might be needed at current point.
// The space will go in at the next output but only when absolutely required, for example it will insert the space in return 10 but not in return"stuff".
space(): void;
// Inserts a comma, and calls space() — that is, if beautification is on you'll get a space after the comma.
comma(): void;
// Inserts a colon, and calls space() if options.space_colon is set.
colon(): void;
// Returns the last printed chunk.
last(): string;
// If beautification is on it always inserts a semicolon.
// Otherwise it saves a hint that a semicolon might be needed at current point.
// The semicolon is inserted when the next output comes in, only if required to not break the JS syntax.
semicolon(): void;
// Always inserts a semicolon and clears the hint that a semicolon might be needed.
force_semicolon(): void;
// Encodes any non-ASCII characters in string with JavaScript's conventions (using \uCODE).
to_ascii(str: string): void;
// Prints an identifier. If options.ascii_only is set, non-ASCII chars will be encoded with JavaScript conventions.
print_name(name: string): void;
// Prints a string. It adds quotes automatically.
// It prefers double-quotes, but will actually count any quotes in the string and will use single-quotes if the output proves to be shorter (depending on how many backslashes it has to insert).
// It encodes to ASCII if options.ascii_only is set.
print_string(str: string): void;
// Returns the width of the next indentation level. For example if current level is 2 and options.indent_level is 4, it'll return 12.
next_indent(): number;
// Sets the current indentation to col (column), calls the function and thereafter restores the previous indentation level.
// If beautification is off it simply calls func.
with_indent(col: number, func: Function): void;
// This is used to output blocks in curly brackets.
// It'll print an open bracket at current point, then call newline() and with the next indentation level it calls your func.
// Lastly, it'll print an indented closing bracket. As usual, if beautification is off you'll just get {x} where x is whatever func outputs.
with_block(func: Function): void;
// Adds parens around the output that your function prints.
with_parens(func: Function): void;
// Adds square brackets around the output that your function prints.
with_square(func: Function): void;
// If options.source_map is set, this will generate a source mapping between the given token (which should be an AST_Token-like object) and the current line/col.
// The name is optional; in most cases it will be inferred from the token.
add_mapping(token: AST_Node, name?: string): void;
// Returns the option with the given name.
option(name: string): any;
// Returns the current line in the output (1-based).
line(): number;
// Returns the current column in the output (zero-based).
col(): number;
// Push the given node into an internal stack. This is used to keep track of current node's parent(s).
push_node(node: AST_Node): void;
// Pops the top of the stack and returns it.
pop_node(): AST_Node;
// Returns that internal stack.
stack(): any;
// Returns the n-th parent node (where zero means the direct parent).
parent(n: number): AST_Node;
}
/**
* The code generator is a recursive process of getting back source code from an AST returned by the parser.
* Every AST node has a “print” method that takes an OutputStream and dumps the code from that node into it.
* The stream object supports a lot of options that control the output.
* You can specify whether you'd like to get human-readable (indented) output, the indentation level, whether you'd like to quote all properties in object literals etc.
*/
function OutputStream(options?: BeautifierOptions): OutputStream;
interface SourceMapOptions {
/**
* The compressed file name
*/
file?: string;
/**
* The root URL to the original sources
*/
root?: string;
/**
* The input source map.
* Useful when you compress code that was generated from some other source (possibly other programming language).
* If you have an input source map, pass it in this argument and UglifyJS will generate a mapping that maps back
* to the original source (as opposed to the compiled code that you are compressing).
*/
orig?: Object | JSON;
}
interface SourceMap {
add(source: string, gen_line: number, gen_col: number, orig_line: number, orig_col: number, name?: string): void;
get(): MOZ_SourceMap.SourceMapGenerator;
toString(): string;
}
/**
* The output stream keeps track of the current line/column in the output and can trivially generate a source mapping to the original code via Mozilla's source-map library.
* To use this functionality, you must load this library (it's automatically require-d by UglifyJS in the NodeJS version, but in a browser you must load it yourself)
* and make it available via the global MOZ_SourceMap variable.
*/
function SourceMap(options?: SourceMapOptions): SourceMap;
interface CompressorOptions {
// Join consecutive statemets with the “comma operator”
sequences?: boolean;
// Optimize property access: a["foo"] → a.foo
properties?: boolean;
// Discard unreachable code
dead_code?: boolean;
// Discard “debugger” statements
drop_debugger?: boolean;
// Some unsafe optimizations (see below)
unsafe?: boolean;
// Optimize if-s and conditional expressions
conditionals?: boolean;
// Optimize comparisons
comparisons?: boolean;
// Evaluate constant expressions
evaluate?: boolean;
// Optimize boolean expressions
booleans?: boolean;
// Optimize loops
loops?: boolean;
// Drop unused variables/functions
unused?: boolean;
// Hoist function declarations
hoist_funs?: boolean;
// Hoist variable declarations
hoist_vars?: boolean;
// Optimize if-s followed by return/continue
if_return?: boolean;
// Join var declarations
join_vars?: boolean;
// Try to cascade `right` into `left` in sequences
cascade?: boolean;
// Drop side-effect-free statements
side_effects?: boolean;
// Warn about potentially dangerous optimizations/code
warnings?: boolean;
// Global definitions
global_defs?: Object;
}
/**
* The compressor is a tree transformer which reduces the code size by applying various optimizations on the AST
*/
function Compressor(options?: CompressorOptions): AST_Toplevel;
// TODO
interface TreeWalker {
}
type visitor = (node: AST_Node, descend: Function) => boolean;
/**
* UglifyJS provides a TreeWalker object and every node has a walk method that given a walker will apply your visitor to each node in the tree.
* Your visitor can return a non-falsy value in order to prevent descending the current node.
*/
function TreeWalker(visitor: visitor): TreeWalker;
// TODO
interface TreeTransformer extends TreeWalker {
}
/**
* The tree transformer is a special case of a tree walker.
* In fact it even inherits from TreeWalker and you can use the same methods, but initialization and visitor protocol are a bit different.
*/
function TreeTransformer(before: visitor, after: visitor): TreeTransformer;
}
export = UglifyJS;
}

View File

@@ -0,0 +1,232 @@
// Type definitions for webpack 1.12.2 (module API)
// Project: https://github.com/webpack/webpack
// Definitions by: use-strict <https://github.com/use-strict>
// Definitions: https://github.com/borisyankov/DefinitelyTyped
/**
* Webpack module API - variables and global functions available inside modules
*/
declare namespace __WebpackModuleApi {
interface RequireContext {
keys(): string[];
<T>(id: string): T;
resolve(id: string): string;
}
interface RequireFunction {
/**
* Returns the exports from a dependency. The call is sync. No request to the server is fired. The compiler ensures that the dependency is available.
*/
<T>(path: string): T;
/**
* Behaves similar to require.ensure, but the callback is called with the exports of each dependency in the paths array. There is no option to provide a chunk name.
*/
(paths: string[], callback: (...modules: any[]) => void): void;
/**
* Download additional dependencies on demand. The paths array lists modules that should be available. When they are, callback is called. If the callback is a function expression, dependencies in that source part are extracted and also loaded on demand. A single request is fired to the server, except if all modules are already available.
*
* This creates a chunk. The chunk can be named. If a chunk with this name already exists, the dependencies are merged into that chunk and that chunk is used.
*/
ensure: (paths: string[], callback: (require: <T>(path: string) => T) => void, chunkName?: string) => void;
context: (path: string, deep?: boolean, filter?: RegExp) => RequireContext;
/**
* Returns the module id of a dependency. The call is sync. No request to the server is fired. The compiler ensures that the dependency is available.
*
* The module id is a number in webpack (in contrast to node.js where it is a string, the filename).
*/
resolve(path: string): number;
/**
* Like require.resolve, but doesnt include the module into the bundle. Its a weak dependency.
*/
resolveWeak(path: string): number;
/**
* Ensures that the dependency is available, but dont execute it. This can be use for optimizing the position of a module in the chunks.
*/
include(path: string): void;
/**
* Multiple requires to the same module result in only one module execution and only one export. Therefore a cache in the runtime exists. Removing values from this cache cause new module execution and a new export. This is only needed in rare cases (for compatibility!).
*/
cache: {
[id: string]: any;
}
}
interface Module {
exports: any;
require(id: string): any;
id: string;
filename: string;
loaded: boolean;
parent: any;
children: any[];
hot: Hot;
}
type ModuleId = string|number;
interface Hot {
/**
* Accept code updates for the specified dependencies. The callback is called when dependencies were replaced.
* @param dependencies
* @param callback
*/
accept(dependencies: string[], callback: (updatedDependencies: ModuleId[]) => void): void;
/**
* Accept code updates for the specified dependencies. The callback is called when dependencies were replaced.
* @param dependency
* @param callback
*/
accept(dependency: string, callback: () => void): void;
/**
* Accept code updates for this module without notification of parents.
* This should only be used if the module doesnt export anything.
* The errHandler can be used to handle errors that occur while loading the updated module.
* @param errHandler
*/
accept(errHandler?: (err: Error) => void): void;
/**
* Do not accept updates for the specified dependencies. If any dependencies is updated, the code update fails with code "decline".
*/
decline(dependencies: string[]): void;
/**
* Do not accept updates for the specified dependencies. If any dependencies is updated, the code update fails with code "decline".
*/
decline(dependency: string): void;
/**
* Flag the current module as not update-able. If updated the update code would fail with code "decline".
*/
decline(): void;
/**
* Add a one time handler, which is executed when the current module code is replaced.
* Here you should destroy/remove any persistent resource you have claimed/created.
* If you want to transfer state to the new module, add it to data object.
* The data will be available at module.hot.data on the new module.
* @param callback
*/
dispose<T>(callback: (data: T) => void): void;
/**
* Add a one time handler, which is executed when the current module code is replaced.
* Here you should destroy/remove any persistent resource you have claimed/created.
* If you want to transfer state to the new module, add it to data object.
* The data will be available at module.hot.data on the new module.
* @param callback
*/
addDisposeHandler<T>(callback: (data: T) => void): void;
/**
* Remove a handler.
* This can useful to add a temporary dispose handler. You could i. e. replace code while in the middle of a multi-step async function.
* @param callback
*/
removeDisposeHandler<T>(callback: (data: T) => void): void;
/**
* Throws an exceptions if status() is not idle.
* Check all currently loaded modules for updates and apply updates if found.
* If no update was found, the callback is called with null.
* If autoApply is truthy the callback will be called with all modules that were disposed.
* apply() is automatically called with autoApply as options parameter.
* If autoApply is not set the callback will be called with all modules that will be disposed on apply().
* @param autoApply
* @param callback
*/
check(autoApply: boolean, callback: (err: Error, outdatedModules: ModuleId[]) => void): void;
/**
* Throws an exceptions if status() is not idle.
* Check all currently loaded modules for updates and apply updates if found.
* If no update was found, the callback is called with null.
* The callback will be called with all modules that will be disposed on apply().
* @param callback
*/
check(callback: (err: Error, outdatedModules: ModuleId[]) => void): void;
/**
* If status() != "ready" it throws an error.
* Continue the update process.
* @param options
* @param callback
*/
apply(options: AcceptOptions, callback: (err: Error, outdatedModules: ModuleId[]) => void): void;
/**
* If status() != "ready" it throws an error.
* Continue the update process.
* @param callback
*/
apply(callback: (err: Error, outdatedModules: ModuleId[]) => void): void;
/**
* Return one of idle, check, watch, watch-delay, prepare, ready, dispose, apply, abort or fail.
*/
status(): string;
/** Register a callback on status change. */
status(callback: (status: string) => void): void;
/** Register a callback on status change. */
addStatusHandler(callback: (status: string) => void): void;
/**
* Remove a registered status change handler.
* @param callback
*/
removeStatusHandler(callback: (status: string) => void): void;
active: boolean;
data: {};
}
interface AcceptOptions {
/**
* If true the update process continues even if some modules are not accepted (and would bubble to the entry point).
*/
ignoreUnaccepted?: boolean;
/**
* Indicates that apply() is automatically called by check function
*/
autoApply?: boolean;
}
}
declare var require: __WebpackModuleApi.RequireFunction;
/**
* The resource query of the current module.
*
* e.g. __resourceQuery === "?test" // Inside "file.js?test"
*/
declare var __resourceQuery: string;
/**
* Equals the config options output.publicPath.
*/
declare var __webpack_public_path__: string;
/**
* The raw require function. This expression isnt parsed by the Parser for dependencies.
*/
declare var __webpack_require__: any;
/**
* The internal chunk loading function
*
* @param chunkId The id for the chunk to load.
* @param callback A callback function called once the chunk is loaded.
*/
declare var __webpack_chunk_load__: (chunkId: any, callback: (require: (id: string) => any) => void) => void;
/**
* Access to the internal object of all modules.
*/
declare var __webpack_modules__: any[];
/**
* Access to the hash of the compilation.
*
* Only available with the HotModuleReplacementPlugin or the ExtendedAPIPlugin
*/
declare var __webpack_hash__: any;
/**
* Generates a require function that is not parsed by webpack. Can be used to do cool stuff with a global require function if available.
*/
declare var __non_webpack_require__: any;
/**
* Equals the config option debug
*/
declare var DEBUG: boolean;
declare var module: __WebpackModuleApi.Module;

View File

@@ -11,6 +11,7 @@ module.exports = {
plugins: [
extractCSS,
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } })
new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }),
new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"production"' })
]
};

View File

@@ -31,6 +31,7 @@ module.exports = {
name: '[name]_[hash]'
})
].concat(isDevelopment ? [] : [
new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } })
new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }),
new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"production"' })
])
};