Skip to content

Commit 8da11b4

Browse files
committed
[added] convenience factories for non-JSX users in lib/factories
1 parent f151f11 commit 8da11b4

9 files changed

+105
-4
lines changed

docs/src/GettingStartedPage.js

+10
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,16 @@ const Page = React.createClass({
6565
</script>
6666
`}</code></pre>
6767
</div>
68+
69+
<h3>Without JSX</h3>
70+
<p>If you do not use JSX and just call components as functions, you must explicitly <a href="https://facebook.github.io/react/blog/2014/10/14/introducing-react-elements.html#deprecated-auto-generated-factories">create a factory before calling it</a>. React-bootstrap provides factories for you in <code>lib/factories</code>:</p>
71+
<div className="highlight">
72+
<pre><code className="js">{`
73+
var Alert = require('react-bootstrap/lib/factories').Alert;
74+
// or
75+
var Alert = require('react-bootstrap/lib/factories/Alert');
76+
`}</code></pre>
77+
</div>
6878
</div>
6979
<div className="bs-docs-section">
7080
<h2 id="browser-support" className="page-header">Browser support</h2>

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"scripts": {
1111
"build": "node run-babel tools/build.js",
1212
"test-watch": "karma start",
13-
"test": "karma start --single-run && npm run lint && npm run build",
13+
"test": "npm run lint && npm run build && karma start --single-run",
1414
"lint": "eslint src test docs ie8 tools webpack karma.conf.js webpack.config.js webpack.docs.js",
1515
"docs-build": "node run-babel tools/build.js --docs-only",
1616
"docs": "node run-babel docs/server.js",
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<% _.forEach(components, function (component) { %>
2+
import <%= component %> from './<%= component %>';
3+
<% }); %>
4+
5+
export default {
6+
<% _.forEach(components, function (component) { %>
7+
<%= component %>,
8+
<% }); %>
9+
}

src/templates/factory.js.template

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import React from 'react';
2+
import <%= name %> from '../<%= name %>';
3+
4+
export default React.createFactory(<%= name %>);

test/FactoriesSpec.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import React from 'react';
2+
import components from '../tools/public-components';
3+
4+
let props = {
5+
Glyphicon: {glyph: 'star'},
6+
Modal: {onRequestHide: function() {}},
7+
ModalTrigger: {modal: React.DOM.div(null)},
8+
OverlayTrigger: {overlay: React.DOM.div(null)}
9+
};
10+
11+
function createTest(component) {
12+
let factory = require(`../lib/factories/${component}`);
13+
describe('factories', function () {
14+
it(`Should have a ${component} factory`, function () {
15+
assert.ok(React.isValidElement(factory(props[component])));
16+
});
17+
});
18+
}
19+
20+
components.map(component => createTest(component));

tools/amd/build.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import path from 'path';
33
import fsp from 'fs-promise';
44
import { copy } from '../fs-utils';
55
import { exec } from '../exec';
6+
import generateFactories from '../generateFactories';
67
import { repoRoot, srcRoot, bowerRoot } from '../constants';
78

89
const packagePath = path.join(repoRoot, 'package.json');
@@ -12,6 +13,10 @@ const bowerJson = path.join(bowerRoot, 'bower.json');
1213
const readme = path.join(__dirname, 'README.md');
1314
const license = path.join(repoRoot, 'LICENSE');
1415

16+
const babelOptions = '--modules amd --optional es7.objectRestSpread';
17+
18+
const factoriesDestination = path.join(bowerRoot, 'factories');
19+
1520
function bowerConfig() {
1621
return Promise.all([
1722
fsp.readFile(packagePath)
@@ -27,10 +32,11 @@ export default function BuildBower() {
2732
console.log('Building: '.cyan + 'bower module'.green);
2833

2934
return exec(`rimraf ${bowerRoot}`)
30-
.then(() => fsp.mkdir(bowerRoot))
35+
.then(() => fsp.mkdirs(factoriesDestination))
3136
.then(() => Promise.all([
3237
bowerConfig(),
33-
exec(`babel --modules amd --optional es7.objectRestSpread ${srcRoot} --out-dir ${path.join(bowerRoot, 'lib')}`),
38+
generateFactories(babelOptions, factoriesDestination),
39+
exec(`babel ${babelOptions} ${srcRoot} --out-dir ${bowerRoot}`),
3440
copy(readme, bowerRoot),
3541
copy(license, bowerRoot)
3642
]))

tools/generateFactories.js

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import _ from 'lodash';
2+
import path from 'path';
3+
import fsp from 'fs-promise';
4+
import { exec } from './exec';
5+
import { srcRoot } from './constants';
6+
import components from './public-components';
7+
8+
const templatePath = path.join(srcRoot, 'templates');
9+
const factoryTemplatePath = path.join(templatePath, 'factory.js.template');
10+
const indexTemplatePath = path.join(templatePath, 'factory.index.js.template');
11+
12+
export default function generateFactories(babelOptions, destination) {
13+
14+
let generateCompiledFile = function (file, content) {
15+
let outpath = path.join(destination, `${file}.js`);
16+
return exec(`babel ${babelOptions} --out-file ${outpath} <<EOF\n ${content}`);
17+
};
18+
19+
return Promise.all([
20+
fsp.readFile(factoryTemplatePath)
21+
.then(template => {
22+
Promise.all(components.map(name => {
23+
generateCompiledFile(name, _.template(template)({name: name}));
24+
}));
25+
}),
26+
fsp.readFile(indexTemplatePath)
27+
.then(template => _.template(template)({components: components}))
28+
.then(content => generateCompiledFile('index', content))
29+
]);
30+
31+
}

tools/lib/build.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
import 'colors';
22
import { exec } from '../exec';
3+
import path from 'path';
4+
import fsp from 'fs-promise';
35
import { srcRoot, libRoot } from '../constants';
6+
import generateFactories from '../generateFactories';
7+
8+
const factoryDestination = path.join(libRoot, 'factories');
9+
const babelOptions = '--optional es7.objectRestSpread';
410

511
export default function BuildCommonJs() {
612
console.log('Building: '.cyan + 'npm module'.green);
713

814
return exec(`rimraf ${libRoot}`)
9-
.then(() => exec(`babel --optional es7.objectRestSpread ${srcRoot} --out-dir ${libRoot}`))
15+
.then(() => fsp.mkdirs(factoryDestination))
16+
.then(() => Promise.all([
17+
generateFactories(babelOptions, factoryDestination),
18+
exec(`babel ${babelOptions} ${srcRoot} --out-dir ${libRoot}`)
19+
]))
1020
.then(() => console.log('Built: '.cyan + 'npm module'.green));
1121
}

tools/public-components.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React from 'react';
2+
import index from '../src/index';
3+
4+
let components = [];
5+
Object.keys(index).forEach(function (item) {
6+
if (index[item] instanceof React.Component.constructor) {
7+
components.push(item);
8+
}
9+
});
10+
11+
export default components;

0 commit comments

Comments
 (0)