diff --git a/.eslintignore b/.eslintignore
index ff8a5577f95..9425417154d 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -4,4 +4,7 @@ node_modules/*
content/*
# Ignore built files
-public/*
\ No newline at end of file
+public/*
+
+# Ignore examples
+examples/*
\ No newline at end of file
diff --git a/content/docs/hello-world.md b/content/docs/hello-world.md
index f9be3bde544..06087d7ba59 100644
--- a/content/docs/hello-world.md
+++ b/content/docs/hello-world.md
@@ -11,7 +11,7 @@ redirect_from:
- "docs/getting-started-zh-CN.html"
---
-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.
+The easiest way to get started with React is to use this Hello World example code on CodePen. 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.
The smallest React example looks like this:
diff --git a/content/docs/introducing-jsx.md b/content/docs/introducing-jsx.md
index 9830ddc93d7..e1e4d64d183 100644
--- a/content/docs/introducing-jsx.md
+++ b/content/docs/introducing-jsx.md
@@ -46,7 +46,7 @@ ReactDOM.render(
);
```
-[Try it on CodePen.](http://codepen.io/gaearon/pen/PGEjdG?editors=0010)
+Try it on CodePen.
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).
diff --git a/examples/hello-world.js b/examples/hello-world.js
new file mode 100644
index 00000000000..d0f87a59b75
--- /dev/null
+++ b/examples/hello-world.js
@@ -0,0 +1,4 @@
+ReactDOM.render(
+
Hello, world!
,
+ document.getElementById('root')
+);
diff --git a/examples/index.html b/examples/index.html
new file mode 100644
index 00000000000..461f110596f
--- /dev/null
+++ b/examples/index.html
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/examples/introducing-jsx.js b/examples/introducing-jsx.js
new file mode 100644
index 00000000000..adb326643d6
--- /dev/null
+++ b/examples/introducing-jsx.js
@@ -0,0 +1,19 @@
+function formatName(user) {
+ return user.firstName + ' ' + user.lastName;
+}
+
+const user = {
+ firstName: 'Harper',
+ lastName: 'Perez',
+};
+
+const element = (
+
+ Hello, {formatName(user)}!
+
+);
+
+ReactDOM.render(
+ element,
+ document.getElementById('root')
+);
diff --git a/gatsby-node.js b/gatsby-node.js
index 0fc10c4f15e..5a078ffc06b 100644
--- a/gatsby-node.js
+++ b/gatsby-node.js
@@ -8,6 +8,7 @@
const {resolve} = require('path');
const webpack = require('webpack');
+const fs = require('fs');
exports.modifyWebpackConfig = ({config, stage}) => {
// See https://github.com/FormidableLabs/react-live/issues/5
@@ -74,11 +75,11 @@ exports.createPages = async ({graphql, boundActionCreators}) => {
// (which gets created by Gatsby during a separate phase).
} else if (
slug.includes('blog/') ||
- slug.includes('community/') ||
- slug.includes('contributing/') ||
- slug.includes('docs/') ||
- slug.includes('tutorial/') ||
- slug.includes('warnings/')
+ slug.includes('community/') ||
+ slug.includes('contributing/') ||
+ slug.includes('docs/') ||
+ slug.includes('tutorial/') ||
+ slug.includes('warnings/')
) {
let template;
if (slug.includes('blog/')) {
@@ -87,8 +88,8 @@ exports.createPages = async ({graphql, boundActionCreators}) => {
template = communityTemplate;
} else if (
slug.includes('contributing/') ||
- slug.includes('docs/') ||
- slug.includes('warnings/')
+ slug.includes('docs/') ||
+ slug.includes('warnings/')
) {
template = docsTemplate;
} else if (slug.includes('tutorial/')) {
@@ -117,8 +118,8 @@ exports.createPages = async ({graphql, boundActionCreators}) => {
redirect.forEach(fromPath => {
if (redirectToSlugMap[fromPath] != null) {
console.error(`Duplicate redirect detected from "${fromPath}" to:\n` +
- `* ${redirectToSlugMap[fromPath]}\n` +
- `* ${slug}\n`
+ `* ${redirectToSlugMap[fromPath]}\n` +
+ `* ${slug}\n`
);
process.exit(1);
}
@@ -161,6 +162,29 @@ exports.createPages = async ({graphql, boundActionCreators}) => {
redirectInBrowser: true,
toPath: newestBlogNode.fields.slug,
});
+
+ // Create Codepen example pages
+ const htmlTemplate = fs.readFileSync('./examples/index.html', 'utf8');
+ fs.readdirSync('./examples').forEach(file => {
+ // Only create pages for the JS files
+ if (file.toLowerCase().split('.').pop() === 'js') {
+ const slug = file.substring(0, file.length - 3);
+ const jsTemplate = fs.readFileSync(`./examples/${file}`, 'utf8');
+
+ createPage({
+ path: `/examples/${slug}`,
+ component: resolve('./src/templates/codepen-example.js'),
+ context: {
+ slug,
+ payload: {
+ html: htmlTemplate,
+ js: jsTemplate,
+ },
+ },
+ });
+ }
+ });
+
};
// Parse date information out of blog post filename.
diff --git a/package.json b/package.json
index 1d214c9f022..b6106a1090d 100644
--- a/package.json
+++ b/package.json
@@ -84,4 +84,4 @@
"devDependencies": {
"eslint-config-prettier": "^2.6.0"
}
-}
+}
\ No newline at end of file
diff --git a/src/templates/codepen-example.js b/src/templates/codepen-example.js
new file mode 100644
index 00000000000..7079cc53788
--- /dev/null
+++ b/src/templates/codepen-example.js
@@ -0,0 +1,64 @@
+'use strict';
+
+import React, {Component} from 'react';
+import Container from 'components/Container';
+import {colors} from 'theme';
+// import {version} from '../site-constants';
+
+// Copied over styles from ButtonLink for the submit btn
+const primaryStyle = {
+ backgroundColor: colors.brand,
+ color: colors.black,
+ padding: '10px 25px',
+ whiteSpace: 'nowrap',
+ transition: 'background-color 0.2s ease-out',
+ outline: 0,
+ border: 'none',
+ cursor: 'pointer',
+
+ ':hover': {
+ backgroundColor: colors.white,
+ },
+
+ display: 'inline-block',
+ fontSize: 16,
+};
+
+class CodepenExample extends Component {
+ componentDidMount() {
+ this.codepenForm.submit();
+ }
+
+ render() {
+ const {payload} = this.props.pathContext;
+ // Set codepen options
+ payload.js_pre_processor = 'babel';
+ // Only have the JS editor open (default for all examples)
+ payload.editors = '0010';
+ // We can pass @version in the URL for version locking, if desired.
+ payload.js_external = `https://unpkg.com/react/umd/react.development.js;https://unpkg.com/react-dom/umd/react-dom.development.js`;
+
+ return (
+
+ Redirecting to Codepen...
+
+
+ );
+ }
+}
+
+export default CodepenExample;