-
Notifications
You must be signed in to change notification settings - Fork 7.7k
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,7 @@ node_modules/* | |
content/* | ||
|
||
# Ignore built files | ||
public/* | ||
public/* | ||
|
||
# Ignore examples | ||
examples/* |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
ReactDOM.render( | ||
<h1>Hello, world!</h1>, | ||
document.getElementById('root') | ||
); |
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> |
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') | ||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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/') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Resolved locally by running |
||
) { | ||
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') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking forward to the day when we can use methods like 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) { There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -84,4 +84,4 @@ | |
"devDependencies": { | ||
"eslint-config-prettier": "^2.6.0" | ||
} | ||
} | ||
} |
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'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Safe to delete the un-used |
||
|
||
// 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(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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`; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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." | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; |
There was a problem hiding this comment.
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.There was a problem hiding this comment.
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