Skip to content

Commit 60b421b

Browse files
committed
initial commit
0 parents  commit 60b421b

14 files changed

+357
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.DS_Store
2+
node_modules
3+
vendor
4+
dist

.jshintrc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"node": true,
3+
"browser": true,
4+
"esnext": true,
5+
"bitwise": true,
6+
"curly": true,
7+
"eqeqeq": true,
8+
"immed": true,
9+
"indent": 2,
10+
"latedef": true,
11+
"newcap": false,
12+
"noarg": true,
13+
"quotmark": "single",
14+
"regexp": true,
15+
"undef": true,
16+
"unused": true,
17+
"strict": true,
18+
"trailing": true,
19+
"smarttabs": true,
20+
"boss": true,
21+
"expr": true
22+
}

comments.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"key":"1","author":"Dagobert Duck","text":"This is one comment"},{"key":"2","author":"Donald Duck","text":"This is *another* comment"}]

gulpfile.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
'use strict';
2+
3+
var gulp = require('gulp');
4+
var gutil = require('gulp-util');
5+
var browserify = require('gulp-browserify');
6+
var uglify = require('gulp-uglify');
7+
var gulpif = require('gulp-if');
8+
var sass = require('gulp-sass');
9+
var server = require('./server');
10+
var bourbon = require('node-bourbon').includePaths;
11+
12+
gutil.log('Environment', gutil.colors.blue(gulp.env.production ? 'Production' : 'Development'));
13+
14+
gulp.task('scripts', function() {
15+
return gulp.src('./src/js/app.js', {read: false})
16+
.pipe(browserify({
17+
insertGlobals : false,
18+
transform: ['reactify'],
19+
extensions: ['.jsx'],
20+
debug: !gulp.env.production
21+
}))
22+
.pipe(gulpif(gulp.env.production, uglify({
23+
mangle: {
24+
except: ['require', 'export', '$super']
25+
}
26+
})))
27+
.pipe(gulp.dest('./dist/js'));
28+
});
29+
30+
gulp.task('styles', function () {
31+
return gulp.src('./src/scss/main.scss')
32+
.pipe(sass({
33+
outputStyle: gulp.env.production ? 'compressed' : 'expanded',
34+
includePaths: ['./src/scss'].concat(bourbon),
35+
errLogToConsole: gulp.env.watch
36+
}))
37+
.pipe(gulp.dest('./dist/css'));
38+
});
39+
40+
gulp.task('default', function() {
41+
gulp.env.watch = true;
42+
var servers = server(8080, 35729);
43+
44+
// Watch files and run tasks if they change
45+
gulp.watch('./src/js/**', function(evt) {
46+
gulp.run('scripts', function () {
47+
servers.lr.changed({body: {files: [evt.path]}});
48+
});
49+
});
50+
51+
gulp.watch('src/scss/**', function(evt) {
52+
gulp.run('styles', function () {
53+
servers.lr.changed({body: {files: [evt.path]}});
54+
});
55+
});
56+
});
57+
58+
gulp.task('build', ['styles', 'scripts']);

index.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<link rel="stylesheet" type="text/css" href="dist/css/main.css">
6+
<title>gulp.js build test</title>
7+
</head>
8+
9+
<body>
10+
<div id="content"></div>
11+
<script src="dist/js/app.js"></script>
12+
</body>
13+
</html>

package.json

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"name": "react-stack-playground",
3+
"private": true,
4+
"version": "0.0.1",
5+
"repository": {
6+
"type": "git",
7+
"url": "https://github.com/aslansky/react-stack-playground.git"
8+
},
9+
"homepage": "https://github.com/aslansky/react-stack-playground",
10+
"author": {
11+
"name": "Alexander Slansky",
12+
"email": "[email protected]",
13+
"url": "http://slansky.net"
14+
},
15+
"dependencies": {
16+
"react": "~0.8.0",
17+
"showdown": "aslansky/showdown",
18+
"shoe": "0.0.15",
19+
"node-bourbon": "1.0.0"
20+
},
21+
"devDependencies": {
22+
"gulp-util": "~2.2.12",
23+
"gulp": "~3.4.0",
24+
"gulp-browserify": "0.3.4",
25+
"gulp-if": "0.0.3",
26+
"gulp-sass": "~0.4.0",
27+
"gulp-uglify": "~0.1.0",
28+
"reactify": "~0.5.1",
29+
"tiny-lr": "0.0.5",
30+
"express": "~3.4.7",
31+
"chokidar": "~0.8.1"
32+
},
33+
"engines": {
34+
"node": ">=0.10.0"
35+
}
36+
}

readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# [gulp](http://gulpjs.com/), [libSass](http://libsass.org/)/[Bourbon](http://bourbon.io/), [React](http://facebook.github.io/react/index.html) and [shoe](https://github.com/substack/shoe) playground

server/index.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
'use strict';
2+
3+
var express = require('express');
4+
var path = require('path');
5+
var tinylr = require('tiny-lr');
6+
var shoe = require('shoe');
7+
var fs = require('fs');
8+
var path = require('path');
9+
var chokidar = require('chokidar');
10+
var gutil = require('gulp-util');
11+
12+
module.exports = function(port, lrport) {
13+
var lr = tinylr();
14+
lr.listen(lrport);
15+
16+
var app = express();
17+
app.use(express.static(path.resolve('./')));
18+
19+
var sendFile = function (stream) {
20+
fs.readFile('./comments.json', function (err, buf) {
21+
gutil.log('Stream write ...');
22+
stream.write(buf);
23+
});
24+
};
25+
var writeFile = function (data) {
26+
data = JSON.parse(data);
27+
fs.readFile('./comments.json', {encoding: 'utf-8'}, function (err, content) {
28+
content = JSON.parse(content);
29+
content.push(data);
30+
fs.writeFile('./comments.json', JSON.stringify(content), {encoding: 'utf-8'});
31+
});
32+
};
33+
var watcher = chokidar.watch('./comments.json');
34+
var sock = shoe(function (stream) {
35+
watcher.on('change', function() {
36+
sendFile(stream);
37+
});
38+
stream.on('data', function (data) {
39+
writeFile(data);
40+
});
41+
stream.on('end', function () {
42+
watcher.close();
43+
});
44+
sendFile(stream);
45+
});
46+
47+
sock.install(app.listen(port), '/comments');
48+
gutil.log('Listening on', port + ' / ' + lrport);
49+
50+
return {
51+
lr: lr,
52+
app: app
53+
};
54+
};

src/js/app.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use strict';
2+
3+
var React = require('react');
4+
var CommentBox = require('./jsx/comment-box');
5+
6+
React.renderComponent(
7+
CommentBox({
8+
url: 'comments.json',
9+
pollInterval: 2000
10+
}),
11+
document.getElementById('content')
12+
);

src/js/jsx/comment-box.jsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/** @jsx React.DOM */
2+
'use strict';
3+
4+
var React = require('react');
5+
var CommentList = require('./comment-list');
6+
var CommentForm = require('./comment-form');
7+
var shoe = require('shoe');
8+
9+
module.exports = React.createClass({
10+
loadCommentsFromServer: function() {
11+
this.stream.on('data', function (data) {
12+
this.setState({data: JSON.parse(data)});
13+
}.bind(this));
14+
},
15+
handleCommentSubmit: function(comment) {
16+
this.stream.write(JSON.stringify(comment));
17+
},
18+
getInitialState: function() {
19+
return {data: []};
20+
},
21+
componentWillMount: function() {
22+
this.stream = shoe('/comments');
23+
this.loadCommentsFromServer();
24+
},
25+
render: function() {
26+
return (
27+
<div className="commentBox">
28+
<h1>Comments</h1>
29+
<CommentList data={this.state.data} />
30+
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
31+
</div>
32+
);
33+
}
34+
});

src/js/jsx/comment-form.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/** @jsx React.DOM */
2+
'use strict';
3+
4+
var React = require('react');
5+
6+
module.exports = React.createClass({
7+
handleSubmit: function() {
8+
var author = this.refs.author.getDOMNode().value.trim();
9+
var text = this.refs.text.getDOMNode().value.trim();
10+
this.props.onCommentSubmit({author: author, text: text});
11+
this.refs.author.getDOMNode().value = '';
12+
this.refs.text.getDOMNode().value = '';
13+
return false;
14+
},
15+
render: function() {
16+
return (
17+
<div className="commentForm">
18+
<form className="commentForm" onSubmit={this.handleSubmit}>
19+
<input type="text" placeholder="Your name" ref="author" />
20+
<textarea placeholder="Say something..." ref="text"></textarea>
21+
<button type="submit">Post</button>
22+
</form>
23+
</div>
24+
);
25+
}
26+
});

src/js/jsx/comment-list.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/** @jsx React.DOM */
2+
'use strict';
3+
4+
var React = require('react/addons');
5+
var Comment = require('./comment');
6+
var ReactTransitionGroup = React.addons.TransitionGroup;
7+
8+
module.exports = React.createClass({
9+
render: function() {
10+
var commentNodes = this.props.data.map(function (comment, i) {
11+
return <Comment key={i} author={comment.author}>{comment.text}</Comment>;
12+
});
13+
return (
14+
<ReactTransitionGroup transitionName="comment">
15+
{commentNodes}
16+
</ReactTransitionGroup>
17+
);
18+
}
19+
});

src/js/jsx/comment.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/** @jsx React.DOM */
2+
'use strict';
3+
4+
var React = require('react');
5+
var Showdown = require('showdown');
6+
var converter = new Showdown.converter();
7+
8+
module.exports = React.createClass({
9+
render: function() {
10+
return (
11+
<div key={this.props.key} className="comment">
12+
<h2 className="commentAuthor">
13+
{this.props.author}
14+
</h2>
15+
<span dangerouslySetInnerHTML={{__html: converter.makeHtml(this.props.children.toString())}} />
16+
</div>
17+
);
18+
}
19+
});

src/scss/main.scss

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
@import 'bourbon';
2+
3+
$primary-color: #333;
4+
$border-color: #BBB;
5+
6+
$primary-size: 16px;
7+
8+
body {
9+
font: $primary-size $helvetica;
10+
color: $primary-color;
11+
background: #EEE;
12+
margin: 50px;
13+
}
14+
15+
h1 {
16+
font-size: 1.5em;
17+
margin-bottom: 1.5em;
18+
}
19+
20+
h2 {
21+
font-size: 1.2em;
22+
margin-bottom: 0;
23+
}
24+
25+
input, textarea {
26+
border: 1px solid $border-color;
27+
display: block;
28+
font-size: $primary-size;
29+
padding: 5px;
30+
width: 400px;
31+
}
32+
33+
textarea {
34+
height: 100px;
35+
}
36+
37+
button {
38+
@include button;
39+
}
40+
41+
.comment {
42+
margin-bottom: 2em;
43+
width: 400px;
44+
&.comment-enter {
45+
opacity: 0;
46+
@include transition(opacity 500ms ease-in);
47+
&.comment-enter-active {
48+
opacity: 1;
49+
}
50+
}
51+
&.comment-leave {
52+
opacity: 1;
53+
@include transition(opacity 500ms ease-in);
54+
&.comment-leave-active {
55+
opacity: 0;
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)