Skip to content

Commit b781e43

Browse files
committed
Add experimental react support within markdown
Also added fronmatter for interactive: true to turn on React on a file by file basis and prevent slowing down the builds for non-react files
1 parent 0547215 commit b781e43

File tree

16 files changed

+31834
-581
lines changed

16 files changed

+31834
-581
lines changed

assets/js/react-dom.development.js

Lines changed: 25147 additions & 0 deletions
Large diffs are not rendered by default.

assets/js/react.development.js

Lines changed: 3318 additions & 0 deletions
Large diffs are not rendered by default.

content/github/getting-started-with-github/access-permissions-on-github.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ intro: 'While you can grant read/write access to collaborators on a personal rep
99
versions:
1010
free-pro-team: '*'
1111
enterprise-server: '*'
12+
interactive: true
1213
---
1314

1415
### Personal user accounts
@@ -17,16 +18,33 @@ A repository owned by a user account has two permission levels: the *repository
1718

1819
### Organization accounts
1920

21+
#### Code Block Component
22+
<!--react-->
23+
<CodeBlock language="javascript">
24+
{`var i;
25+
for (i = 0; i < cars.length; i++) {
26+
text += cars[i] + "<br>";
27+
}`}
28+
</CodeBlock>
29+
<!--end-react-->
30+
2031
Organization members can have *owner*{% if currentVersion == "free-pro-team@latest" %}, *billing manager*,{% endif %} or *member* roles. Owners have complete administrative access to your organization{% if currentVersion == "free-pro-team@latest" %}, while billing managers can manage billing settings{% endif %}. Member is the default role for everyone else. You can manage access permissions for multiple members at a time with teams. For more information, see:
2132
- "[Permission levels for an organization](/articles/permission-levels-for-an-organization)"
2233
- "[Project board permissions for an organization](/articles/project-board-permissions-for-an-organization)"
2334
- "[Repository permission levels for an organization](/articles/repository-permission-levels-for-an-organization)"
2435
- "[About teams](/articles/about-teams)"
2536

37+
#### Code Editor Component
38+
39+
<!--react--><RedContent>Red content!</RedContent><!--end-react-->
40+
41+
<!--react--><Timer /><!--end-react-->
42+
2643
{% if currentVersion == "free-pro-team@latest" %}
2744

2845
### Enterprise accounts
2946

47+
3048
*Enterprise owners* have ultimate power over the enterprise account and can take every action in the enterprise account. *Billing managers* can manage your enterprise account's billing settings. Members and outside collaborators of organizations owned by your enterprise account are automatically members of the enterprise account, although they have no access to the enterprise account itself or its settings. For more information, see "[Roles for an enterprise account](/articles/roles-for-an-enterprise-account)."
3149

3250
{% data reusables.gated-features.enterprise-accounts %}

includes/head.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,6 @@
2626
<link rel="stylesheet" href="/dist/index.css">
2727
<link rel="alternate icon" type="image/png" href="/assets/images/site/favicon.png">
2828
<link rel="icon" type="image/svg+xml" href="/assets/images/site/favicon.svg">
29+
<script src="/assets/js/react.development.js" crossorigin></script>
30+
<script src="/assets/js/react-dom.development.js" crossorigin></script>
2931
</head>

javascripts/index.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ import experiment from './experiment'
1616
import copyCode from './copy-code'
1717
import { fillCsrf } from './get-csrf'
1818
import initializeEvents from './events'
19+
import CodeBlock from '../react/CodeBlock'
20+
import RedContent from '../react/RedContent'
21+
import Timer from '../react/Timer'
1922

2023
document.addEventListener('DOMContentLoaded', async () => {
2124
displayPlatformSpecificContent()
@@ -35,3 +38,9 @@ document.addEventListener('DOMContentLoaded', async () => {
3538
copyCode()
3639
initializeEvents()
3740
})
41+
42+
module.export = {
43+
CodeBlock,
44+
RedContent,
45+
Timer
46+
}

lib/frontmatter.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ const schema = {
7070
quickstart: { type: 'string' },
7171
learn: { type: 'string' }
7272
}
73+
},
74+
interactive: {
75+
type: 'boolean'
7376
}
7477
}
7578
}

lib/page.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ const pathUtils = require('./path-utils')
1515
const Permalink = require('./permalink')
1616
const languages = require('./languages')
1717
const renderContent = require('./render-content')
18+
const { renderReact } = require('./react/engine')
1819
const frontmatter = require('./frontmatter')
1920
const products = require('./all-products')
2021
const slash = require('slash')
2122

23+
2224
class Page {
2325
constructor (opts) {
2426
assert(opts.relativePath, 'relativePath is required')
@@ -119,9 +121,30 @@ class Page {
119121
this.title = await renderContent(this.rawTitle, context, { textOnly: true, encodeEntities: true })
120122
this.shortTitle = await renderContent(this.shortTitle, context, { textOnly: true, encodeEntities: true })
121123

122-
const markdown = this.mapTopic
124+
let markdown = this.mapTopic
123125
? getMapTopicContent(this, context.pages, context.redirects)
124126
: this.markdown
127+
128+
// If the article is interactive parse the React!
129+
if (this.interactive) {
130+
// Search for the react code comments to find the react components
131+
const reactComponents = markdown.match(/<!--react-->(.*?)<!--end-react-->/gms)
132+
133+
// Render each of the react components in the markdown
134+
for (const index in reactComponents) {
135+
let componentStr = reactComponents[index]
136+
137+
// Remove the React comment indicators
138+
componentStr = componentStr.replace('<!--react-->\n', '').replace('<!--react-->', '')
139+
componentStr = componentStr.replace('\n<!--end-react-->', '').replace('<!--end-react-->', '')
140+
141+
// Get the rendered component
142+
const renderedComponent = await renderReact(componentStr)
143+
144+
// Replace the react component with the rendered markdown
145+
markdown = markdown.replace(reactComponents[index], renderedComponent)
146+
}
147+
}
125148

126149
const html = await renderContent(markdown, context)
127150

@@ -163,6 +186,7 @@ class Page {
163186
return cleanedHTML
164187
}
165188

189+
166190
// Allow other modules (like custom liquid tags) to make one-off requests
167191
// for a page's rendered properties like `title` and `intro`
168192
async renderProp (propName, context, opts = { unwrap: false }) {
@@ -179,6 +203,7 @@ class Page {
179203

180204
const html = await renderContent(prop, context, opts)
181205

206+
182207
if (!opts.unwrap) return html
183208

184209
// The unwrap option removes surrounding tags from a string, preserving any inner HTML

lib/react/engine.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
const { renderToString } = require('react-dom/server')
2+
const transform = require('./transform')
3+
4+
// These all need to be here even though eslint doesn't think so
5+
/* eslint-disable */
6+
const React = require('react')
7+
const CodeBlock = require('../../dist/react/CodeBlock')
8+
const RedContent = require('../../dist/react/RedContent')
9+
const Timer = require('../../dist/react/Timer')
10+
/* eslint-enable */
11+
12+
const renderReact = async componentStr => {
13+
const componentName = componentStr.match(/[^<]([a-zA-Z])*/gm)[0]
14+
const jsx = `<div className="react-component-${componentName}">\n${componentStr}\n</div>`
15+
const component = transform(jsx)
16+
17+
// eslint-disable-next-line
18+
return renderToString(eval(component))
19+
}
20+
21+
module.exports = {
22+
renderReact
23+
}

lib/react/transform.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const babel = require('@babel/core')
2+
const transform = code =>
3+
babel.transform(code, {
4+
presets: ['@babel/preset-env'],
5+
plugins: [
6+
'@babel/plugin-transform-react-jsx',
7+
'@babel/plugin-proposal-object-rest-spread',
8+
'@babel/plugin-transform-modules-commonjs',
9+
'@babel/plugin-proposal-class-properties'
10+
]
11+
}).code
12+
13+
module.exports = transform

0 commit comments

Comments
 (0)