diff --git a/.eslintignore b/.eslintignore
index 942541715..705b4afee 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -7,4 +7,4 @@ content/*
public/*
# Ignore examples
-examples/*
\ No newline at end of file
+codepen/*
\ No newline at end of file
diff --git a/codepen/components-and-props/composing-components.js b/codepen/components-and-props/composing-components.js
new file mode 100644
index 000000000..9158dd0cf
--- /dev/null
+++ b/codepen/components-and-props/composing-components.js
@@ -0,0 +1,18 @@
+function Welcome(props) {
+ return
Hello, {props.name}
;
+}
+
+function App() {
+ return (
+
+
+
+
+
+ );
+}
+
+ReactDOM.render(
+ ,
+ document.getElementById('root')
+);
\ No newline at end of file
diff --git a/codepen/components-and-props/extracting-components-continued.js b/codepen/components-and-props/extracting-components-continued.js
new file mode 100644
index 000000000..bcb6547b1
--- /dev/null
+++ b/codepen/components-and-props/extracting-components-continued.js
@@ -0,0 +1,52 @@
+function formatDate(date) {
+ return date.toLocaleDateString();
+}
+
+function Avatar(props) {
+ return (
+
+ );
+}
+
+function UserInfo(props) {
+ return (
+
+
+
+ {props.user.name}
+
+
+ );
+}
+
+function Comment(props) {
+ return (
+
+
+
+ {props.text}
+
+
+ {formatDate(props.date)}
+
+
+ );
+}
+
+const comment = {
+ date: new Date(),
+ text: 'I hope you enjoy learning React!',
+ author: {
+ name: 'Hello Kitty',
+ avatarUrl: 'http://placekitten.com/g/64/64'
+ }
+};
+ReactDOM.render(
+ ,
+ document.getElementById('root')
+);
\ No newline at end of file
diff --git a/codepen/components-and-props/extracting-components.js b/codepen/components-and-props/extracting-components.js
new file mode 100644
index 000000000..720624ea7
--- /dev/null
+++ b/codepen/components-and-props/extracting-components.js
@@ -0,0 +1,40 @@
+function formatDate(date) {
+ return date.toLocaleDateString();
+}
+
+function Comment(props) {
+ return (
+
+
+

+
+ {props.author.name}
+
+
+
+ {props.text}
+
+
+ {formatDate(props.date)}
+
+
+ );
+}
+
+const comment = {
+ date: new Date(),
+ text: 'I hope you enjoy learning React!',
+ author: {
+ name: 'Hello Kitty',
+ avatarUrl: 'http://placekitten.com/g/64/64'
+ }
+};
+ReactDOM.render(
+ ,
+ document.getElementById('root')
+);
\ No newline at end of file
diff --git a/codepen/components-and-props/rendering-a-component.js b/codepen/components-and-props/rendering-a-component.js
new file mode 100644
index 000000000..d42e1681c
--- /dev/null
+++ b/codepen/components-and-props/rendering-a-component.js
@@ -0,0 +1,9 @@
+function Welcome(props) {
+ return Hello, {props.name}
;
+}
+
+const element = ;
+ReactDOM.render(
+ element,
+ document.getElementById('root')
+);
\ No newline at end of file
diff --git a/content/docs/components-and-props.md b/content/docs/components-and-props.md
index 1bd1f7a65..b6e967c75 100644
--- a/content/docs/components-and-props.md
+++ b/content/docs/components-and-props.md
@@ -76,7 +76,7 @@ ReactDOM.render(
);
```
-[Try it on CodePen.](http://codepen.io/gaearon/pen/YGYmEG?editors=0010)
+Try it on CodePen.
Let's recap what happens in this example:
@@ -118,7 +118,7 @@ ReactDOM.render(
);
```
-[Try it on CodePen.](http://codepen.io/gaearon/pen/KgQKPr?editors=0010)
+Try it on CodePen.
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.
@@ -152,7 +152,7 @@ function Comment(props) {
}
```
-[Try it on CodePen.](http://codepen.io/gaearon/pen/VKQwEo?editors=0010)
+Try it on CodePen.
It accepts `author` (an object), `text` (a string), and `date` (a date) as props, and describes a comment on a social media website.
@@ -231,7 +231,7 @@ function Comment(props) {
}
```
-[Try it on CodePen.](http://codepen.io/gaearon/pen/rrJNJY?editors=0010)
+Try it on CodePen.
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.
diff --git a/gatsby-node.js b/gatsby-node.js
index 381595491..359be8011 100644
--- a/gatsby-node.js
+++ b/gatsby-node.js
@@ -6,7 +6,8 @@
'use strict';
-const {readdirSync, readFileSync} = require('fs');
+const recursiveReaddir = require('recursive-readdir');
+const {readFileSync} = require('fs');
const {resolve} = require('path');
const webpack = require('webpack');
@@ -170,12 +171,13 @@ exports.createPages = async ({graphql, boundActionCreators}) => {
// Create Codepen redirects.
// These use the Codepen prefill API to JIT-create Pens.
// https://blog.codepen.io/documentation/api/prefill/
- readdirSync('./codepen').forEach(file => {
+ const files = await recursiveReaddir('./codepen');
+ files.forEach(file => {
const slug = file.substring(0, file.length - 3); // Trim extension
- const code = readFileSync(`./codepen/${file}`, 'utf8');
+ const code = readFileSync(file, 'utf8');
createPage({
- path: `/codepen/${slug}`,
+ path: slug,
component: resolve('./src/templates/codepen-example.js'),
context: {
code,
diff --git a/package.json b/package.json
index 9adc56da2..82a862d66 100644
--- a/package.json
+++ b/package.json
@@ -84,6 +84,7 @@
"reset": "rimraf ./.cache"
},
"devDependencies": {
- "eslint-config-prettier": "^2.6.0"
+ "eslint-config-prettier": "^2.6.0",
+ "recursive-readdir": "^2.2.1"
}
}
diff --git a/yarn.lock b/yarn.lock
index a7cd0524b..c527a80a1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1535,7 +1535,7 @@ bowser@^1.6.0:
version "1.7.1"
resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.7.1.tgz#a4de8f18a1a0dc9531eb2a92a1521fb6a9ba96a5"
-brace-expansion@^1.1.7:
+brace-expansion@^1.0.0, brace-expansion@^1.1.7:
version "1.1.8"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
dependencies:
@@ -6367,6 +6367,12 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
dependencies:
brace-expansion "^1.1.7"
+minimatch@3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774"
+ dependencies:
+ brace-expansion "^1.0.0"
+
minimist@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
@@ -8054,6 +8060,12 @@ rechoir@^0.6.2:
dependencies:
resolve "^1.1.6"
+recursive-readdir@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.1.tgz#90ef231d0778c5ce093c9a48d74e5c5422d13a99"
+ dependencies:
+ minimatch "3.0.3"
+
redbox-react@^1.3.6:
version "1.5.0"
resolved "https://registry.yarnpkg.com/redbox-react/-/redbox-react-1.5.0.tgz#04dab11557d26651bf3562a67c22ace56c5d3967"