Skip to content

Commit 6d5d102

Browse files
authored
Merge pull request #245 from bvaughn/codepen-continued
Seamlessly sync examples from Github -> Codepen
2 parents 49ee183 + cadaeae commit 6d5d102

14 files changed

+260
-9
lines changed

.eslintignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,7 @@ node_modules/*
44
content/*
55

66
# Ignore built files
7-
public/*
7+
public/*
8+
9+
# Ignore examples
10+
codepen/*
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
function Welcome(props) {
2+
return <h1>Hello, {props.name}</h1>;
3+
}
4+
5+
function App() {
6+
return (
7+
<div>
8+
<Welcome name="Sara" />
9+
<Welcome name="Cahal" />
10+
<Welcome name="Edite" />
11+
</div>
12+
);
13+
}
14+
15+
ReactDOM.render(
16+
<App />,
17+
document.getElementById('root')
18+
);
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
function formatDate(date) {
2+
return date.toLocaleDateString();
3+
}
4+
5+
function Avatar(props) {
6+
return (
7+
<img className="Avatar"
8+
src={props.user.avatarUrl}
9+
alt={props.user.name} />
10+
);
11+
}
12+
13+
function UserInfo(props) {
14+
return (
15+
<div className="UserInfo">
16+
<Avatar user={props.user} />
17+
<div className="UserInfo-name">
18+
{props.user.name}
19+
</div>
20+
</div>
21+
);
22+
}
23+
24+
function Comment(props) {
25+
return (
26+
<div className="Comment">
27+
<UserInfo user={props.author} />
28+
<div className="Comment-text">
29+
{props.text}
30+
</div>
31+
<div className="Comment-date">
32+
{formatDate(props.date)}
33+
</div>
34+
</div>
35+
);
36+
}
37+
38+
const comment = {
39+
date: new Date(),
40+
text: 'I hope you enjoy learning React!',
41+
author: {
42+
name: 'Hello Kitty',
43+
avatarUrl: 'http://placekitten.com/g/64/64'
44+
}
45+
};
46+
ReactDOM.render(
47+
<Comment
48+
date={comment.date}
49+
text={comment.text}
50+
author={comment.author} />,
51+
document.getElementById('root')
52+
);
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
function formatDate(date) {
2+
return date.toLocaleDateString();
3+
}
4+
5+
function Comment(props) {
6+
return (
7+
<div className="Comment">
8+
<div className="UserInfo">
9+
<img className="Avatar"
10+
src={props.author.avatarUrl}
11+
alt={props.author.name} />
12+
<div className="UserInfo-name">
13+
{props.author.name}
14+
</div>
15+
</div>
16+
<div className="Comment-text">
17+
{props.text}
18+
</div>
19+
<div className="Comment-date">
20+
{formatDate(props.date)}
21+
</div>
22+
</div>
23+
);
24+
}
25+
26+
const comment = {
27+
date: new Date(),
28+
text: 'I hope you enjoy learning React!',
29+
author: {
30+
name: 'Hello Kitty',
31+
avatarUrl: 'http://placekitten.com/g/64/64'
32+
}
33+
};
34+
ReactDOM.render(
35+
<Comment
36+
date={comment.date}
37+
text={comment.text}
38+
author={comment.author} />,
39+
document.getElementById('root')
40+
);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
function Welcome(props) {
2+
return <h1>Hello, {props.name}</h1>;
3+
}
4+
5+
const element = <Welcome name="Sara" />;
6+
ReactDOM.render(
7+
element,
8+
document.getElementById('root')
9+
);

codepen/hello-world.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
ReactDOM.render(
2+
<h1>Hello, world!</h1>,
3+
document.getElementById('root')
4+
);

codepen/introducing-jsx.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
function formatName(user) {
2+
return user.firstName + ' ' + user.lastName;
3+
}
4+
5+
const user = {
6+
firstName: 'Harper',
7+
lastName: 'Perez',
8+
};
9+
10+
const element = (
11+
<h1>
12+
Hello, {formatName(user)}!
13+
</h1>
14+
);
15+
16+
ReactDOM.render(
17+
element,
18+
document.getElementById('root')
19+
);

content/docs/components-and-props.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ ReactDOM.render(
7676
);
7777
```
7878

79-
[Try it on CodePen.](http://codepen.io/gaearon/pen/YGYmEG?editors=0010)
79+
<a href="/codepen/components-and-props/rendering-a-component" target="_blank">Try it on CodePen</a>.
8080

8181
Let's recap what happens in this example:
8282

@@ -118,7 +118,7 @@ ReactDOM.render(
118118
);
119119
```
120120

121-
[Try it on CodePen.](http://codepen.io/gaearon/pen/KgQKPr?editors=0010)
121+
<a href="/codepen/components-and-props/composing-components" target="_blank">Try it on CodePen</a>.
122122

123123
Typically, new React apps have a single `App` component at the very top. However, if you integrate React into an existing app, you might start bottom-up with a small component like `Button` and gradually work your way to the top of the view hierarchy.
124124

@@ -152,7 +152,7 @@ function Comment(props) {
152152
}
153153
```
154154

155-
[Try it on CodePen.](http://codepen.io/gaearon/pen/VKQwEo?editors=0010)
155+
<a href="/codepen/components-and-props/extracting-components" target="_blank">Try it on CodePen</a>.
156156

157157
It accepts `author` (an object), `text` (a string), and `date` (a date) as props, and describes a comment on a social media website.
158158

@@ -231,7 +231,7 @@ function Comment(props) {
231231
}
232232
```
233233

234-
[Try it on CodePen.](http://codepen.io/gaearon/pen/rrJNJY?editors=0010)
234+
<a href="/codepen/components-and-props/extracting-components-continued" target="_blank">Try it on CodePen</a>.
235235

236236
Extracting components might seem like grunt work at first, but having a palette of reusable components pays off in larger apps. A good rule of thumb is that if a part of your UI is used several times (`Button`, `Panel`, `Avatar`), or is complex enough on its own (`App`, `FeedStory`, `Comment`), it is a good candidate to be a reusable component.
237237

content/docs/hello-world.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ redirect_from:
1212
- "docs/getting-started-zh-CN.html"
1313
---
1414

15-
The easiest way to get started with React is to use [this Hello World example code on CodePen](http://codepen.io/gaearon/pen/ZpvBNJ?editors=0010). You don't need to install anything; you can just open it in another tab and follow along as we go through examples. If you'd rather use a local development environment, check out the [Installation](/docs/installation.html) page.
15+
The easiest way to get started with React is to use <a href="/codepen/hello-world" target="_blank">this Hello World example code on CodePen</a>. You don't need to install anything; you can just open it in another tab and follow along as we go through examples. If you'd rather use a local development environment, check out the [Installation](/docs/installation.html) page.
1616

1717
The smallest React example looks like this:
1818

content/docs/introducing-jsx.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ ReactDOM.render(
4646
);
4747
```
4848

49-
[Try it on CodePen.](http://codepen.io/gaearon/pen/PGEjdG?editors=0010)
49+
<a href="/codepen/introducing-jsx" target="_blank">Try it on CodePen.</a>
5050

5151
We split JSX over multiple lines for readability. While it isn't required, when doing this, we also recommend wrapping it in parentheses to avoid the pitfalls of [automatic semicolon insertion](http://stackoverflow.com/q/2846283).
5252

gatsby-node.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
'use strict';
88

9+
const recursiveReaddir = require('recursive-readdir');
10+
const {readFileSync} = require('fs');
911
const {resolve} = require('path');
1012
const webpack = require('webpack');
1113

@@ -165,6 +167,24 @@ exports.createPages = async ({graphql, boundActionCreators}) => {
165167
redirectInBrowser: true,
166168
toPath: newestBlogNode.fields.slug,
167169
});
170+
171+
// Create Codepen redirects.
172+
// These use the Codepen prefill API to JIT-create Pens.
173+
// https://blog.codepen.io/documentation/api/prefill/
174+
const files = await recursiveReaddir('./codepen');
175+
files.forEach(file => {
176+
const slug = file.substring(0, file.length - 3); // Trim extension
177+
const code = readFileSync(file, 'utf8');
178+
179+
createPage({
180+
path: slug,
181+
component: resolve('./src/templates/codepen-example.js'),
182+
context: {
183+
code,
184+
slug,
185+
},
186+
});
187+
});
168188
};
169189

170190
// Parse date information out of blog post filename.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
"reset": "rimraf ./.cache"
8585
},
8686
"devDependencies": {
87-
"eslint-config-prettier": "^2.6.0"
87+
"eslint-config-prettier": "^2.6.0",
88+
"recursive-readdir": "^2.2.1"
8889
}
8990
}

src/templates/codepen-example.js

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
'use strict';
2+
3+
import React, {Component} from 'react';
4+
import Container from 'components/Container';
5+
import {colors} from 'theme';
6+
7+
const EXTERNALS = [
8+
'https://unpkg.com/react/umd/react.development.js',
9+
'https://unpkg.com/react-dom/umd/react-dom.development.js',
10+
];
11+
12+
// Copied over styles from ButtonLink for the submit btn
13+
const primaryStyle = {
14+
backgroundColor: colors.brand,
15+
color: colors.black,
16+
padding: '10px 25px',
17+
whiteSpace: 'nowrap',
18+
transition: 'background-color 0.2s ease-out',
19+
outline: 0,
20+
border: 'none',
21+
cursor: 'pointer',
22+
23+
':hover': {
24+
backgroundColor: colors.white,
25+
},
26+
27+
display: 'inline-block',
28+
fontSize: 16,
29+
};
30+
31+
class CodepenExample extends Component {
32+
componentDidMount() {
33+
this.codepenForm.submit();
34+
}
35+
36+
render() {
37+
// Codepen configuration.
38+
// https://blog.codepen.io/documentation/api/prefill/
39+
const payload = JSON.stringify({
40+
editors: '0010',
41+
html: '<div id="root"></div>',
42+
js: this.props.pathContext.code,
43+
js_external: EXTERNALS.join(';'),
44+
js_pre_processor: 'babel',
45+
layout: 'left',
46+
title: 'reactjs.org example',
47+
});
48+
49+
return (
50+
<Container>
51+
<h1>Redirecting to Codepen...</h1>
52+
<form
53+
style={{paddingBottom: '50px'}}
54+
ref={form => {
55+
this.codepenForm = form;
56+
}}
57+
action="https://codepen.io/pen/define"
58+
method="POST">
59+
<input type="hidden" name="data" value={payload} />
60+
61+
<p>
62+
Not automatically redirecting?
63+
<br />
64+
<br />
65+
<input style={primaryStyle} type="submit" value="Click here" />
66+
</p>
67+
</form>
68+
</Container>
69+
);
70+
}
71+
}
72+
73+
export default CodepenExample;

yarn.lock

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1535,7 +1535,7 @@ bowser@^1.6.0:
15351535
version "1.7.1"
15361536
resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.7.1.tgz#a4de8f18a1a0dc9531eb2a92a1521fb6a9ba96a5"
15371537

1538-
brace-expansion@^1.1.7:
1538+
brace-expansion@^1.0.0, brace-expansion@^1.1.7:
15391539
version "1.1.8"
15401540
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
15411541
dependencies:
@@ -6367,6 +6367,12 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
63676367
dependencies:
63686368
brace-expansion "^1.1.7"
63696369

6370+
6371+
version "3.0.3"
6372+
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774"
6373+
dependencies:
6374+
brace-expansion "^1.0.0"
6375+
63706376
63716377
version "0.0.8"
63726378
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
@@ -8054,6 +8060,12 @@ rechoir@^0.6.2:
80548060
dependencies:
80558061
resolve "^1.1.6"
80568062

8063+
recursive-readdir@^2.2.1:
8064+
version "2.2.1"
8065+
resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.1.tgz#90ef231d0778c5ce093c9a48d74e5c5422d13a99"
8066+
dependencies:
8067+
minimatch "3.0.3"
8068+
80578069
redbox-react@^1.3.6:
80588070
version "1.5.0"
80598071
resolved "https://registry.yarnpkg.com/redbox-react/-/redbox-react-1.5.0.tgz#04dab11557d26651bf3562a67c22ace56c5d3967"

0 commit comments

Comments
 (0)