Merge pull request #4 from Microsoft/excel-range

1. Removed gulp as build tool and switched to webpack.
This commit is contained in:
markxyoung 2016-12-05 17:27:01 -08:00 коммит произвёл GitHub
Родитель 715dc5c262 2cd69ba6c9
Коммит 8bf648c422
32 изменённых файлов: 900 добавлений и 41823 удалений

Просмотреть файл

@ -0,0 +1,20 @@
{
"presets": [
"latest",
"react",
"stage-1"
],
"env": {
"development": {
"presets": [
"react-hmre"
]
},
"production": {
"plugins": [
"transform-react-constant-elements",
"transform-react-remove-prop-types"
]
}
}
}

11602
excel/react-sheet/dist/spreadsheet.js поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

8
excel/react-sheet/dist/spreadsheet.min.js поставляемый

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

30065
excel/react-sheet/example/bundle.js поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -3,8 +3,6 @@
<head>
<meta http-equiv='Content-type' content='text/html; charset=utf-8'>
<title>React Spreadsheet Example</title>
<link rel="stylesheet" type="text/css" href="../styles/excel.css" />
<link rel="stylesheet" type="text/css" href="example.css" />
<link href='http://fonts.googleapis.com/css?family=Roboto:400,300' rel='stylesheet' type='text/css'>
</head>
<body>
@ -20,6 +18,5 @@
<h3>Fancy Editable Spreadsheet</h3>
<div id="exampleTwo"></div>
</div>
<script src="bundle.js"></script>
</body>
</html>
</html>

Просмотреть файл

@ -9,64 +9,100 @@
},
"dependencies": {
"jquery": "^2.1",
"mousetrap": "^1.5.3"
"mousetrap": "^1.5.3",
"object-assign": "4.1.0",
"react": "^15.4.1",
"react-dom": "^15.4.1",
"react-redux": ">=4.4.5",
"react-router": ">=2.8.1",
"react-router-redux": ">=4.0.6",
"redux": ">=3.6.0",
"redux-thunk": ">=2.1.0"
},
"peerDependencies": {
"react": "^0.14.3"
"react": "^15.4.1"
},
"devDependencies": {
"autoprefixer": "6.5.1",
"babel-cli": "6.16.0",
"babel-core": "6.17.0",
"babel-eslint": "^7.1.1",
"babel-loader": "6.2.5",
"babel-plugin-react-display-name": "2.0.0",
"babel-plugin-transform-react-constant-elements": "6.9.1",
"babel-plugin-transform-react-remove-prop-types": "0.2.10",
"babel-preset-latest": "6.16.0",
"babel-preset-react": "6.16.0",
"babel-preset-react-hmre": "1.1.1",
"babel-preset-stage-1": "6.16.0",
"babel-register": "6.16.3",
"body-parser": "^1.12.4",
"browserify": "^12.0.1",
"browserify-shim": "^3.8.11",
"browser-sync": "2.17.5",
"chai": "3.5.0",
"chalk": "1.1.3",
"connect-history-api-fallback": "1.3.0",
"coveralls": "2.11.14",
"cross-env": "3.1.3",
"css-loader": "0.25.0",
"del": "^2.0.2",
"enzyme": "2.5.1",
"eslint": "^3.11.1",
"eslint-plugin-import": "^2.2.0",
"eslint-plugin-react": "^6.8.0",
"eslint-watch": "2.1.14",
"express": "^4.12.3",
"gulp": "^3.8.11",
"gulp-connect": "^4.0.0",
"gulp-eslint": "^3.0.1",
"gulp-header": "^1.2.2",
"gulp-plumber": "^1.0.0",
"gulp-react": "^3.0.1",
"gulp-rename": "^1.2.0",
"gulp-streamify": "1.0.2",
"gulp-uglify": "^1.1.0",
"gulp-util": "^3.0.4",
"extract-text-webpack-plugin": "1.0.1",
"file-loader": "0.9.0",
"html-webpack-plugin": "2.24.0",
"isparta": "4.0.0",
"istanbul": "0.4.4",
"jest-babel-preprocessor": "^0.3.0",
"jest-cli": "^0.8.2",
"json-loader": "0.5.4",
"mocha": "3.1.2",
"mockdate": "1.0.4",
"multer": "^1.1.0",
"react": "^0.14.0",
"react-addons-test-utils": "^0.14.3",
"react-dom": "^0.14.0",
"react-tools": "^0.13.3",
"reactify": "^1.1.1",
"tape": "^4.2.2",
"vinyl-source-stream": "^1.1.0"
"node-sass": "3.10.1",
"npm-run-all": "3.1.1",
"open": "0.0.5",
"postcss-loader": "1.0.0",
"prompt": "1.0.0",
"react-addons-test-utils": ">=0.14.3",
"react-tools": ">=0.13.3",
"redux-immutable-state-invariant": "1.2.4",
"replace": "0.3.0",
"rimraf": "2.5.4",
"sass-loader": "4.0.2",
"sinon": "1.17.6",
"sinon-chai": "2.8.0",
"style-loader": "0.13.1",
"url-loader": "0.5.7",
"webpack": "^1.13.3",
"webpack-bundle-analyzer": "^2.1.1",
"webpack-dev-middleware": "^1.8.4",
"webpack-hot-middleware": "^2.13.2",
"webpack-md5-hash": "0.0.5"
},
"scripts": {
"debug": "gulp --debug",
"dist": "gulp bundle-js --production --release && gulp bundle-js --development --release",
"watch": "gulp",
"start-message": "babel-node tools/startMessage.js",
"prestart": "npm-run-all --parallel start-message remove-dist",
"start": "npm-run-all --parallel test open:src lint:watch",
"test": "jest",
"lint": "eslint src"
"lint": "esw webpack.config.* src tools --color",
"lint:watch": "npm run lint -- --watch",
"remove-dist": "rimraf ./dist",
"clean-dist": "npm run remove-dist && mkdir dist",
"prebuild": "npm run clean-dist && npm run lint && npm run test",
"build": "babel-node tools/build.js && npm run open:dist",
"build2": "babel-node tools/build.js",
"analyze-bundle": "babel-node ./tools/analyzeBundle.js",
"open:src": "babel-node tools/srcServer.js",
"open:dist": "babel-node tools/distServer.js"
},
"jest": {
"scriptPreprocessor": "<rootDir>/preprocessor.js",
"scriptPreprocessor": "<rootDir>/node_modules/jest-babel-preprocessor/preprocessor.js",
"unmockedModulePathPatterns": [
"<rootDir>/node_modules/*"
]
},
"browserify-shim": {
"react": "global:React",
"react/addons": "global:React",
"react-dom": "global:ReactDOM"
},
"browserify": {
"transform": [
"browserify-shim"
]
},
"main": "./lib/spreadsheet.js",
"standalone": "React-Spreadsheet"
}
}

Просмотреть файл

@ -112,7 +112,11 @@ Clone the repository from GitHub and open the created folder:
Install npm packages and compile JSX
```bash
npm install
gulp
npm start //for development with hot reloading
npm lint //run Eslint
npm test //run jest tests
npm build //build for production
npm open:dist //open against a local prod server
```
Eslint is run automatically when you type 'gulp'. To check lint errors, do 'npm run lint'.

185
excel/react-sheet/src/cell.js поставляемый
Просмотреть файл

@ -1,147 +1,119 @@
"use strict";
const React = require('react');
var ReactDOM = require('react-dom');
import React, {PropTypes} from 'react';
import ReactDOM from 'react-dom';
var Dispatcher = require('./dispatcher');
var Helpers = require('./helpers');
import Dispatcher from './dispatcher';
import Helpers from './helpers';
var CellComponent = React.createClass({
class CellComponent extends React.Component {
constructor(props, context) {
super(props, context);
/**
* React "getInitialState" method, setting whether or not
* the cell is being edited and its changing value
*/
getInitialState: function() {
return {
editing: this.props.editing,
changedValue: this.props.value
};
},
/**
* React "getInitialState" method, setting whether or not
* the cell is being edited and its changing value
*/
this.state = {
editing: this.props.editing,
changedValue: this.props.value
};
/**
* React "render" method, rendering the individual cell
*/
render: function() {
var props = this.props,
selected = (props.selected) ? 'selected' : '',
ref = 'input_' + props.uid.join('_'),
config = props.config || { emptyValueSymbol: ''},
displayValue = (props.value === '' || !props.value) ? config.emptyValueSymbol : props.value,
cellClasses = (props.cellClasses && props.cellClasses.length > 0) ? props.cellClasses + ' ' + selected : selected,
cellContent;
this.handleClick = this.handleClick.bind(this);
this.handleHeadClick = this.handleHeadClick.bind(this);
this.handleDoubleClick = this.handleDoubleClick.bind(this);
this.handleBlur = this.handleBlur.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleBlur = this.handleBlur.bind(this);
this.handleBlur = this.handleBlur.bind(this);
this.handleBlur = this.handleBlur.bind(this);
// Check if header - if yes, render it
var header = this.renderHeader();
if (header) {
return header;
}
}
// If not a header, check for editing and return
if (props.selected && props.editing) {
cellContent = (
<input className="mousetrap"
onChange={this.handleChange}
onBlur={this.handleBlur}
ref={ref}
defaultValue={this.props.value} />
)
}
return (
<td className={cellClasses} ref={props.uid.join('_')}>
<div className="reactTableCell">
{cellContent}
<span onDoubleClick={this.handleDoubleClick} onClick={this.handleClick}>
{displayValue}
</span>
</div>
</td>
);
},
/**
* React "componentDidUpdate" method, ensuring correct input focus
* @param {React previous properties} prevProps
* @param {React previous state} prevState
*/
componentDidUpdate: function(prevProps, prevState) {
componentDidUpdate(prevProps, prevState) {
if (this.props.editing && this.props.selected) {
var node = ReactDOM.findDOMNode(this.refs['input_' + this.props.uid.join('_')]);
const node = ReactDOM.findDOMNode(this.refs['input_' + this.props.uid.join('_')]);
node.focus();
}
if (prevProps.selected && prevProps.editing && this.state.changedValue !== this.props.value) {
this.props.onCellValueChange(this.props.uid, this.state.changedValue);
}
},
}
/**
* Click handler for individual cell, ensuring navigation and selection
* @param {event} e
*/
handleClick: function (e) {
var cellElement = ReactDOM.findDOMNode(this.refs[this.props.uid.join('_')]);
handleClick(e) {
let cellElement = ReactDOM.findDOMNode(this.refs[this.props.uid.join('_')]);
this.props.handleSelectCell(this.props.uid, cellElement);
},
}
/**
* Click handler for individual cell if the cell is a header cell
* @param {event} e
*/
handleHeadClick: function (e) {
var cellElement = ReactDOM.findDOMNode(this.refs[this.props.uid.join('_')]);
handleHeadClick(e) {
let cellElement = ReactDOM.findDOMNode(this.refs[this.props.uid.join('_')]);
Dispatcher.publish('headCellClicked', cellElement, this.props.spreadsheetId);
},
}
/**
* Double click handler for individual cell, ensuring navigation and selection
* @param {event} e
*/
handleDoubleClick: function (e) {
handleDoubleClick(e) {
e.preventDefault();
this.props.handleDoubleClickOnCell(this.props.uid);
},
}
/**
* Blur handler for individual cell
* @param {event} e
*/
handleBlur: function (e) {
var newValue = ReactDOM.findDOMNode(this.refs['input_' + this.props.uid.join('_')]).value;
handleBlur(e) {
let newValue = ReactDOM.findDOMNode(this.refs['input_' + this.props.uid.join('_')]).value;
this.props.onCellValueChange(this.props.uid, newValue, e);
this.props.handleCellBlur(this.props.uid);
Dispatcher.publish('cellBlurred', this.props.uid, this.props.spreadsheetId);
},
}
/**
* Change handler for an individual cell, propagating the value change
* @param {event} e
*/
handleChange: function (e) {
var newValue = ReactDOM.findDOMNode(this.refs['input_' + this.props.uid.join('_')]).value;
handleChange(e) {
let newValue = ReactDOM.findDOMNode(this.refs['input_' + this.props.uid.join('_')]).value;
this.setState({changedValue: newValue});
},
}
/**
* Checks if a header exists - if it does, it returns a header object
* @return {false|react} [Either false if it's not a header cell, a react object if it is]
*/
renderHeader: function () {
var props = this.props,
renderHeader() {
let props = this.props,
selected = (props.selected) ? 'selected' : '',
uid = props.uid,
config = props.config || { emptyValueSymbol: ''},
displayValue = (props.value === '' || !props.value) ? config.emptyValueSymbol : props.value,
cellClasses = (props.cellClasses && props.cellClasses.length > 0) ? this.props.cellClasses + ' ' + selected : selected;
cellClasses = (props.cellClasses && props.cellClasses.length > 0) ?
this.props.cellClasses + ' ' + selected : selected;
// Cases
var headRow = (uid[0] === 0),
let headRow = (uid[0] === 0),
headColumn = (uid[1] === 0),
headRowAndEnabled = (config.hasHeadRow && uid[0] === 0),
headColumnAndEnabled = (config.hasHeadColumn && uid[1] === 0)
headColumnAndEnabled = (config.hasHeadColumn && uid[1] === 0);
// Head Row enabled, cell is in head row
// Head Column enabled, cell is in head column
@ -173,6 +145,65 @@ var CellComponent = React.createClass({
return false;
}
}
});
module.exports = CellComponent;
/**
* React "render" method, rendering the individual cell
*/
render() {
let props = this.props,
selected = (props.selected) ? 'selected' : '',
ref = 'input_' + props.uid.join('_'),
config = props.config || {
emptyValueSymbol: ''
},
displayValue = (props.value === '' || !props.value) ? config.emptyValueSymbol : props.value,
cellClasses = (props.cellClasses && props.cellClasses.length > 0) ? props.cellClasses + ' ' + selected : selected,
cellContent;
// Check if header - if yes, render it
const header = this.renderHeader();
if (header) {
return header;
}
// If not a header, check for editing and return
if (props.selected && props.editing) {
cellContent = (
<input className="mousetrap"
onChange={this.handleChange}
onBlur={this.handleBlur}
ref={ref}
defaultValue={this.props.value} />
);
}
return (
<td className={cellClasses} ref={props.uid.join('_')}>
<div className="reactTableCell">
{cellContent}
<span onDoubleClick={this.handleDoubleClick} onClick={this.handleClick}>
{displayValue}
</span>
</div>
</td>
);
}
}
CellComponent.propTypes = {
editing: PropTypes.bool,
value: PropTypes.string,
selected: PropTypes.bool,
spreadsheetId: PropTypes.string,
cellClasses: PropTypes.string,
uid: PropTypes.array,
onCellValueChange: PropTypes.func,
handleSelectCell: PropTypes.func,
handleDoubleClickOnCell: PropTypes.func,
handleCellBlur: PropTypes.func
};
export default CellComponent;

Просмотреть файл

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv='Content-type' content='text/html; charset=utf-8'>
<title>React Spreadsheet Example</title>
<link href='http://fonts.googleapis.com/css?family=Roboto:400,300' rel='stylesheet' type='text/css'>
</head>
<body>
<div class="intro">
<h2><a href="https://github.com/felixrieseberg/React-Spreadsheet-Component">React-Spreadsheet-Component</a></h2>
<p>These are two rather simple examples of <a href="https://github.com/felixrieseberg/React-Spreadsheet-Component">React-Spreadsheet-Component</a>, a simple spreadsheet component in React (creative name, huh?). It's made with by Microsoft DX and released under the MIT License.</p>
</div>
<div class="example">
<h3>Simple Example Spreadsheet</h3>
<div id="exampleOne"></div>
</div>
<div class="example">
<h3>Fancy Editable Spreadsheet</h3>
<div id="exampleTwo"></div>
</div>
</body>
</html>

Просмотреть файл

@ -1,11 +1,13 @@
'use strict';
var React = require('react');
var ReactDOM = require('react-dom');
var Spreadsheet = require('./lib/spreadsheet');
import React from 'react';
import ReactDOM from 'react-dom';
import Spreadsheet from './spreadsheet';
import './styles/excel.css';
import './styles/example.css';
// Example One
var exampleOne = {};
let exampleOne = {};
exampleOne.initialData = {
rows: [
@ -31,7 +33,7 @@ exampleOne.config = {
};
// Example Two
var exampleTwo = {};
let exampleTwo = {};
exampleTwo.initialData = {
rows: [
['Customer', 'Job', 'Contact', 'City', 'Revenue'],

45
excel/react-sheet/src/row.js поставляемый
Просмотреть файл

@ -1,23 +1,26 @@
"use strict";
var React = require('react');
import React, {PropTypes} from 'react';
var CellComponent = require('./cell');
var Helpers = require('./helpers');
import CellComponent from './cell';
import Helpers from './helpers';
var RowComponent = React.createClass({
class RowComponent extends React.Component {
constructor(props, context) {
super(props, context);
}
/**
* React Render method
* @return {[JSX]} [JSX to render]
*/
render: function() {
var config = this.props.config,
render() {
let config = this.props.config,
cells = this.props.cells,
columns = [],
key, uid, selected, cellClasses, i;
if (!config.columns || cells.length === 0) {
return console.error('Table can\'t be initialized without set number of columsn and no data!');
return console.error('Table can\'t be initialized without set number of columsn and no data!'); // eslint-disable-line no-console
}
for (i = 0; i < cells.length; i = i + 1) {
@ -27,23 +30,37 @@ var RowComponent = React.createClass({
key = 'row_' + this.props.uid + '_cell_' + i;
uid = [this.props.uid, i];
columns.push(<CellComponent key={key}
columns.push(<CellComponent key={key}
uid={uid}
value={cells[i]}
value={cells[i].toString()}
config={config}
cellClasses={cellClasses}
onCellValueChange={this.props.onCellValueChange}
onCellValueChange={this.props.onCellValueChange}
handleSelectCell={this.props.handleSelectCell}
handleDoubleClickOnCell={this.props.handleDoubleClickOnCell}
handleCellBlur={this.props.handleCellBlur}
spreadsheetId={this.props.spreadsheetId}
selected={selected}
selected={selected}
editing={this.props.editing} />
);
}
return <tr>{columns}</tr>;
}
});
}
module.exports = RowComponent;
RowComponent.propTypes = {
config: PropTypes.object,
editing: PropTypes.bool,
cells: PropTypes.array,
selected: PropTypes.array,
uid: PropTypes.number,
cellClasses: PropTypes.array,
spreadsheetId: PropTypes.string,
onCellValueChange: PropTypes.func,
handleSelectCell: PropTypes.func,
handleDoubleClickOnCell: PropTypes.func,
handleCellBlur: PropTypes.func
};
export default RowComponent;

13
excel/react-sheet/src/spreadsheet.js поставляемый
Просмотреть файл

@ -1,12 +1,11 @@
"use strict";
var React = require('react');
var ReactDOM = require('react-dom');
var $ = require('jquery');
import React, {PropTypes} from 'react';
import ReactDOM from 'react-dom';
import $ from 'jquery';
var RowComponent = require('./row');
var Dispatcher = require('./dispatcher');
var Helpers = require('./helpers');
import RowComponent from './row';
import Dispatcher from './dispatcher';
import Helpers from './helpers';
var SpreadsheetComponent = React.createClass({
spreadsheetId: null,

Просмотреть файл

@ -0,0 +1,98 @@
h2, h3 {
color: #000
}
h2 a {
text-decoration: none;
color: #000;
}
body {
background-color: #F7F7F7;
}
div.example {
margin-bottom: 80px;
margin-left: 20px;
}
div.intro {
margin-bottom: 80px;
width: 700px;
margin-left: 20px;
color: #000;
}
div#exampleTwo td, div#exampleTwo th {
width: 128px;
height: 35px;
border: none;
text-align: left;
background-color: inherit;
}
div#exampleTwo th {
background-color: #fff;
}
div#exampleTwo span {
line-height: 28px;
}
div#exampleTwo table {
-webkit-box-shadow: 2px 2px 36px 0px rgba(0,0,0,0.39);
-moz-box-shadow: 2px 2px 36px 0px rgba(0,0,0,0.39);
box-shadow: 2px 2px 36px 0px rgba(0,0,0,0.39);
border: none;
padding: 8px;
font-family: 'Roboto', sans-serif;
border: 1px solid #D7D7D7;
background-color: #FFFFFF;
}
div#exampleTwo table > tbody > tr:first-child > th {
border-bottom: 1px solid #D8D8D8;
border-right: none;
text-transform: uppercase;
text-align: left;
height: 30px;
font-weight: 300;
margin-bottom: 8px;
}
div#exampleTwo table > tbody > tr > th {
border-right: 1px solid #D8D8D8;
}
div#exampleTwo table > tbody > tr > th:nth-child(2),
div#exampleTwo table > tbody > tr > td:nth-child(2) {
padding-left: 15px;
}
div#exampleTwo td input {
background-color: #F0FAFF;
}
div#exampleTwo tr:hover {
background-color: #EEEEEE;
}
div#exampleTwo input::selection {
background: #F0FAFF;
}
div#exampleTwo .selected {
border-bottom: 2px solid #FF074E;
}
div#exampleTwo .green {
border-left: 13px solid #62B9A4;
}
div#exampleTwo .purple {
border-left: 13px solid #985DFF;
}
div#exampleTwo .yellow {
border-left: 13px solid #FF9E39;
}

9
excel/react-sheet/src/webpack-public-path.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,9 @@
// Dynamically set the webpack public path at runtime below
// This magic global is used by webpack to set the public path at runtime.
// The public path is set dynamically to avoid the following issues:
// 1. https://github.com/coryhouse/react-slingshot/issues/205
// 2. https://github.com/coryhouse/react-slingshot/issues/181
// 3. https://github.com/coryhouse/react-slingshot/pull/125
// Documentation: http://webpack.github.io/docs/configuration.html#output-publicpath
// eslint-disable-next-line no-undef
__webpack_public_path__ = window.location.protocol + "//" + window.location.host + "/";

Просмотреть файл

@ -0,0 +1 @@
!browser-sync-ui/lib/plugins/history # need this for now because of https://github.com/yarnpkg/yarn/issues/1396#issuecomment-255965666

15
excel/react-sheet/tools/analyzeBundle.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,15 @@
import webpack from 'webpack';
import {BundleAnalyzerPlugin} from 'webpack-bundle-analyzer';
import config from '../webpack.config.prod';
config.plugins.push(new BundleAnalyzerPlugin());
const compiler = webpack(config);
compiler.run((error, stats) => {
if (error) {
throw new Error(error);
}
console.log(stats); // eslint-disable-line no-console
});

35
excel/react-sheet/tools/build.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,35 @@
// More info on Webpack's Node API here: https://webpack.github.io/docs/node.js-api.html
// Allowing console calls below since this is a build file.
/* eslint-disable no-console */
import webpack from 'webpack';
import config from '../webpack.config.prod';
import {chalkError, chalkSuccess, chalkWarning, chalkProcessing} from './chalkConfig';
process.env.NODE_ENV = 'production'; // this assures React is built in prod mode and that the Babel dev config doesn't apply.
console.log(chalkProcessing('Generating minified bundle. This will take a moment...'));
webpack(config).run((error, stats) => {
if (error) { // so a fatal error occurred. Stop here.
console.log(chalkError(error));
return 1;
}
const jsonStats = stats.toJson();
if (jsonStats.hasErrors) {
return jsonStats.errors.map(error => console.log(chalkError(error)));
}
if (jsonStats.hasWarnings) {
console.log(chalkWarning('Webpack generated the following warnings: '));
jsonStats.warnings.map(warning => console.log(chalkWarning(warning)));
}
console.log(`Webpack stats: ${stats}`);
// if we got this far, the build succeeded.
console.log(chalkSuccess('Your app is compiled in production mode in /dist. It\'s ready to roll!'));
return 0;
});

6
excel/react-sheet/tools/chalkConfig.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,6 @@
// Centralized configuration for chalk, which is used to add color to console.log statements.
import chalk from 'chalk';
export const chalkError = chalk.red;
export const chalkSuccess = chalk.green;
export const chalkWarning = chalk.yellow;
export const chalkProcessing = chalk.blue;

27
excel/react-sheet/tools/distServer.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,27 @@
// This file configures a web server for testing the production build
// on your local machine.
import browserSync from 'browser-sync';
import historyApiFallback from 'connect-history-api-fallback';
import {chalkProcessing} from './chalkConfig';
/* eslint-disable no-console */
console.log(chalkProcessing('Opening production build...'));
// Run Browsersync
browserSync({
port: 3000,
ui: {
port: 3001
},
server: {
baseDir: 'dist'
},
files: [
'src/*.html'
],
middleware: [historyApiFallback()]
});

10
excel/react-sheet/tools/nodeVersionCheck.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,10 @@
/* eslint-disable */
var exec = require('child_process').exec;
exec('node -v', function (err, stdout) {
if (err) throw err;
if (parseFloat(stdout.slice(1)) < 4) {
throw new Error('React Slingshot requires node 4.0 or greater.');
}
});

Просмотреть файл

73
excel/react-sheet/tools/removeDemo.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,73 @@
// This script removes demo app files
import rimraf from 'rimraf';
import fs from 'fs';
import {chalkSuccess} from './chalkConfig';
/* eslint-disable no-console */
const pathsToRemove = [
'./src/actions/*',
'./src/utils',
'./src/components/*',
'./src/constants/*',
'./src/containers/*',
'./src/images',
'./src/reducers/*',
'./src/store/store.spec.js',
'./src/styles',
'./src/routes.js',
'./src/index.js',
'./tools/removeDemo.js'
];
const filesToCreate = [
{
path: './src/components/emptyTest.spec.js',
content: '// Must have at least one test file in this directory or Mocha will throw an error.'
},
{
path: './src/index.js',
content: '// Set up your application entry point here...'
},
{
path: './src/reducers/index.js',
content: '// Set up your root reducer here...\n import { combineReducers } from \'redux\';\n export default combineReducers;'
}
];
function removePath(path, callback) {
rimraf(path, error => {
if (error) throw new Error(error);
callback();
});
}
function createFile(file) {
fs.writeFile(file.path, file.content, error => {
if (error) throw new Error(error);
});
}
function removePackageJsonScriptEntry(scriptName) {
const packageJsonPath = './package.json';
let fileData = fs.readFileSync(packageJsonPath);
let content = JSON.parse(fileData);
delete content.scripts[scriptName];
fs.writeFileSync(packageJsonPath,
JSON.stringify(content, null, 2) + '\n');
}
let numPathsRemoved = 0;
pathsToRemove.map(path => {
removePath(path, () => {
numPathsRemoved++;
if (numPathsRemoved === pathsToRemove.length) { // All paths have been processed
// Now we can create files since we're done deleting.
filesToCreate.map(file => createFile(file));
}
});
});
removePackageJsonScriptEntry('remove-demo');
console.log(chalkSuccess('Demo app removed.'));

94
excel/react-sheet/tools/setup/setup.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,94 @@
/* eslint-disable no-var */
var rimraf = require('rimraf');
var chalk = require('chalk');
var replace = require("replace");
var prompt = require("prompt");
var prompts = require('./setupPrompts');
var chalkSuccess = chalk.green;
var chalkProcessing = chalk.blue;
var chalkWarn = chalk.red;
/* eslint-disable no-console */
console.log(chalkSuccess('Dependencies installed.'));
prompt.start();
console.log(chalkWarn("WARNING: Preparing to delete local git repository..."));
prompt.get([{name: 'deleteGit', description: "Delete the git repository? YES to continue or NO to skip."}], function(err, result) {
var deleteGit;
if (err) {
process.exit(1);
}
deleteGit = result.deleteGit.toUpperCase();
if (deleteGit === 'Y' || deleteGit === "YES") {
// remove the original git repository
rimraf('.git', error => {
if (error) throw new Error(error);
console.log(chalkSuccess('Original Git repository removed.\n'));
console.log(chalkProcessing('Updating package.json settings:'));
prompt.get(prompts, function(err, result) {
// parse user responses
// default values provided for fields that will cause npm to complain if left empty
const responses = [
{
key: 'name',
value: result.projectName || 'new-project'
},
{
key: 'version',
value: result.version || '0.1.0'
},
{
key: 'author',
value: result.author
},
{
key: 'license',
value: result.license || 'MIT'
},
{
key: 'description',
value: result.description
},
// simply use an empty URL here to clear the existing repo URL
{
key: 'url',
value: ''
}
];
// update package.json with the user's values
responses.forEach(res => {
replace({
regex: `("${res.key}"): "(.*?)"`,
replacement: `$1: "${res.value}"`,
paths: ['package.json'],
recursive: false,
silent: true
});
});
// reset package.json 'keywords' field to empty state
replace({
regex: /"keywords": \[[\s\S]+\]/,
replacement: `"keywords": []`,
paths: ['package.json'],
recursive: false,
silent: true
});
// remove all setup scripts from the 'tools' folder
console.log(chalkSuccess('\nSetup complete! Cleaning up...\n'));
rimraf('./tools/setup', error => {
if (error) throw new Error(error);
});
});
});
}
});

6
excel/react-sheet/tools/setup/setupMessage.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,6 @@
// This script displays an intro message for the setup script
/* eslint-disable no-console */
console.log('===========================');
console.log('= React Slingshot Setup =');
console.log('===========================\n');
console.log('Installing dependencies. Please wait...');

26
excel/react-sheet/tools/setup/setupPrompts.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,26 @@
// Define prompts for use with npm 'prompt' module in setup script
module.exports = [
{
name: 'projectName',
description: 'Project name (default: new-project)',
pattern: /^[^._][a-z0-9\.\-_~]+$/,
message: 'Limited to: lowercase letters, numbers, period, hyphen, ' +
'underscore, and tilde; cannot begin with period or underscore.'
},
{
name: 'version',
description: 'Version (default: 0.1.0)'
},
{
name: 'author',
description: 'Author'
},
{
name: 'license',
description: 'License (default: MIT)'
},
{
name: 'description',
description: 'Project description'
}
];

59
excel/react-sheet/tools/srcServer.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,59 @@
// This file configures the development web server
// which supports hot reloading and synchronized testing.
// Require Browsersync along with webpack and middleware for it
import browserSync from 'browser-sync';
// Required for react-router browserHistory
// see https://github.com/BrowserSync/browser-sync/issues/204#issuecomment-102623643
import historyApiFallback from 'connect-history-api-fallback';
import webpack from 'webpack';
import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import config from '../webpack.config.dev';
const bundler = webpack(config);
// Run Browsersync and use middleware for Hot Module Replacement
browserSync({
port: 3000,
ui: {
port: 3001
},
server: {
baseDir: 'src',
middleware: [
historyApiFallback(),
webpackDevMiddleware(bundler, {
// Dev middleware can't access config, so we provide publicPath
publicPath: config.output.publicPath,
// These settings suppress noisy webpack output so only errors are displayed to the console.
noInfo: false,
quiet: false,
stats: {
assets: false,
colors: true,
version: false,
hash: false,
timings: false,
chunks: false,
chunkModules: false
},
// for other settings see
// http://webpack.github.io/docs/webpack-dev-middleware.html
}),
// bundler should be the same as above
webpackHotMiddleware(bundler)
]
},
// no need to watch '*.js' here, webpack will take care of it for us,
// including full page reloads if HMR won't work
files: [
'src/*.html'
]
});

5
excel/react-sheet/tools/startMessage.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,5 @@
import {chalkSuccess} from './chalkConfig';
/* eslint-disable no-console */
console.log(chalkSuccess('Starting app in dev mode...'));

22
excel/react-sheet/tools/testSetup.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,22 @@
// Tests are placed alongside files under test.
// This file does the following:
// 1. Sets the environment to 'test' so that
// dev-specific babel config in .babelrc doesn't run.
// 2. Disables Webpack-specific features that Mocha doesn't understand.
// 3. Registers babel for transpiling our code for testing.
// This assures the .babelrc dev config (which includes
// hot module reloading code) doesn't apply for tests.
// Setting NODE_ENV to test instead of production because setting it to production will suppress error messaging
// and propType validation warnings.
process.env.NODE_ENV = 'test';
// Disable webpack-specific features for tests since
// Mocha doesn't know what to do with them.
['.css', '.scss', '.png', '.jpg'].forEach(ext => {
require.extensions[ext] = () => null;
});
// Register babel so that it will transpile ES6 to ES5
// before our tests run.
require('babel-register')();

Просмотреть файл

@ -0,0 +1,55 @@
import webpack from 'webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import autoprefixer from 'autoprefixer';
import path from 'path';
export default {
resolve: {
extensions: ['', '.js', '.jsx', '.json']
},
debug: true,
devtool: 'eval-source-map', // more info:https://webpack.github.io/docs/build-performance.html#sourcemaps and https://webpack.github.io/docs/configuration.html#devtool
noInfo: true, // set to false to see a list of every file being bundled.
entry: [
// must be first entry to properly set public path
'./src/webpack-public-path',
'webpack-hot-middleware/client?reload=true',
path.resolve(__dirname, 'src/index.js') // Defining path seems necessary for this to work consistently on Windows machines.
],
target: 'web', // necessary per https://webpack.github.io/docs/testing.html#compile-and-test
output: {
path: path.resolve(__dirname, 'dist'), // Note: Physical files are only output by the production build task `npm run build`.
publicPath: '/',
filename: 'bundle.js'
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development'), // Tells React to build in either dev or prod modes. https://facebook.github.io/react/downloads.html (See bottom)
__DEV__: true
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new HtmlWebpackPlugin({ // Create HTML file that includes references to bundled CSS and JS.
template: 'src/index.html',
minify: {
removeComments: true,
collapseWhitespace: true
},
inject: true
})
],
module: {
loaders: [
{test: /\.jsx?$/, exclude: /node_modules/, loaders: ['babel']},
{test: /\.eot(\?v=\d+.\d+.\d+)?$/, loader: 'file'},
{test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url?limit=10000&mimetype=application/font-woff"},
{test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream'},
{test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml'},
{test: /\.(jpe?g|png|gif)$/i, loader: 'file?name=[name].[ext]'},
{test: /\.ico$/, loader: 'file?name=[name].[ext]'},
{test: /(\.css|\.scss)$/, loaders: ['style', 'css?sourceMap', 'postcss', 'sass?sourceMap']},
{test: /\.json$/, loader: "json"}
]
},
postcss: ()=> [autoprefixer]
};

Просмотреть файл

@ -0,0 +1,83 @@
// For info about this file refer to webpack and webpack-hot-middleware documentation
// For info on how we're generating bundles with hashed filenames for cache busting: https://medium.com/@okonetchnikov/long-term-caching-of-static-assets-with-webpack-1ecb139adb95#.w99i89nsz
import webpack from 'webpack';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import WebpackMd5Hash from 'webpack-md5-hash';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import autoprefixer from 'autoprefixer';
import path from 'path';
const GLOBALS = {
'process.env.NODE_ENV': JSON.stringify('production'),
__DEV__: false
};
export default {
resolve: {
extensions: ['', '.js', '.jsx', '.json']
},
debug: true,
devtool: 'source-map', // more info:https://webpack.github.io/docs/build-performance.html#sourcemaps and https://webpack.github.io/docs/configuration.html#devtool
noInfo: true, // set to false to see a list of every file being bundled.
entry: path.resolve(__dirname, 'src/index'),
target: 'web', // necessary per https://webpack.github.io/docs/testing.html#compile-and-test
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
filename: '[name].[chunkhash].js'
},
plugins: [
// Hash the files using MD5 so that their names change when the content changes.
new WebpackMd5Hash(),
// Optimize the order that items are bundled. This assures the hash is deterministic.
new webpack.optimize.OccurenceOrderPlugin(),
// Tells React to build in prod mode. https://facebook.github.io/react/downloads.html
new webpack.DefinePlugin(GLOBALS),
// Generate an external css file with a hash in the filename
new ExtractTextPlugin('[name].[contenthash].css'),
// Generate HTML file that contains references to generated bundles. See here for how this works: https://github.com/ampedandwired/html-webpack-plugin#basic-usage
new HtmlWebpackPlugin({
template: 'src/index.html',
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true
},
inject: true,
// Note that you can add custom options here if you need to handle other custom logic in index.html
// To track JavaScript errors via TrackJS, sign up for a free trial at TrackJS.com and enter your token below.
trackJSToken: ''
}),
// Eliminate duplicate packages when generating bundle
new webpack.optimize.DedupePlugin(),
// Minify JS
new webpack.optimize.UglifyJsPlugin()
],
module: {
loaders: [
{test: /\.jsx?$/, exclude: /node_modules/, loader: 'babel'},
{test: /\.eot(\?v=\d+.\d+.\d+)?$/, loader: 'url?name=[name].[ext]'},
{test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url?limit=10000&mimetype=application/font-woff&name=[name].[ext]"},
{test: /\.ttf(\?v=\d+.\d+.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream&name=[name].[ext]'},
{test: /\.svg(\?v=\d+.\d+.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml&name=[name].[ext]'},
{test: /\.(jpe?g|png|gif)$/i, loader: 'file?name=[name].[ext]'},
{test: /\.ico$/, loader: 'file?name=[name].[ext]'},
{test: /(\.css|\.scss)$/, loader: ExtractTextPlugin.extract('css?sourceMap!postcss!sass?sourceMap')},
{test: /\.json$/, loader: "json"}
]
},
postcss: ()=> [autoprefixer]
};