mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 15:47:23 +02:00
[markdown] Switch to Remarkable (#153)
* Switch to Remarkable * Clean up references to custom code blocks * Remove valdiateDOMNesting warning * Add syntax highlighting * Add Reason support * Breaking change: prismColor to codeColor, remove CompLibrary.Prism, expose hljs * Completely remove Prism and associated CSS rules * Support loading plugins and scripts * Remove CSS rules, allowing Highlight.js theme to be used entirely * Remove unnecessary webplayer script
This commit is contained in:
parent
58613545b6
commit
b832176dc6
18 changed files with 231 additions and 2744 deletions
|
@ -17,7 +17,7 @@ Documents use the following markdown header fields that are enclosed by a line `
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
```markup
|
```
|
||||||
---
|
---
|
||||||
id: doc1
|
id: doc1
|
||||||
title: My Document
|
title: My Document
|
||||||
|
@ -29,7 +29,7 @@ Versioned documents have their ids altered to include the version number when th
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
```markup
|
```
|
||||||
---
|
---
|
||||||
id: version-1.0.0-doc1
|
id: version-1.0.0-doc1
|
||||||
title: My Document
|
title: My Document
|
||||||
|
@ -52,7 +52,7 @@ Blog Posts use the following markdown header fields that are enclosed by a line
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
```markup
|
```
|
||||||
---
|
---
|
||||||
title: My First Blog Post
|
title: My First Blog Post
|
||||||
author: Frank Li
|
author: Frank Li
|
||||||
|
@ -91,9 +91,10 @@ Example:
|
||||||
|
|
||||||
You can make an autogenerated list of links, which can be useful as a table of contents for API docs.
|
You can make an autogenerated list of links, which can be useful as a table of contents for API docs.
|
||||||
|
|
||||||
In your markdown file, insert a line with the text <`AUTOGENERATED_TABLE_OF_CONTENTS>`. Write your documentation using `h3` headers for each function inside a code block. These will be found by Docusaurus and a list of links to these sections will inserted at the text <`AUTOGENERATED_TABLE_OF_CONTENTS>`.
|
In your markdown file, insert a line with the text <`AUTOGENERATED_TABLE_OF_CONTENTS`>. Write your documentation using `h3` headers for each function inside a code block. These will be found by Docusaurus and a list of links to these sections will inserted at the text <`AUTOGENERATED_TABLE_OF_CONTENTS`>.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
### `docusaurus.function(a, b)`
|
### `docusaurus.function(a, b)`
|
||||||
|
|
||||||
|
@ -111,4 +112,50 @@ will lead to a table of contents of the functions:
|
||||||
- `docusaurus.function(a, b)`
|
- `docusaurus.function(a, b)`
|
||||||
- `docdoc(file)`
|
- `docdoc(file)`
|
||||||
```
|
```
|
||||||
|
|
||||||
and each function will link to their corresponding sections in the page.
|
and each function will link to their corresponding sections in the page.
|
||||||
|
|
||||||
|
## Syntax Highlighting
|
||||||
|
|
||||||
|
Syntax highlighting is enabled by default on fenced code blocks. The language should be detected automatically, but you can sometimes get better results by specifying the language. You can do so using an [info string](https://github.github.com/gfm/#example-111), following the three opening backticks. The following JavaScript example...
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
ReactDOM.render(
|
||||||
|
<h1>Hello, world!</h1>,
|
||||||
|
document.getElementById('root')
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
...would be rendered with syntax highlighting like so:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
ReactDOM.render(
|
||||||
|
<h1>Hello, world!</h1>,
|
||||||
|
document.getElementById('root')
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Highlighting is provided by [Highlight.js](https://highlightjs.org) using the theme specified in your `siteConfig.js` file as part of the `highlight` key:
|
||||||
|
|
||||||
|
```
|
||||||
|
highlight: {
|
||||||
|
theme: 'default'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can find the full list of supported themes in the Highlight.js [`styles`](https://github.com/isagalaev/highlight.js/tree/master/src/styles) directory.
|
||||||
|
|
||||||
|
### Registering additional languages
|
||||||
|
|
||||||
|
While Highlight.js provides support for [many popular languages out of the box](https://highlightjs.org/static/demo/), you may find the need to register additional language support. For these cases, we provide an escape valve by exposing the `hljs` constant as part of the `highlight` config key. This in turn allows you to call [`registerLanguage`](http://highlightjs.readthedocs.io/en/latest/api.html#registerlanguage-name-language):
|
||||||
|
|
||||||
|
```
|
||||||
|
highlight: {
|
||||||
|
theme: 'default',
|
||||||
|
hljs: function(hljs) {
|
||||||
|
hljs.registerLanguage('galacticbasic', function(hljs) {
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
@ -127,7 +127,7 @@ Static assets should be placed into the `website/static` folder. They can be acc
|
||||||
|
|
||||||
## Styles
|
## Styles
|
||||||
|
|
||||||
You should configure your site's primary, secondary, and Prism colors using the `colors` field in `siteConfig` as specified [here](site-config.md). You can also configure other colors in the same way as described in the `siteConfig` doc.
|
You should configure your site's primary, secondary, and code block colors using the `colors` field in `siteConfig` as specified [here](api-site-config.md). You can also configure other colors in the same way as described in the `siteConfig` doc.
|
||||||
|
|
||||||
You can provide your own custom styles by adding them anywhere in the `website/static` folder. Any `.css` files you provide in the `static` folder will get concatenated to the end of Docusaurus's provided styles, allowing you to add to or override Docusaurus default styles as you wish.
|
You can provide your own custom styles by adding them anywhere in the `website/static` folder. Any `.css` files you provide in the `static` folder will get concatenated to the end of Docusaurus's provided styles, allowing you to add to or override Docusaurus default styles as you wish.
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,6 @@ headerLinks: [
|
||||||
|
|
||||||
- `primaryColor` is the color used the header navigation bar and sidebars.
|
- `primaryColor` is the color used the header navigation bar and sidebars.
|
||||||
- `secondaryColor` is the color seen in the second row of the header navigation bar when the site window is narrow (including on mobile).
|
- `secondaryColor` is the color seen in the second row of the header navigation bar when the site window is narrow (including on mobile).
|
||||||
- `prismColor` is the color used in the background of syntax highlighting for code in documentation. It is recommended to be the same color as `primaryColor` in `rgba` form with an alpha value of `0.03`. Other fields can be added
|
|
||||||
- Custom color configurations can also be added. For example, if user styles are added with colors specified as `$myColor`, then adding a `myColor` field to `colors` will allow you to easily configure this color.
|
- Custom color configurations can also be added. For example, if user styles are added with colors specified as `$myColor`, then adding a `myColor` field to `colors` will allow you to easily configure this color.
|
||||||
|
|
||||||
`copyright` - The copyright string at footer of site and within feed
|
`copyright` - The copyright string at footer of site and within feed
|
||||||
|
@ -81,9 +80,18 @@ headerLinks: [
|
||||||
|
|
||||||
`gaTrackingId` - Google Analytics tracking ID to track page views.
|
`gaTrackingId` - Google Analytics tracking ID to track page views.
|
||||||
|
|
||||||
|
|
||||||
`sourceCodeButton` - the type of button to use for pointing to your source code. If this field is non-null, the site will pull in the appropriate button code in the header, for you to be able to render as you see fit. Currently accepted values: `"github"`, `"none"`. Defaults to `"github"`.
|
`sourceCodeButton` - the type of button to use for pointing to your source code. If this field is non-null, the site will pull in the appropriate button code in the header, for you to be able to render as you see fit. Currently accepted values: `"github"`, `"none"`. Defaults to `"github"`.
|
||||||
|
|
||||||
|
`highlight` - [Syntax highlighting](api-doc-markdown.md) options:
|
||||||
|
|
||||||
|
- `theme` is the name of the theme used by Highlight.js when highlighting code.
|
||||||
|
- `version` specifies a particular version of Highlight.js to be used.
|
||||||
|
- `hljs` provides an escape valve by passing an instance of Highlight.js to the function specified here, allowing additional languages to be registered for syntax highlighting.
|
||||||
|
|
||||||
|
`markdownPlugins` - An array of plugins to be loaded by Remarkable, the markdown parser and renderer used by Docusaurus. The plugin will receive a reference to the Remarkable instance, allowing custom parsing and rendering rules to be defined.
|
||||||
|
|
||||||
|
`scripts` - Array of JavaScript sources to load. The script tag will be inserted in the HTML head.
|
||||||
|
|
||||||
Users can also add their own custom fields if they wish to provide some data across different files.
|
Users can also add their own custom fields if they wish to provide some data across different files.
|
||||||
|
|
||||||
## Example siteConfig.js with all fields
|
## Example siteConfig.js with all fields
|
||||||
|
@ -118,12 +126,8 @@ const siteConfig = {
|
||||||
favicon: "img/favicon.png",
|
favicon: "img/favicon.png",
|
||||||
colors: {
|
colors: {
|
||||||
primaryColor: "#2E8555",
|
primaryColor: "#2E8555",
|
||||||
secondaryColor: "#205C3B",
|
secondaryColor: "#205C3B"
|
||||||
prismColor:
|
|
||||||
"rgba(46, 133, 85, 0.03)"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
editUrl: "https://github.com/deltice/test-site/edit/master/docs/",
|
editUrl: "https://github.com/deltice/test-site/edit/master/docs/",
|
||||||
users,
|
users,
|
||||||
disableHeaderTitle: true,
|
disableHeaderTitle: true,
|
||||||
|
@ -138,9 +142,20 @@ const siteConfig = {
|
||||||
indexName: "github"
|
indexName: "github"
|
||||||
},
|
},
|
||||||
gaTrackingId: "U-A2352",
|
gaTrackingId: "U-A2352",
|
||||||
sourceCodeButton: "github"
|
sourceCodeButton: "github",
|
||||||
|
highlight: {
|
||||||
|
theme: 'default'
|
||||||
|
},
|
||||||
|
markdownPlugins: [
|
||||||
|
function foo(md) {
|
||||||
|
md.renderer.rules.fence_custom.foo = function(tokens, idx, options, env, instance) {
|
||||||
|
return '<div class="foo">bar</div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
scripts: [ "https://docusaurus.io/slash.js" ]
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = siteConfig;
|
module.exports = siteConfig;
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -35,15 +35,17 @@ const siteConfig = {
|
||||||
/* colors for website */
|
/* colors for website */
|
||||||
colors: {
|
colors: {
|
||||||
primaryColor: "#2E8555",
|
primaryColor: "#2E8555",
|
||||||
secondaryColor: "#205C3B",
|
secondaryColor: "#205C3B"
|
||||||
prismColor:
|
|
||||||
"rgba(46, 133, 85, 0.03)" /* primaryColor in rgba form, with 0.03 alpha */
|
|
||||||
},
|
},
|
||||||
// This copyright info is used in /core/Footer.js and blog rss/atom feeds.
|
// This copyright info is used in /core/Footer.js and blog rss/atom feeds.
|
||||||
copyright:
|
copyright:
|
||||||
"Copyright © " +
|
"Copyright © " +
|
||||||
new Date().getFullYear() +
|
new Date().getFullYear() +
|
||||||
" Your Name or Your Company Name"
|
" Your Name or Your Company Name",
|
||||||
|
highlight: {
|
||||||
|
// Highlight.js theme to use for syntax highlighting in code blocks
|
||||||
|
theme: "default"
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = siteConfig;
|
module.exports = siteConfig;
|
||||||
|
|
|
@ -8,12 +8,10 @@
|
||||||
const Marked = require("./Marked.js");
|
const Marked = require("./Marked.js");
|
||||||
const Container = require("./Container.js");
|
const Container = require("./Container.js");
|
||||||
const GridBlock = require("./GridBlock.js");
|
const GridBlock = require("./GridBlock.js");
|
||||||
const Prism = require("./Prism.js");
|
|
||||||
|
|
||||||
// collection of other components to provide to users
|
// collection of other components to provide to users
|
||||||
module.exports = {
|
module.exports = {
|
||||||
Marked: Marked,
|
Marked: Marked,
|
||||||
Container: Container,
|
Container: Container,
|
||||||
GridBlock: GridBlock,
|
GridBlock: GridBlock
|
||||||
Prism: Prism
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,15 +10,24 @@ const React = require("react");
|
||||||
// html head for each page
|
// html head for each page
|
||||||
class Head extends React.Component {
|
class Head extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
let links = this.props.config.headerLinks;
|
const links = this.props.config.headerLinks;
|
||||||
let hasBlog = false;
|
let hasBlog = false;
|
||||||
links.map(link => {
|
links.map(link => {
|
||||||
if (link.blog) hasBlog = true;
|
if (link.blog) hasBlog = true;
|
||||||
});
|
});
|
||||||
let sourceCodeButton = this.props.config.sourceCodeButton;
|
const sourceCodeButton = this.props.config.sourceCodeButton;
|
||||||
// defaults to github, but other values may be allowed in the future
|
// defaults to GitHub, but other values may be allowed in the future
|
||||||
let includeGithubButton =
|
const includeGitHubButton =
|
||||||
sourceCodeButton === "github" || sourceCodeButton == null;
|
sourceCodeButton === "github" || sourceCodeButton == null;
|
||||||
|
|
||||||
|
const highlightDefaultVersion = '9.12.0';
|
||||||
|
const highlightConfig = this.props.config.highlight
|
||||||
|
|| { version: highlightDefaultVersion, theme: 'default' };
|
||||||
|
const highlightVersion = highlightConfig.version || highlightDefaultVersion;
|
||||||
|
const highlightTheme = highlightConfig.theme || 'default';
|
||||||
|
|
||||||
|
const hasCustomScripts = this.props.config.scripts;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<head>
|
<head>
|
||||||
<meta charSet="utf-8" />
|
<meta charSet="utf-8" />
|
||||||
|
@ -64,7 +73,7 @@ class Head extends React.Component {
|
||||||
href={this.props.config.url + "/blog/atom.xml"}
|
href={this.props.config.url + "/blog/atom.xml"}
|
||||||
title={this.props.config.title + " Blog ATOM Feed"}
|
title={this.props.config.title + " Blog ATOM Feed"}
|
||||||
/>
|
/>
|
||||||
)}{" "}
|
)}
|
||||||
{hasBlog && (
|
{hasBlog && (
|
||||||
<link
|
<link
|
||||||
rel="alternate"
|
rel="alternate"
|
||||||
|
@ -73,14 +82,18 @@ class Head extends React.Component {
|
||||||
title={this.props.config.title + " Blog RSS Feed"}
|
title={this.props.config.title + " Blog RSS Feed"}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{includeGithubButton && (
|
{includeGitHubButton && (
|
||||||
<script async defer src="https://buttons.github.io/buttons.js" />
|
<script async defer src="https://buttons.github.io/buttons.js" />
|
||||||
)}
|
)}
|
||||||
<script
|
<link
|
||||||
type="text/javascript"
|
rel="stylesheet"
|
||||||
src={this.props.config.baseUrl + "js/webplayer.js"}
|
href={`//cdnjs.cloudflare.com/ajax/libs/highlight.js/${highlightVersion}/styles/${highlightTheme}.min.css`}
|
||||||
/>
|
/>
|
||||||
<script type="text/javascript" src="https://snack.expo.io/embed.js" />
|
{hasCustomScripts && this.props.config.scripts.map(function(source) {
|
||||||
|
return (
|
||||||
|
<script type="text/javascript" src={source} />
|
||||||
|
);
|
||||||
|
})}
|
||||||
</head>
|
</head>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
1110
lib/core/Marked.js
1110
lib/core/Marked.js
File diff suppressed because it is too large
Load diff
1161
lib/core/Prism.js
1161
lib/core/Prism.js
File diff suppressed because it is too large
Load diff
93
lib/core/Remarkable.js
Normal file
93
lib/core/Remarkable.js
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const React = require('react');
|
||||||
|
const hljs = require('highlight.js')
|
||||||
|
const Markdown = require('Remarkable');
|
||||||
|
const toSlug = require("./toSlug.js");
|
||||||
|
|
||||||
|
const CWD = process.cwd();
|
||||||
|
|
||||||
|
function anchors(md) {
|
||||||
|
md.renderer.rules.heading_open = function(tokens, idx /*, options, env */) {
|
||||||
|
return '<h' + tokens[idx].hLevel + '>' + '<a class="anchor" name="' + toSlug(tokens[idx+1].content) + '"></a>';
|
||||||
|
};
|
||||||
|
md.renderer.rules.heading_close = function(tokens, idx /*, options, env */) {
|
||||||
|
return ' <a class="hash-link" href="#' + toSlug(tokens[idx-1].content) + '">#</a>' + '</h' + tokens[idx].hLevel + '>\n';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class Remarkable extends React.Component {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
var Container = this.props.container;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container>
|
||||||
|
{this.content()}
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUpdate(nextProps, nextState) {
|
||||||
|
if (nextProps.options !== this.props.options) {
|
||||||
|
this.md = new Markdown(nextProps.options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
content() {
|
||||||
|
if (this.props.source) {
|
||||||
|
return <span dangerouslySetInnerHTML={{ __html: this.renderMarkdown(this.props.source) }} />;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return React.Children.map(this.props.children, child => {
|
||||||
|
if (typeof child === 'string') {
|
||||||
|
return <span dangerouslySetInnerHTML={{ __html: this.renderMarkdown(child) }} />;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderMarkdown(source) {
|
||||||
|
if (!this.md) {
|
||||||
|
this.md = new Markdown({
|
||||||
|
highlight: function (str, lang) {
|
||||||
|
if (lang && hljs.getLanguage(lang)) {
|
||||||
|
try {
|
||||||
|
return hljs.highlight(lang, str).value;
|
||||||
|
} catch (err) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return hljs.highlightAuto(str).value;
|
||||||
|
} catch (err) {}
|
||||||
|
|
||||||
|
return ''; // use external default escaping
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Register anchors plugin
|
||||||
|
this.md.use(anchors);
|
||||||
|
|
||||||
|
// Allow client sites to register their own plugins
|
||||||
|
const siteConfig = require(CWD + "/siteConfig.js");
|
||||||
|
if (siteConfig.markdownPlugins) {
|
||||||
|
siteConfig.markdownPlugins.forEach(function(plugin) {
|
||||||
|
this.md.use(plugin);
|
||||||
|
}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.md.render(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Remarkable.defaultProps = {
|
||||||
|
container: 'div',
|
||||||
|
options: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Remarkable;
|
|
@ -32,6 +32,10 @@ class Site extends React.Component {
|
||||||
(this.props.url || "index.html");
|
(this.props.url || "index.html");
|
||||||
let latestVersion;
|
let latestVersion;
|
||||||
|
|
||||||
|
const highlightDefaultVersion = '9.12.0';
|
||||||
|
const highlightConfig = this.props.config.highlight
|
||||||
|
|| { version: highlightDefaultVersion, theme: 'default' };
|
||||||
|
const highlightVersion = highlightConfig.version || highlightDefaultVersion;
|
||||||
if (fs.existsSync(CWD + "/versions.json")) {
|
if (fs.existsSync(CWD + "/versions.json")) {
|
||||||
latestVersion = require(CWD + "/versions.json")[0];
|
latestVersion = require(CWD + "/versions.json")[0];
|
||||||
}
|
}
|
||||||
|
@ -124,6 +128,12 @@ class Site extends React.Component {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
<script src={`//cdnjs.cloudflare.com/ajax/libs/highlight.js/${highlightVersion}/highlight.min.js`}></script>
|
||||||
|
<script
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: `hljs.initHighlightingOnLoad();`
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,139 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) 2017-present, Facebook, Inc.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @providesModule SnackPlayer
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var Prism = require('./Prism');
|
|
||||||
var React = require('react');
|
|
||||||
|
|
||||||
const PropTypes = require('prop-types');
|
|
||||||
|
|
||||||
const LatestSDKVersion = '21.0.0';
|
|
||||||
var ReactNativeToExpoSDKVersionMap = {
|
|
||||||
'0.48': '21.0.0',
|
|
||||||
'0.47': '20.0.0',
|
|
||||||
'0.46': '19.0.0',
|
|
||||||
'0.45': '18.0.0',
|
|
||||||
'0.44': '17.0.0',
|
|
||||||
'0.43': '16.0.0',
|
|
||||||
'0.42': '15.0.0',
|
|
||||||
'0.41': '14.0.0',
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use the SnackPlayer by including a ```SnackPlayer``` block in markdown.
|
|
||||||
*
|
|
||||||
* Optionally, include url parameters directly after the block's language.
|
|
||||||
* Valid options are name, description, and platform.
|
|
||||||
*
|
|
||||||
* E.g.
|
|
||||||
* ```SnackPlayer?platform=android&name=Hello%20world!
|
|
||||||
* import React from 'react';
|
|
||||||
* import { Text } from 'react-native';
|
|
||||||
*
|
|
||||||
* export default class App extends React.Component {
|
|
||||||
* render() {
|
|
||||||
* return <Text>Hello World!</Text>;
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
class SnackPlayer extends React.Component {
|
|
||||||
constructor(props, context) {
|
|
||||||
super(props, context);
|
|
||||||
|
|
||||||
this.parseParams = this.parseParams.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
window.ExpoSnack && window.ExpoSnack.initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
var code = encodeURIComponent(this.props.children);
|
|
||||||
var params = this.parseParams(this.props.params);
|
|
||||||
var platform = params.platform
|
|
||||||
? params.platform
|
|
||||||
: 'ios';
|
|
||||||
var name = params.name
|
|
||||||
? decodeURIComponent(params.name)
|
|
||||||
: 'Example';
|
|
||||||
var description = params.description
|
|
||||||
? decodeURIComponent(params.description)
|
|
||||||
: 'Example usage';
|
|
||||||
|
|
||||||
var optionalProps = {};
|
|
||||||
var { version } = this.context;
|
|
||||||
if (version === 'next') {
|
|
||||||
optionalProps[
|
|
||||||
'data-snack-sdk-version'
|
|
||||||
] = LatestSDKVersion;
|
|
||||||
} else {
|
|
||||||
optionalProps[
|
|
||||||
'data-snack-sdk-version'
|
|
||||||
] = ReactNativeToExpoSDKVersionMap[version] ||
|
|
||||||
LatestSDKVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="snack-player">
|
|
||||||
<div
|
|
||||||
className="mobile-friendly-snack"
|
|
||||||
style={{ display: 'none' }}
|
|
||||||
>
|
|
||||||
<Prism>
|
|
||||||
{this.props.children}
|
|
||||||
</Prism>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
className="desktop-friendly-snack"
|
|
||||||
style={{ marginTop: 15, marginBottom: 15 }}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
data-snack-name={name}
|
|
||||||
data-snack-description={description}
|
|
||||||
data-snack-code={code}
|
|
||||||
data-snack-platform={platform}
|
|
||||||
data-snack-preview="true"
|
|
||||||
{...optionalProps}
|
|
||||||
style={{
|
|
||||||
overflow: 'hidden',
|
|
||||||
background: '#fafafa',
|
|
||||||
border: '1px solid rgba(0,0,0,.16)',
|
|
||||||
borderRadius: '4px',
|
|
||||||
height: '514px',
|
|
||||||
width: '880px',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
parseParams(paramString) {
|
|
||||||
var params = {};
|
|
||||||
|
|
||||||
if (paramString) {
|
|
||||||
var pairs = paramString.split('&');
|
|
||||||
for (var i = 0; i < pairs.length; i++) {
|
|
||||||
var pair = pairs[i].split('=');
|
|
||||||
params[pair[0]] = pair[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return params;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SnackPlayer.contextTypes = {
|
|
||||||
version: PropTypes.number.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = SnackPlayer;
|
|
|
@ -1,75 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) 2017-present, Facebook, Inc.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*
|
|
||||||
* @providesModule WebPlayer
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
var Prism = require('./Prism');
|
|
||||||
var React = require('react');
|
|
||||||
|
|
||||||
var WEB_PLAYER_VERSION = '1.10.0';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use the WebPlayer by including a ```ReactNativeWebPlayer``` block in markdown.
|
|
||||||
*
|
|
||||||
* Optionally, include url parameters directly after the block's language. For
|
|
||||||
* the complete list of url parameters, see: https://github.com/dabbott/react-native-web-player
|
|
||||||
*
|
|
||||||
* E.g.
|
|
||||||
* ```ReactNativeWebPlayer?platform=android
|
|
||||||
* import React from 'react';
|
|
||||||
* import { AppRegistry, Text } from 'react-native';
|
|
||||||
*
|
|
||||||
* const App = () => <Text>Hello World!</Text>;
|
|
||||||
*
|
|
||||||
* AppRegistry.registerComponent('MyApp', () => App);
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
class WebPlayer extends React.Component {
|
|
||||||
constructor(props, context) {
|
|
||||||
super(props, context);
|
|
||||||
|
|
||||||
this.parseParams = this.parseParams.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
parseParams(paramString) {
|
|
||||||
var params = {};
|
|
||||||
|
|
||||||
if (paramString) {
|
|
||||||
var pairs = paramString.split('&');
|
|
||||||
for (var i = 0; i < pairs.length; i++) {
|
|
||||||
var pair = pairs[i].split('=');
|
|
||||||
params[pair[0]] = pair[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return params;
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
var hash = `#code=${encodeURIComponent(this.props.children)}`;
|
|
||||||
|
|
||||||
if (this.props.params) {
|
|
||||||
hash += `&${this.props.params}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={'web-player'}>
|
|
||||||
<Prism>{this.props.children}</Prism>
|
|
||||||
<iframe
|
|
||||||
style={{marginTop: 4}}
|
|
||||||
width="880"
|
|
||||||
height={this.parseParams(this.props.params).platform === 'android' ? '425' : '420'}
|
|
||||||
data-src={`//cdn.rawgit.com/dabbott/react-native-web-player/gh-v${WEB_PLAYER_VERSION}/index.html${hash}`}
|
|
||||||
frameBorder="0"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = WebPlayer;
|
|
|
@ -342,13 +342,12 @@ function execute() {
|
||||||
if (
|
if (
|
||||||
!siteConfig.colors ||
|
!siteConfig.colors ||
|
||||||
!siteConfig.colors.primaryColor ||
|
!siteConfig.colors.primaryColor ||
|
||||||
!siteConfig.colors.secondaryColor ||
|
!siteConfig.colors.secondaryColor
|
||||||
!siteConfig.colors.prismColor
|
|
||||||
) {
|
) {
|
||||||
console.error(
|
console.error(
|
||||||
`${chalk.yellow(
|
`${chalk.yellow(
|
||||||
"Missing color configuration."
|
"Missing color configuration."
|
||||||
)} Make sure siteConfig.colors includes primaryColor, secondaryColor, and prismColor fields.`
|
)} Make sure siteConfig.colors includes primaryColor and secondaryColor fields.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,8 +80,9 @@ function execute(port) {
|
||||||
function reloadSiteConfig() {
|
function reloadSiteConfig() {
|
||||||
removeModuleAndChildrenFromCache(CWD + "/siteConfig.js");
|
removeModuleAndChildrenFromCache(CWD + "/siteConfig.js");
|
||||||
siteConfig = require(CWD + "/siteConfig.js");
|
siteConfig = require(CWD + "/siteConfig.js");
|
||||||
if (siteConfig.prism) {
|
|
||||||
siteConfig.prism(require("../core/Prism.js").Prism);
|
if (siteConfig.highlight && siteConfig.highlight.hljs) {
|
||||||
|
siteConfig.highlight.hljs(require("highlight.js"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -464,13 +465,12 @@ function execute(port) {
|
||||||
if (
|
if (
|
||||||
!siteConfig.colors ||
|
!siteConfig.colors ||
|
||||||
!siteConfig.colors.primaryColor ||
|
!siteConfig.colors.primaryColor ||
|
||||||
!siteConfig.colors.secondaryColor ||
|
!siteConfig.colors.secondaryColor
|
||||||
!siteConfig.colors.prismColor
|
|
||||||
) {
|
) {
|
||||||
console.error(
|
console.error(
|
||||||
`${chalk.yellow(
|
`${chalk.yellow(
|
||||||
"Missing color configuration."
|
"Missing color configuration."
|
||||||
)} Make sure siteConfig.colors includes primaryColor, secondaryColor, and prismColor fields.`
|
)} Make sure siteConfig.colors includes primaryColor and secondaryColor fields.`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -724,8 +724,8 @@ a code,
|
||||||
.mainContainer .wrapper a:focus code {
|
.mainContainer .wrapper a:focus code {
|
||||||
color: $primaryColor;
|
color: $primaryColor;
|
||||||
font-family: "SFMono-Regular",source-code-pro,Menlo,Monaco,Consolas,"Roboto Mono","Droid Sans Mono","Liberation Mono",Consolas,"Courier New",Courier,monospace;
|
font-family: "SFMono-Regular",source-code-pro,Menlo,Monaco,Consolas,"Roboto Mono","Droid Sans Mono","Liberation Mono",Consolas,"Courier New",Courier,monospace;
|
||||||
font-weight: 300;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a code {
|
a code {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
@ -733,121 +733,11 @@ a:hover code {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prism {
|
.hljs {
|
||||||
white-space: pre-wrap;
|
|
||||||
font-family: "SFMono-Regular",source-code-pro,Menlo,Monaco,Consolas,"Roboto Mono","Droid Sans Mono","Liberation Mono",Consolas,"Courier New",Courier,monospace;
|
font-family: "SFMono-Regular",source-code-pro,Menlo,Monaco,Consolas,"Roboto Mono","Droid Sans Mono","Liberation Mono",Consolas,"Courier New",Courier,monospace;
|
||||||
font-size: 13px;
|
|
||||||
line-height: 20px;
|
|
||||||
border-left: 4px solid $primaryColor;
|
border-left: 4px solid $primaryColor;
|
||||||
overflow-x: scroll;
|
font-size: 13px;
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
padding: 15px 10px;
|
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
background-color: $prismColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prism + .prism {
|
|
||||||
margin-top: 14px;
|
|
||||||
}
|
|
||||||
.prism table {
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
.prism table tbody tr {
|
|
||||||
background: none;
|
|
||||||
display: flex;
|
|
||||||
flex-flow: row nowrap;
|
|
||||||
}
|
|
||||||
.highlighter-rouge .prism table tbody tr td {
|
|
||||||
display: block;
|
|
||||||
flex: 1 1;
|
|
||||||
}
|
|
||||||
.highlighter-rouge .prism table tbody tr td.gutter {
|
|
||||||
border-right: 1px solid #005469;
|
|
||||||
color: #006883;
|
|
||||||
margin-right: 10px;
|
|
||||||
max-width: 40px;
|
|
||||||
padding-right: 10px;
|
|
||||||
}
|
|
||||||
.highlighter-rouge .prism table tbody tr td.gutter pre {
|
|
||||||
max-width: 20px;
|
|
||||||
}
|
|
||||||
/* Inline code */
|
|
||||||
:not(pre) > code[class*="language-"] {
|
|
||||||
padding: .1em;
|
|
||||||
border-radius: .3em;
|
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.comment,
|
|
||||||
.token.prolog,
|
|
||||||
.token.doctype,
|
|
||||||
.token.cdata {
|
|
||||||
color: slategray;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.punctuation {
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
|
|
||||||
.namespace {
|
|
||||||
opacity: .7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.property,
|
|
||||||
.token.tag,
|
|
||||||
.token.boolean,
|
|
||||||
.token.number,
|
|
||||||
.token.constant,
|
|
||||||
.token.symbol,
|
|
||||||
.token.deleted {
|
|
||||||
color: #905;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.selector,
|
|
||||||
.token.attr-name,
|
|
||||||
.token.string,
|
|
||||||
.token.char,
|
|
||||||
.token.builtin,
|
|
||||||
.token.inserted {
|
|
||||||
color: #690;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.operator,
|
|
||||||
.token.entity,
|
|
||||||
.token.url,
|
|
||||||
.language-css .token.string,
|
|
||||||
.style .token.string {
|
|
||||||
color: #a67f59;
|
|
||||||
background: hsla(0, 0%, 100%, .5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.atrule,
|
|
||||||
.token.attr-value,
|
|
||||||
.token.keyword {
|
|
||||||
color: #07a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.function {
|
|
||||||
color: #DD4A68;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.regex,
|
|
||||||
.token.important,
|
|
||||||
.token.variable {
|
|
||||||
color: #e90;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.important,
|
|
||||||
.token.bold {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.token.italic {
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.entity {
|
|
||||||
cursor: help;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** GitHub **/
|
/** GitHub **/
|
||||||
|
@ -2011,37 +1901,3 @@ footer .copyright {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Web player **/
|
|
||||||
.web-player > iframe {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.web-player > .prism {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.web-player.desktop > iframe {
|
|
||||||
display: block; }
|
|
||||||
|
|
||||||
.web-player.mobile > .prism {
|
|
||||||
display: block; }
|
|
||||||
|
|
||||||
.token.keyword {
|
|
||||||
color: #1990b8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.string,
|
|
||||||
.token.regex {
|
|
||||||
color: #2f9c0a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.boolean,
|
|
||||||
.token.number {
|
|
||||||
color: #c92c2c;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token.comment {
|
|
||||||
color: #7d8b99;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) 2017-present, Facebook, Inc.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* eslint-disable module-strict */
|
|
||||||
|
|
||||||
(function() {
|
|
||||||
"use strict";
|
|
||||||
// Not on browser
|
|
||||||
if (typeof document === "undefined") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", init);
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
var mobile = isMobile();
|
|
||||||
|
|
||||||
if (mobile) {
|
|
||||||
document
|
|
||||||
.querySelector(".nav-site-wrapper a[data-target]")
|
|
||||||
.addEventListener("click", toggleTarget);
|
|
||||||
}
|
|
||||||
|
|
||||||
var webPlayerList = document.querySelectorAll(".web-player");
|
|
||||||
// Either show interactive or static code block, depending on desktop or mobile
|
|
||||||
for (var i = 0; i < webPlayerList.length; ++i) {
|
|
||||||
webPlayerList[i].classList.add(mobile ? "mobile" : "desktop");
|
|
||||||
|
|
||||||
if (!mobile) {
|
|
||||||
// Determine location to look up required assets
|
|
||||||
var assetRoot = encodeURIComponent(
|
|
||||||
document.location.origin + "/react-native"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Set iframe src. Do this dynamically so the iframe never loads on mobile.
|
|
||||||
var iframe = webPlayerList[i].querySelector("iframe");
|
|
||||||
iframe.src =
|
|
||||||
iframe.getAttribute("data-src") + "&assetRoot=" + assetRoot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var snackPlayerList = document.querySelectorAll(".snack-player");
|
|
||||||
|
|
||||||
// Either show interactive or static code block, depending on desktop or mobile
|
|
||||||
for (var i = 0; i < snackPlayerList.length; ++i) {
|
|
||||||
var snackPlayer = snackPlayerList[i];
|
|
||||||
var snackDesktopPlayer = snackPlayer.querySelectorAll(
|
|
||||||
".desktop-friendly-snack"
|
|
||||||
)[0];
|
|
||||||
var plainCodeExample = snackPlayer.querySelectorAll(
|
|
||||||
".mobile-friendly-snack"
|
|
||||||
)[0];
|
|
||||||
|
|
||||||
if (mobile) {
|
|
||||||
snackDesktopPlayer.remove();
|
|
||||||
plainCodeExample.style.display = "block";
|
|
||||||
} else {
|
|
||||||
plainCodeExample.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Primitive mobile detection
|
|
||||||
function isMobile() {
|
|
||||||
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
|
|
||||||
navigator.userAgent
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})();
|
|
|
@ -14,10 +14,13 @@
|
||||||
"feed": "^1.1.0",
|
"feed": "^1.1.0",
|
||||||
"fs-extra": "^3.0.1",
|
"fs-extra": "^3.0.1",
|
||||||
"glob": "^7.1.2",
|
"glob": "^7.1.2",
|
||||||
|
"highlight.js": "^9.12.0",
|
||||||
"prettier": "^1.5.3",
|
"prettier": "^1.5.3",
|
||||||
"react": "^15.5.4",
|
"react": "^15.5.4",
|
||||||
"react-dom": "^15.5.4",
|
"react-dom": "^15.5.4",
|
||||||
"react-dom-factories": "^1.0.1",
|
"react-dom-factories": "^1.0.1",
|
||||||
|
"react-remarkable": "^1.1.3",
|
||||||
|
"remarkable": "^1.7.1",
|
||||||
"request": "^2.81.0",
|
"request": "^2.81.0",
|
||||||
"shelljs": "^0.7.8",
|
"shelljs": "^0.7.8",
|
||||||
"sitemap": "^1.13.0"
|
"sitemap": "^1.13.0"
|
||||||
|
|
|
@ -57,11 +57,14 @@ const siteConfig = {
|
||||||
},
|
},
|
||||||
colors: {
|
colors: {
|
||||||
primaryColor: "#2E8555",
|
primaryColor: "#2E8555",
|
||||||
secondaryColor: "#205C3B",
|
secondaryColor: "#205C3B"
|
||||||
prismColor: "rgba(46, 133, 85, 0.03)"
|
|
||||||
},
|
},
|
||||||
translationRecruitingLink: "https://crowdin.com/project/docusaurus",
|
translationRecruitingLink: "https://crowdin.com/project/docusaurus",
|
||||||
copyright: "Copyright © " + new Date().getFullYear() + " Facebook Inc."
|
copyright: "Copyright © " + new Date().getFullYear() + " Facebook Inc.",
|
||||||
|
highlight: {
|
||||||
|
theme: "solarized-dark"
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
module.exports = siteConfig;
|
module.exports = siteConfig;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue