diff --git a/docs/getting-started.md b/docs/getting-started.md index 41b42bdcec5..507ece0ed96 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -3,24 +3,19 @@ id: environment-setup title: Setting up the development environment --- +import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; + This page will help you install and build your first React Native app. If you are new to mobile development, the easiest way to get started is with Expo CLI. Expo is a set of tools built around React Native and, while it has many [features](https://expo.io/features), the most relevant feature for us right now is that it can get you writing a React Native app within minutes. You will only need a recent version of Node.js and a phone or emulator. If you'd like to try out React Native directly in your web browser before installing any tools, you can try out [Snack](https://snack.expo.io/). If you are already familiar with mobile development, you may want to use React Native CLI. It requires Xcode or Android Studio to get started. If you already have one of these tools installed, you should be able to get up and running within a few minutes. If they are not installed, you should expect to spend about an hour installing and configuring them. -
- -
+ + + - + Assuming that you have [Node 12 LTS](https://nodejs.org/en/download/) or greater installed, you can use npm to install the Expo CLI command line utility: @@ -82,28 +77,101 @@ Expo CLI configures your project to use the most recent React Native version tha If you're integrating React Native into an existing project, you'll want to skip Expo CLI and go directly to setting up the native build environment. Select "React Native CLI Quickstart" above for instructions on configuring a native build environment for React Native. - + + + + +

Follow these instructions if you need to build native code in your project. For example, if you are integrating React Native into an existing application, or if you "ejected" from Expo, you'll need this section.

The instructions are a bit different depending on your development operating system, and whether you want to start developing for iOS or Android. If you want to develop for both Android and iOS, that's fine - you can pick one to start with, since the setup is a bit different. -
- Development OS: - - - - - -
- -
- Target OS: - - - - -
+ + + + + + + + + + + + +

Installing dependencies

+ +You will need Node, Watchman, the React Native command line interface, and Xcode. + +While you can use any editor of your choice to develop your app, you will need to install Xcode in order to set up the necessary tooling to build your React Native app for iOS. + +
+ + + + + +> Android developers may be familiar with this concept. + + +
+ +
+ + + + + + + + + +

Unsupported

+ +

A Mac is required to build projects with native code for iOS. You can follow the Quick Start to learn how to build your app using Expo instead.

+ +
+ + + + + +> Android developers may be familiar with this concept. + + +
+ +
+ + + + + + + + + +

Unsupported

+ +

A Mac is required to build projects with native code for iOS. You can follow the Quick Start to learn how to build your app using Expo instead.

+ +
+ + + + + +> Android developers may be familiar with this concept. + + +
+ +
+ +
+ +
+
diff --git a/docs/introduction.md b/docs/introduction.md index e80dfc549c5..050d2cb7b54 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -4,6 +4,8 @@ title: Introduction description: This helpful guide lays out the prerequisites for learning React Native, using these docs, and setting up your environment. --- +import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; +

Welcome to the very start of your React Native journey! If you're looking for environment setup instructions, they've moved to their own section. Continue reading for an introduction to the documentation, Native Components, React, and more! @@ -54,18 +56,9 @@ With React, you can make components using either classes or functions. Originall [Hooks were introduced in React Native 0.58.](/blog/2019/03/12/releasing-react-native-059), and because Hooks are the future-facing way to write your React components, we wrote this introduction using function component examples. Where useful, we also cover class components under a toggle like so: -

-
    - - -
-
+ - + ```SnackPlayer name=Hello%20World%20Function%20Component import React from 'react'; @@ -86,7 +79,9 @@ const HelloWorldApp = () => { export default HelloWorldApp; ``` - + + + ```SnackPlayer name=Hello%20World%20Class%20Component import React, { Component } from 'react'; @@ -109,7 +104,9 @@ class HelloWorldApp extends Component { export default HelloWorldApp; ``` - + + + You can find more examples of class components in [previous versions of this documentation](/versions). @@ -117,28 +114,27 @@ You can find more examples of class components in [previous versions of this doc People from many different development backgrounds are learning React Native. You may have experience with a range of technologies, from web to Android to iOS and more. We try to write for developers from all backgrounds. Sometimes we provide explanations specific to one platform or another like so: -
- Developer Notes - - - - - -
+ - + > Web developers may be familiar with this concept. - + + + > Android developers may be familiar with this concept. - + + + > iOS developers may be familiar with this concept. - + + + ## Formatting diff --git a/website/core/RemarkPlugins.js b/website/core/RemarkPlugins.js new file mode 100644 index 00000000000..ff292a79e79 --- /dev/null +++ b/website/core/RemarkPlugins.js @@ -0,0 +1,128 @@ +'use strict'; + +const hljs = require('highlight.js'); +const visit = require('unist-util-visit-parents'); +const u = require('unist-builder'); + +function 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]; + } + } + + if (!params.platform) { + params.platform = 'web'; + } + + return params; +} + +function htmlForCodeBlock(code) { + return ( + '
' +
+    hljs.highlight('javascript', code).value +
+    '
' + ); +} + +/** + * 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 Hello World!; + * } + * } + * ``` + */ +function SnackPlayer() { + return tree => + new Promise(async (resolve, reject) => { + const nodesToProcess = []; + // Parse all CodeBlocks + visit(tree, 'code', (node, parent) => { + //Add SnackPlayer CodeBlocks to processing queue + if (node.lang == 'SnackPlayer') { + nodesToProcess.push( + new Promise(async (resolve, reject) => { + try { + let params = parseParams(node.meta); + + // Gather necessary Params + const name = params.name + ? decodeURIComponent(params.name) + : 'Example'; + const description = params.description + ? decodeURIComponent(params.description) + : 'Example usage'; + const sampleCode = node.value; + const encodedSampleCode = encodeURIComponent(sampleCode); + const platform = params.platform ? params.platform : 'ios'; + const supportedPlatforms = params.supportedPlatforms + ? params.supportedPlatforms + : 'ios,android,web'; + + // Generate Node for SnackPlayer + const snackPlayerDiv = u('html', { + value: `
+ +
+
+
+
+
`, + }); + + // Replace code block with SnackPlayer Node + const index = parent[0].children.indexOf(node); + parent[0].children.splice(index, 1, snackPlayerDiv); + } catch (e) { + return reject(e); + } + resolve(); + }) + ); + } + }); + + // Wait for all promises to be resolved + Promise.all(nodesToProcess) + .then(resolve()) + .catch(reject()); + }); +} + +function ReactNativeWebPlayer() { + return function transformer(tree, file) {}; +} + +module.exports = {ReactNativeWebPlayer, SnackPlayer}; diff --git a/website/core/RemarkablePlugins.js b/website/core/RemarkablePlugins.js deleted file mode 100644 index ee73e59caa7..00000000000 --- a/website/core/RemarkablePlugins.js +++ /dev/null @@ -1,144 +0,0 @@ -'use strict'; - -const hljs = require('highlight.js'); - -// Remove leading "SnackPlayer", "ReactNativeWebPlayer" -function cleanParams(params) { - if (params && params.split(' ').length > 0) { - return params.split(' ')[1]; - } - - return null; -} - -function 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]; - } - } - - if (!params.platform) { - params.platform = 'web'; - } - - return params; -} - -function htmlForCodeBlock(code) { - return ( - '
' +
-    hljs.highlight('javascript', code).value +
-    '
' - ); -} - -/** - * 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 Hello World!; - * } - * } - * ``` - */ -function SnackPlayer(md) { - md.renderer.rules.fence_custom.SnackPlayer = function(tokens, idx) { - let params = parseParams(cleanParams(tokens[idx].params)); - - const name = params.name ? decodeURIComponent(params.name) : 'Example'; - const description = params.description - ? decodeURIComponent(params.description) - : 'Example usage'; - const sampleCode = tokens[idx].content; - const encodedSampleCode = encodeURIComponent(sampleCode); - const platform = params.platform ? params.platform : 'ios'; - const supportedPlatforms = params.supportedPlatforms - ? params.supportedPlatforms - : 'ios,android,web'; - - return ( - '
' + - '' + - '
' + - `
` + - '
' + - '
' + - '
' - ); - }; -} - -/** - * 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 { Text } from 'react-native'; - * - * const App = () => Hello World!; - * export default App; - * ``` - */ -function ReactNativeWebPlayer(md) { - md.renderer.rules.fence_custom.ReactNativeWebPlayer = function(tokens, idx) { - const WEB_PLAYER_VERSION = '2.0.0-alpha.8'; - - let sampleCode = tokens[idx].content; - let hash = `#code=${encodeURIComponent(sampleCode)}`; - - let paramsString = cleanParams(tokens[idx].params); - if (paramsString) { - hash += `&${paramsString}`; - } - let params = parseParams(paramsString); - - return ( - '
' + - htmlForCodeBlock(sampleCode) + - `` + - `
` + - '\n\n' - ); - }; -} - -module.exports = {ReactNativeWebPlayer, SnackPlayer}; diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index d431bbc43bb..64928259526 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -1,3 +1,5 @@ +const RemarkPlugins = require('./core/RemarkPlugins'); + module.exports = { title: 'React Native', tagline: 'A framework for building native apps using React', @@ -10,9 +12,9 @@ module.exports = { 'https://platform.twitter.com/widgets.js', 'https://buttons.github.io/buttons.js', '/js/codeblocks.js', - '/js/tabs.js', + // '/js/tabs.js', '/js/docs-rating.js', - '/js/announcement.js', + // '/js/announcement.js', ], favicon: 'img/favicon.ico', customFields: { @@ -335,6 +337,10 @@ module.exports = { '@docusaurus/preset-classic', { docs: { + remarkPlugins: [ + RemarkPlugins.SnackPlayer, + RemarkPlugins.ReactNativeWebPlayer, + ], homePageId: 'getting-started', showLastUpdateAuthor: true, showLastUpdateTime: true, @@ -354,6 +360,9 @@ module.exports = { ], plugins: [], themeConfig: { + prism: { + additionalLanguages: ['objectivec', 'swift', 'java'], + }, announcementBar: { id: 'blm', backgroundColor: '#242526', diff --git a/website/package.json b/website/package.json index 9d73339db7c..5e7befe6294 100644 --- a/website/package.json +++ b/website/package.json @@ -15,7 +15,7 @@ "main": "n/a", "scripts": { "start": "docusaurus start", - "build": "docusaurus build", + "build": "node --max_old_space_size=4096 node_modules/@docusaurus/core/bin/docusaurus build", "prepublish-gh-pages": "yarn sync-community-repos", "publish-gh-pages": "docusaurus-publish", "version": "docusaurus-version", @@ -45,12 +45,13 @@ }, "dependencies": { "highlight.js": "^9.15.10", - "remarkable": "^2.0.0", "@docusaurus/core": "2.0.0-alpha.64", "@docusaurus/preset-classic": "2.0.0-alpha.64", "clsx": "^1.1.1", "react": "^16.10.2", - "react-dom": "^16.10.2" + "react-dom": "^16.10.2", + "unist-builder": "^2.0.3", + "unist-util-visit-parents": "^3.1.0" }, "devDependencies": { "@motiz88/react-native-docgen": "0.0.3", diff --git a/website/yarn.lock b/website/yarn.lock index 8b110e3f11b..f32cf3f303e 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -2261,7 +2261,7 @@ are-we-there-yet@~1.1.2: delegates "^1.0.0" readable-stream "^2.0.6" -argparse@^1.0.10, argparse@^1.0.7: +argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== @@ -2385,13 +2385,6 @@ atob@^2.1.1: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -autolinker@^3.11.0: - version "3.11.0" - resolved "https://registry.yarnpkg.com/autolinker/-/autolinker-3.11.0.tgz#209c4632550eed32285058eaac51f1382dae023a" - integrity sha512-VMTEjE3jeBK5MinTZiuVE07O4wMVmXhpzmc5sCc8cap6exsVzjmQJgtH8NqHsFru58ujUieBA9Dmwiz+E5KWEA== - dependencies: - tslib "^1.9.3" - autoprefixer@^9.6.1: version "9.8.6" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.6.tgz#3b73594ca1bf9266320c5acf1588d74dea74210f" @@ -9687,14 +9680,6 @@ remark-squeeze-paragraphs@4.0.0: dependencies: mdast-squeeze-paragraphs "^4.0.0" -remarkable@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/remarkable/-/remarkable-2.0.1.tgz#280ae6627384dfb13d98ee3995627ca550a12f31" - integrity sha512-YJyMcOH5lrR+kZdmB0aJJ4+93bEojRZ1HGDn9Eagu6ibg7aVZhc3OWbbShRid+Q5eAfsEqWxpe+g5W5nYNfNiA== - dependencies: - argparse "^1.0.10" - autolinker "^3.11.0" - remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" @@ -11028,7 +11013,7 @@ tslib@^1.10.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== -tslib@^1.9.0, tslib@^1.9.3: +tslib@^1.9.0: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== @@ -11243,7 +11228,7 @@ unique-string@^2.0.0: dependencies: crypto-random-string "^2.0.0" -unist-builder@2.0.3, unist-builder@^2.0.0: +unist-builder@2.0.3, unist-builder@^2.0.0, unist-builder@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-2.0.3.tgz#77648711b5d86af0942f334397a33c5e91516436" integrity sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw== @@ -11330,6 +11315,14 @@ unist-util-visit-parents@^3.0.0: "@types/unist" "^2.0.3" unist-util-is "^4.0.0" +unist-util-visit-parents@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.0.tgz#4dd262fb9dcfe44f297d53e882fc6ff3421173d5" + integrity sha512-0g4wbluTF93npyPrp/ymd3tCDTMnP0yo2akFD2FIBAYXq/Sga3lwaU1D8OYKbtpioaI6CkDcQ6fsMnmtzt7htw== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + unist-util-visit@2.0.3, unist-util-visit@^2.0.1, unist-util-visit@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c"