Skip to content

Seamlessly sync examples from Github -> Codepen #162

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ node_modules/*
content/*

# Ignore built files
public/*
public/*

# Ignore examples
examples/*
2 changes: 1 addition & 1 deletion content/docs/hello-world.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <a href="/examples/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.

The smallest React example looks like this:

Expand Down
2 changes: 1 addition & 1 deletion content/docs/introducing-jsx.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ ReactDOM.render(
);
```

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find myself wanting a follow-up item to also pull the code snippet shown within the Markdown from the examples folder as well, so the 2 will automatically stay in sync.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've since done this (or at least similar) with commit f5aaf4c


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).

Expand Down
4 changes: 4 additions & 0 deletions examples/hello-world.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);
3 changes: 3 additions & 0 deletions examples/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div id="root">
<!-- This div's content will be managed by React. -->
</div>
19 changes: 19 additions & 0 deletions examples/introducing-jsx.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
function formatName(user) {
return user.firstName + ' ' + user.lastName;
}

const user = {
firstName: 'Harper',
lastName: 'Perez',
};

const element = (
<h1>
Hello, {formatName(user)}!
</h1>
);

ReactDOM.render(
element,
document.getElementById('root')
);
42 changes: 33 additions & 9 deletions gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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/')) {
Expand All @@ -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/')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These whitespace changes in this file are unexpected. Were they something your editor did by chance?

We use Prettier to ensure consistent formatting within the codebase (and avoid potential time spent debating the merits of formatting issues 😁 ). Looks like Prettier wasn't running on the gatsby-* JS files b'c they were in the root directory. I've fixed this in master. Mind rebasing and running yarn prettier to make sure these whitespace-only changes are Prettier approved?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved locally by running yarn prettier

) {
template = docsTemplate;
} else if (slug.includes('tutorial/')) {
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking forward to the day when we can use methods like endsWith without polyfilling 😄

It probably doesn't matter, but it would be a bit more efficient to write this check as:

if (file.indexOf('.js', file.length - 3) !== -1) {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, couldn't we just remove this check entirely and say "only .js files go in the examples folder"? The HTML boilerplate is so minimal it's okay to just embed it directly within the template as a constant, eg:

const HTML = '<div id="root"></div>;'

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.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,4 @@
"devDependencies": {
"eslint-config-prettier": "^2.6.0"
}
}
}
64 changes: 64 additions & 0 deletions src/templates/codepen-example.js
Original file line number Diff line number Diff line change
@@ -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';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Safe to delete the un-used version import?


// 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();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm. First 2 times I tried this redirect just now it timed out. Third time it worked. Odd.

Now it's working every time. 😄

}

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`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's interesting. Probably unnecessary though as I think we'd always aim to keep examples working for the latest release of React.


return (
<Container>
<h1>Redirecting to Codepen...</h1>
<form
style={{paddingBottom: '50px'}}
ref={form => {
this.codepenForm = form;
}}
action="https://codepen.io/pen/define"
method="POST">
<input type="hidden" name="data" value={JSON.stringify(payload)} />

<input
style={primaryStyle}
type="submit"
value="Not automatically redirecting? Click here."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this is too much text for a button. 😄 Maybe something more like this?

<p>Not automatically redirecting?</p>
<button>Click here</button>

/>
</form>
</Container>
);
}
}

export default CodepenExample;