Initial version of the website and docs.

This commit is contained in:
Christopher Chedeau 2015-02-11 20:26:43 -08:00
parent dd78b09741
commit 9231d4f8f0
27 changed files with 3342 additions and 0 deletions

78
docs/GettingStarted.md Normal file
View File

@ -0,0 +1,78 @@
---
id: getting-started
title: Getting Started
layout: docs
category: Quick Start
permalink: docs/getting-started.html
---
Our first React Native implementation is `ReactKit`, targeting iOS. We are also
working on an Android implementation which we will release later. `ReactKit`
apps are built using the [React JS](https://github.com/facebook/react) framework, and render directly to
native UIKit elements using a fully asynchronous architecture. There is no
browser and no HTML. We have picked what we think is the best set of features
from these and other technologies to build what we hope to become the best
product development framework available, with an emphasis on iteration speed,
developer delight, continuity of technology, and absolutely beautiful and fast
products with no compromises in quality or capability.
## Requirements
1. OS X - This repo only contains the iOS implementation right now, and Xcode only runs on Mac.
2. New to Xcode? [Download it](https://developer.apple.com/xcode/downloads/) from the Mac App Store.
3. [Homebrew](http://brew.sh/) is the recommended way to install node, watchman, and flow.
4. New to node or npm? `brew install node`
5. We recommend installing [watchman](https://facebook.github.io/watchman/docs/install.html), otherwise you might hit a node file watching bug. `brew install watchman`
6. If you want to use [flow](http://www.flowtype.org), `brew install flow`
## Quick start
Get up and running with our Movies sample app:
1. Once you have the repo cloned and met all the requirements above, start the
packager that will transform your JS code on-the-fly:
```
npm install
npm start
```
2. Open the `Examples/Movies/Movies.xcodeproj` project in Xcode.
3. Make sure the target is set to `Movies` and that you have an iOS simulator
selected to run the app.
4. Build and run the project with the Xcode run button.
You should now see the Movies app running on your iOS simulator.
Congratulations! You've just successfully run your first React Native app.
Now try editing a JavaScript file and viewing your changes. Let's change the
movie search placeholder text:
1. Open the `Examples/Movies/SearchScreen.js` file in your favorite JavaScript
editor.
2. Look for the current search placeholder text and change it to "Search for an
awesome movie...".
3. Hit cmd+R ([twice](http://openradar.appspot.com/19613391)) in your iOS simulator to reload the app and see your change.
If you don't immediately see your changes, try restarting your app within Xcode.
Feel free to browse the Movies sample files and customize various properties to
get familiar with the codebase and React Native.
Also check out the UI Component Explorer for more sample code:
`Examples/UIExplorer/UIExplorer.xcodeproj`. **Make sure to close the Movies
project first - Xcode will break if you have two projects open that reference
the same library.**
## Troubleshooting
+ Xcode will break if you have two examples open at the same time.
+ If `npm start` fails with log spew like:
```
2015-02-02 10:56 node[24294] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-21)
```
then you've hit the node file watching bug - `brew install watchman` should fix the issue.
+ Jest testing does not yet work on node versions after 0.10.x.
+ You can verify the packager is working by loading the [bundle](http://localhost:8081/Examples/Movies/MoviesApp.includeRequire.runModule.bundle) in your browser and
inspecting the contents.
Please report any other issues you encounter so we can fix them ASAP.

36
website/README.md Normal file
View File

@ -0,0 +1,36 @@
# Run the server
The first time, get all the dependencies loaded via
```
npm install
```
Then, run the server via
```
npm start
Open http://localhost:8080/react-native/index.html
```
Anytime you change the contents, just refresh the page and it's going to be updated
# Publish the website
First setup your environment by having two folders, one `react-native` and one `react-native-gh-pages`. The publish script expects those exact names.
```
cd ../../
git clone git@github.com:facebook/react-native.git react-native-gh-pages
cd react-native-gh-pages
git checkout origin/gh-pages
git checkout -b gh-pages
git push --set-upstream origin gh-pages
cd ../react-native/website
```
Then, after you've done changes, just run the command and it'll automatically build the static version of the site and publish it to gh-pages.
```
./publish.sh
```

View File

@ -0,0 +1,96 @@
/**
* @providesModule DocsSidebar
* @jsx React.DOM
*/
var React = require('React');
var Metadata = require('Metadata');
var DocsSidebar = React.createClass({
getCategories: function() {
var metadatas = Metadata.files.filter(function(metadata) {
return metadata.layout === 'docs';
});
// Build a hashmap of article_id -> metadata
var articles = {};
for (var i = 0; i < metadatas.length; ++i) {
var metadata = metadatas[i];
articles[metadata.id] = metadata;
}
// Build a hashmap of article_id -> previous_id
var previous = {};
for (var i = 0; i < metadatas.length; ++i) {
var metadata = metadatas[i];
if (metadata.next) {
if (!articles[metadata.next]) {
throw '`next: ' + metadata.next + '` in ' + metadata.id + ' doesn\'t exist';
}
previous[articles[metadata.next].id] = metadata.id;
}
}
// Find the first element which doesn't have any previous
var first = null;
for (var i = 0; i < metadatas.length; ++i) {
var metadata = metadatas[i];
if (!previous[metadata.id]) {
first = metadata;
break;
}
}
var categories = [];
var currentCategory = null;
var metadata = first;
var i = 0;
while (metadata && i++ < 1000) {
if (!currentCategory || metadata.category !== currentCategory.name) {
currentCategory && categories.push(currentCategory);
currentCategory = {
name: metadata.category,
links: []
};
}
currentCategory.links.push(metadata);
metadata = articles[metadata.next];
}
categories.push(currentCategory);
return categories;
},
getLink: function(metadata) {
if (metadata.permalink.match(/^https?:/)) {
return metadata.permalink;
}
return '/react-native/' + metadata.permalink + '#content';
},
render: function() {
return <div className="nav-docs">
{this.getCategories().map((category) =>
<div className="nav-docs-section" key={category.name}>
<h3>{category.name}</h3>
<ul>
{category.links.map((metadata) =>
<li key={metadata.id}>
<a
target={metadata.permalink.match(/^https?:/) && '_blank'}
style={{marginLeft: metadata.indent ? 20 : 0}}
className={metadata.id === this.props.metadata.id ? 'active' : ''}
href={this.getLink(metadata)}>
{metadata.title}
</a>
</li>
)}
</ul>
</div>
)}
</div>;
}
});
module.exports = DocsSidebar;

17
website/core/H2.js Normal file
View File

@ -0,0 +1,17 @@
/**
* @providesModule H2
* @jsx React.DOM
*/
var React = require('React');
var Header = require('Header');
var H2 = React.createClass({
render: function() {
return this.transferPropsTo(
<Header level={2}>{this.props.children}</Header>
);
}
});
module.exports = H2;

53
website/core/Header.js Normal file
View File

@ -0,0 +1,53 @@
/**
* @providesModule Header
* @jsx React.DOM
*/
var React = require('React');
var Header = React.createClass({
slug: function(string) {
// var accents = 'àáäâèéëêìíïîòóöôùúüûñç';
var accents = '\u00e0\u00e1\u00e4\u00e2\u00e8' +
'\u00e9\u00eb\u00ea\u00ec\u00ed\u00ef' +
'\u00ee\u00f2\u00f3\u00f6\u00f4\u00f9' +
'\u00fa\u00fc\u00fb\u00f1\u00e7';
var without = 'aaaaeeeeiiiioooouuuunc';
return string
.toString()
// Handle uppercase characters
.toLowerCase()
// Handle accentuated characters
.replace(
new RegExp('[' + accents + ']', 'g'),
function (c) { return without.charAt(accents.indexOf(c)); })
// Dash special characters
.replace(/[^a-z0-9]/g, '-')
// Compress multiple dash
.replace(/-+/g, '-')
// Trim dashes
.replace(/^-|-$/g, '');
},
render: function() {
var slug = this.slug(this.props.toSlug || this.props.children);
var H = React.DOM['h' + this.props.level];
return this.transferPropsTo(
<H>
<a className="anchor" name={slug}></a>
{this.props.children}
{' '}<a className="hash-link" href={'#' + slug}>#</a>
</H>
);
}
});
module.exports = Header;

View File

@ -0,0 +1,34 @@
/**
* @providesModule HeaderLinks
* @jsx React.DOM
*/
var React = require('React');
var HeaderLinks = React.createClass({
links: [
{section: 'docs', href: '/react-native/docs/getting-started.html#content', text: 'docs'},
{section: 'support', href: '/react-native/support.html', text: 'support'},
{section: 'github', href: 'http://github.com/facebook/react-native', text: 'github'},
],
render: function() {
return (
<ul className="nav-site">
{this.links.map(function(link) {
return (
<li key={link.section}>
<a
href={link.href}
className={link.section === this.props.section ? 'active' : ''}>
{link.text}
</a>
</li>
);
}, this)}
</ul>
);
}
});
module.exports = HeaderLinks;

1092
website/core/Marked.js Normal file

File diff suppressed because it is too large Load Diff

357
website/core/Prism.js Normal file
View File

@ -0,0 +1,357 @@
/**
* Prism: Lightweight, robust, elegant syntax highlighting
* MIT license http://www.opensource.org/licenses/mit-license.php/
* @author Lea Verou http://lea.verou.me
*
* @providesModule Prism
* @jsx React.DOM
*/
var React = require('React');
var _ = {
util: {
type: function (o) {
return Object.prototype.toString.call(o).match(/\[object (\w+)\]/)[1];
},
// Deep clone a language definition (e.g. to extend it)
clone: function (o) {
var type = _.util.type(o);
switch (type) {
case 'Object':
var clone = {};
for (var key in o) {
if (o.hasOwnProperty(key)) {
clone[key] = _.util.clone(o[key]);
}
}
return clone;
case 'Array':
return o.slice();
}
return o;
}
},
languages: {
extend: function (id, redef) {
var lang = _.util.clone(_.languages[id]);
for (var key in redef) {
lang[key] = redef[key];
}
return lang;
},
// Insert a token before another token in a language literal
insertBefore: function (inside, before, insert, root) {
root = root || _.languages;
var grammar = root[inside];
var ret = {};
for (var token in grammar) {
if (grammar.hasOwnProperty(token)) {
if (token == before) {
for (var newToken in insert) {
if (insert.hasOwnProperty(newToken)) {
ret[newToken] = insert[newToken];
}
}
}
ret[token] = grammar[token];
}
}
return root[inside] = ret;
},
// Traverse a language definition with Depth First Search
DFS: function(o, callback) {
for (var i in o) {
callback.call(o, i, o[i]);
if (_.util.type(o) === 'Object') {
_.languages.DFS(o[i], callback);
}
}
}
},
tokenize: function(text, grammar) {
var Token = _.Token;
var strarr = [text];
var rest = grammar.rest;
if (rest) {
for (var token in rest) {
grammar[token] = rest[token];
}
delete grammar.rest;
}
tokenloop: for (var token in grammar) {
if(!grammar.hasOwnProperty(token) || !grammar[token]) {
continue;
}
var pattern = grammar[token],
inside = pattern.inside,
lookbehind = !!pattern.lookbehind,
lookbehindLength = 0;
pattern = pattern.pattern || pattern;
for (var i=0; i<strarr.length; i++) { // Dont cache length as it changes during the loop
var str = strarr[i];
if (strarr.length > text.length) {
// Something went terribly wrong, ABORT, ABORT!
break tokenloop;
}
if (str instanceof Token) {
continue;
}
pattern.lastIndex = 0;
var match = pattern.exec(str);
if (match) {
if(lookbehind) {
lookbehindLength = match[1].length;
}
var from = match.index - 1 + lookbehindLength,
match = match[0].slice(lookbehindLength),
len = match.length,
to = from + len,
before = str.slice(0, from + 1),
after = str.slice(to + 1);
var args = [i, 1];
if (before) {
args.push(before);
}
var wrapped = new Token(token, inside? _.tokenize(match, inside) : match);
args.push(wrapped);
if (after) {
args.push(after);
}
Array.prototype.splice.apply(strarr, args);
}
}
}
return strarr;
},
hooks: {
all: {},
add: function (name, callback) {
var hooks = _.hooks.all;
hooks[name] = hooks[name] || [];
hooks[name].push(callback);
},
run: function (name, env) {
var callbacks = _.hooks.all[name];
if (!callbacks || !callbacks.length) {
return;
}
for (var i=0, callback; callback = callbacks[i++];) {
callback(env);
}
}
}
};
var Token = _.Token = function(type, content) {
this.type = type;
this.content = content;
};
Token.reactify = function(o, key) {
if (typeof o == 'string') {
return o;
}
if (Array.isArray(o)) {
return o.map(function(element, i) {
return Token.reactify(element, i);
});
}
var attributes = {
className: 'token ' + o.type,
key: key
};
if (o.type == 'comment') {
attributes.spellCheck = true;
}
return React.DOM.span(attributes, Token.reactify(o.content));
};
_.languages.markup = {
'comment': /&lt;!--[\w\W]*?-->/g,
'prolog': /&lt;\?.+?\?>/,
'doctype': /&lt;!DOCTYPE.+?>/,
'cdata': /&lt;!\[CDATA\[[\w\W]*?]]>/i,
'tag': {
pattern: /&lt;\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|[^\s'">=]+))?\s*)*\/?>/gi,
inside: {
'tag': {
pattern: /^&lt;\/?[\w:-]+/i,
inside: {
'punctuation': /^&lt;\/?/,
'namespace': /^[\w-]+?:/
}
},
'attr-value': {
pattern: /=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi,
inside: {
'punctuation': /=|>|"/g
}
},
'punctuation': /\/?>/g,
'attr-name': {
pattern: /[\w:-]+/g,
inside: {
'namespace': /^[\w-]+?:/
}
}
}
},
'entity': /&amp;#?[\da-z]{1,8};/gi
};
_.languages.css = {
'comment': /\/\*[\w\W]*?\*\//g,
'atrule': {
pattern: /@[\w-]+?.*?(;|(?=\s*{))/gi,
inside: {
'punctuation': /[;:]/g
}
},
'url': /url\((["']?).*?\1\)/gi,
'selector': /[^\{\}\s][^\{\};]*(?=\s*\{)/g,
'property': /(\b|\B)[\w-]+(?=\s*:)/ig,
'string': /("|')(\\?.)*?\1/g,
'important': /\B!important\b/gi,
'ignore': /&(lt|gt|amp);/gi,
'punctuation': /[\{\};:]/g
};
_.languages.insertBefore('markup', 'tag', {
'style': {
pattern: /(&lt;|<)style[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/style(>|&gt;)/ig,
inside: {
'tag': {
pattern: /(&lt;|<)style[\w\W]*?(>|&gt;)|(&lt;|<)\/style(>|&gt;)/ig,
inside: _.languages.markup.tag.inside
},
rest: _.languages.css
}
}
});
_.languages.clike = {
'comment': {
pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g,
lookbehind: true
},
'string': /("|')(\\?.)*?\1/g,
'class-name': {
pattern: /((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/ig,
lookbehind: true,
inside: {
punctuation: /(\.|\\)/
}
},
'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g,
'boolean': /\b(true|false)\b/g,
'function': {
pattern: /[a-z0-9_]+\(/ig,
inside: {
punctuation: /\(/
}
},
'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,
'operator': /[-+]{1,2}|!|&lt;=?|>=?|={1,3}|(&amp;){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,
'ignore': /&(lt|gt|amp);/gi,
'punctuation': /[{}[\];(),.:]/g
};
_.languages.javascript = _.languages.extend('clike', {
'keyword': /\b(var|let|if|else|while|do|for|return|in|instanceof|function|get|set|new|with|typeof|try|throw|catch|finally|null|break|continue|this)\b/g,
'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g
});
_.languages.insertBefore('javascript', 'keyword', {
'regex': {
pattern: /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,
lookbehind: true
}
});
_.languages.insertBefore('markup', 'tag', {
'script': {
pattern: /(&lt;|<)script[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/script(>|&gt;)/ig,
inside: {
'tag': {
pattern: /(&lt;|<)script[\w\W]*?(>|&gt;)|(&lt;|<)\/script(>|&gt;)/ig,
inside: _.languages.markup.tag.inside
},
rest: _.languages.javascript
}
}
});
var Prism = React.createClass({
statics: {
_: _
},
getDefaultProps: function() {
return {
language: 'javascript'
};
},
render: function() {
var grammar = _.languages[this.props.language];
return (
<div className={'prism language-' + this.props.language}>
{Token.reactify(_.tokenize(this.props.children, grammar))}
</div>
);
}
});
module.exports = Prism;

69
website/core/Site.js Normal file
View File

@ -0,0 +1,69 @@
/**
* @providesModule Site
* @jsx React.DOM
*/
var React = require('React');
var HeaderLinks = require('HeaderLinks');
var Site = React.createClass({
render: function() {
return (
<html>
<head>
<meta charSet="utf-8" />
<meta httpEquiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<title>React Native | Build Native Apps Using React</title>
<meta name="viewport" content="width=device-width" />
<meta property="og:title" content="React Native | Build Native Apps Using React" />
<meta property="og:type" content="website" />
<meta property="og:url" content="http://facebook.github.io/react-native/index.html" />
<meta property="og:image" content="http://facebook.github.io/react-native/img/opengraph.png" />
<meta property="og:description" content="Build Native Apps Using React" />
<link rel="shortcut icon" href="/react-native/img/favicon.png" />
<link rel="stylesheet" href="/react-native/css/react-native.css" />
<script type="text/javascript" src="//use.typekit.net/vqa1hcx.js"></script>
<script type="text/javascript">{'try{Typekit.load();}catch(e){}'}</script>
</head>
<body>
<div className="container">
<div className="nav-main">
<div className="wrap">
<a className="nav-home" href="/react-native/">
<img src="/react-native/img/logo.png" />
React Native
</a>
<HeaderLinks section={this.props.section} />
</div>
</div>
{this.props.children}
<footer className="wrap">
<div className="right">© 2014 Facebook Inc.</div>
</footer>
</div>
<div id="fb-root" />
<script dangerouslySetInnerHTML={{__html: `
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-387204-10', 'facebook.github.io');
ga('send', 'pageview');
!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)
){js=d.createElement(s);js.id=id;js.src="https://platform.twitter.com/widgets.js";
fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");
`}} />
</body>
</html>
);
}
});
module.exports = Site;

16
website/core/center.js Normal file
View File

@ -0,0 +1,16 @@
/**
* @providesModule center
* @jsx React.DOM
*/
var React = require('React');
var center = React.createClass({
render: function() {
return this.transferPropsTo(
<div style={{textAlign: 'center'}}>{this.props.children}</div>
);
}
});
module.exports = center;

15
website/core/metadata.js Normal file
View File

@ -0,0 +1,15 @@
/**
* @generated
* @providesModule Metadata
*/
module.exports = {
"files": [
{
"id": "getting-started",
"title": "Getting Started",
"layout": "docs",
"category": "Quick Start",
"permalink": "docs/getting-started.html"
}
]
};

22
website/core/unindent.js Normal file
View File

@ -0,0 +1,22 @@
/**
* @providesModule unindent
*/
// Remove the indentation introduced by JSX
function unindent(code) {
var lines = code.split('\n');
if (lines[0] === '') {
lines.shift();
}
if (lines.length <= 1) {
return code;
}
var indent = lines[0].match(/^\s*/)[0];
for (var i = 0; i < lines.length; ++i) {
lines[i] = lines[i].replace(new RegExp('^' + indent), '');
}
return lines.join('\n');
}
module.exports = unindent;

View File

@ -0,0 +1,33 @@
/**
* @providesModule DocsLayout
* @jsx React.DOM
*/
var React = require('React');
var Site = require('Site');
var Marked = require('Marked');
var DocsSidebar = require('DocsSidebar');
var DocsLayout = React.createClass({
render: function() {
var metadata = this.props.metadata;
var content = this.props.children;
return (
<Site section="docs">
<section className="content wrap documentationContent">
<DocsSidebar metadata={metadata} />
<div className="inner-content">
<a id="content" />
<h1>{metadata.title}</h1>
<Marked>{content}</Marked>
<div className="docs-prevnext">
{metadata.previous && <a className="docs-prev" href={metadata.previous + '.html#content'}>&larr; Prev</a>}
{metadata.next && <a className="docs-next" href={metadata.next + '.html#content'}>Next &rarr;</a>}
</div>
</div>
</section>
</Site>
);
}
});
module.exports = DocsLayout;

View File

@ -0,0 +1,26 @@
/**
* @providesModule PageLayout
* @jsx React.DOM
*/
var React = require('React');
var Site = require('Site');
var Marked = require('Marked');
var support = React.createClass({
render: function() {
var metadata = this.props.metadata;
var content = this.props.children;
return (
<Site section={metadata.section}>
<section className="content wrap documentationContent nosidebar">
<div className="inner-content">
<Marked>{content}</Marked>
</div>
</section>
</Site>
);
}
});
module.exports = support;

15
website/package.json Normal file
View File

@ -0,0 +1,15 @@
{
"scripts": {
"start": "node server/server.js"
},
"dependencies": {
"React": "~0.12.0",
"optimist": "0.6.0",
"react-page-middleware": "git://github.com/facebook/react-page-middleware.git",
"connect": "2.8.3",
"glob": "*",
"mkdirp": "*",
"request": "*",
"fs.extra": "*"
}
}

22
website/publish.sh Executable file
View File

@ -0,0 +1,22 @@
#!/bin/bash
set -e
# Start in website/ even if run from root directory
cd "$(dirname "$0")"
cd ../../react-native-gh-pages
git checkout -- .
git clean -dfx
git fetch
git rebase
rm -Rf *
cd ../react-native/website
node server/generate.js
cp -R build/react-native/* ../../react-native-gh-pages/
rm -Rf build/
cd ../../react-native-gh-pages
git add --all
git commit -m "update website"
git push
cd ../react-native/website

117
website/server/convert.js Normal file
View File

@ -0,0 +1,117 @@
var fs = require('fs')
var glob = require('glob');
var mkdirp = require('mkdirp');
var optimist = require('optimist');
var path = require('path');
var argv = optimist.argv;
function splitHeader(content) {
var lines = content.split('\n');
for (var i = 1; i < lines.length - 1; ++i) {
if (lines[i] === '---') {
break;
}
}
return {
header: lines.slice(1, i + 1).join('\n'),
content: lines.slice(i + 1).join('\n')
};
}
function backtickify(str) {
var escaped = '`' + str.replace(/\\/g, '\\\\').replace(/`/g, '\\`') + '`';
// Replace require( with require\( so node-haste doesn't replace example
// require calls in the docs
return escaped.replace(/require\(/g, 'require\\(');
}
function execute() {
var MD_DIR = '../docs/';
glob('src/react-native/docs/*.*', function(er, files) {
files.forEach(function(file) {
try {
fs.unlinkSync(file);
} catch(e) {
/* seriously, unlink throws when the file doesn't exist :( */
}
});
});
var metadatas = {
files: [],
};
glob(MD_DIR + '**/*.*', function (er, files) {
files.forEach(function(file) {
var extension = path.extname(file);
if (extension === '.md' || extension === '.markdown') {
var content = fs.readFileSync(file, {encoding: 'utf8'});
var metadata = {};
// Extract markdown metadata header
var both = splitHeader(content);
var lines = both.header.split('\n');
for (var i = 0; i < lines.length - 1; ++i) {
var keyvalue = lines[i].split(':');
var key = keyvalue[0].trim();
var value = keyvalue.slice(1).join(':').trim();
// Handle the case where you have "Community #10"
try { value = JSON.parse(value); } catch(e) { }
metadata[key] = value;
}
metadatas.files.push(metadata);
if (metadata.permalink.match(/^https?:/)) {
return;
}
// Create a dummy .js version that just calls the associated layout
var layout = metadata.layout[0].toUpperCase() + metadata.layout.substr(1) + 'Layout';
var content = (
'/**\n' +
' * @generated\n' +
' * @jsx React.DOM\n' +
' */\n' +
'var React = require("React");\n' +
'var layout = require("' + layout + '");\n' +
'var content = ' + backtickify(both.content) + '\n' +
'var Post = React.createClass({\n' +
' render: function() {\n' +
' return layout({metadata: ' + JSON.stringify(metadata) + '}, content);\n' +
' }\n' +
'});\n' +
// TODO: Use React statics after upgrading React
'Post.content = content;\n' +
'module.exports = Post;\n'
);
var targetFile = 'src/react-native/' + metadata.permalink.replace(/\.html$/, '.js');
mkdirp.sync(targetFile.replace(new RegExp('/[^/]*$'), ''));
fs.writeFileSync(targetFile, content);
}
if (extension === '.json') {
var content = fs.readFileSync(file, {encoding: 'utf8'});
metadatas[path.basename(file, '.json')] = JSON.parse(content);
}
});
fs.writeFileSync(
'core/metadata.js',
'/**\n' +
' * @generated\n' +
' * @providesModule Metadata\n' +
' */\n' +
'module.exports = ' + JSON.stringify(metadatas, null, 2) + ';'
);
});
}
if (argv.convert) {
console.log('convert!')
execute();
}
module.exports = execute;

View File

@ -0,0 +1,61 @@
var request = require('request');
var glob = require('glob');
var fs = require('fs.extra');
var mkdirp = require('mkdirp');
var server = require('./server.js');
// Sadly, our setup fatals when doing multiple concurrent requests
// I don't have the time to dig into why, it's easier to just serialize
// requests.
var queue = (function() {
var is_executing = false;
var queue = [];
function push(fn) {
queue.push(fn);
execute();
}
function execute() {
if (is_executing) {
return;
}
if (queue.length === 0) {
return;
}
var fn = queue.shift();
is_executing = true;
fn(function() {
is_executing = false;
execute()
});
}
return {push: push};
})();
glob('src/**/*.*', function(er, files) {
files.forEach(function(file) {
var targetFile = file.replace(/^src/, 'build');
if (file.match(/\.js$/)) {
targetFile = targetFile.replace(/\.js$/, '.html');
queue.push(function(cb) {
request('http://localhost:8079/' + targetFile.replace(/^build\//, ''), function(error, response, body) {
mkdirp.sync(targetFile.replace(new RegExp('/[^/]*$'), ''));
fs.writeFileSync(targetFile, body);
cb();
});
});
} else {
queue.push(function(cb) {
mkdirp.sync(targetFile.replace(new RegExp('/[^/]*$'), ''));
fs.copy(file, targetFile, cb);
});
}
});
queue.push(function(cb) {
server.close();
console.log('It is live at: http://facebook.github.io/react-native/')
cb();
});
});

53
website/server/server.js Normal file
View File

@ -0,0 +1,53 @@
"use strict";
var connect = require('connect');
var http = require('http');
var optimist = require('optimist');
var path = require('path');
var reactMiddleware = require('react-page-middleware');
var convert = require('./convert.js');
var argv = optimist.argv;
var PROJECT_ROOT = path.resolve(__dirname, '..');
var FILE_SERVE_ROOT = path.join(PROJECT_ROOT, 'src');
var port = argv.port;
if (argv.$0 === 'node ./server/generate.js') {
// Using a different port so that you can publish the website
// and keeping the server up at the same time.
port = 8079;
}
var buildOptions = {
projectRoot: PROJECT_ROOT,
pageRouteRoot: FILE_SERVE_ROOT,
useBrowserBuiltins: false,
logTiming: true,
useSourceMaps: true,
ignorePaths: function(p) {
return p.indexOf('__tests__') !== -1;
},
serverRender: true,
dev: argv.dev !== 'false',
static: true
};
var app = connect()
.use(function(req, res, next) {
// convert all the md files on every request. This is not optimal
// but fast enough that we don't really need to care right now.
convert();
next();
})
.use(reactMiddleware.provide(buildOptions))
.use(connect['static'](FILE_SERVE_ROOT))
.use(connect.favicon(path.join(FILE_SERVE_ROOT, 'elements', 'favicon', 'favicon.ico')))
.use(connect.logger())
.use(connect.compress())
.use(connect.errorHandler());
var portToUse = port || 8080;
var server = http.createServer(app);
server.listen(portToUse);
console.log('Open http://localhost:' + portToUse + '/react-native/index.html');
module.exports = server;

View File

@ -0,0 +1,967 @@
html {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-family: proxima-nova, "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: 300;
color: #484848;
line-height: 1.28;
}
body {
background-color: #F5FCFF;
}
p {
margin: 0 0 10px;
}
.subHeader {
font-size: 21px;
font-weight: 200;
line-height: 30px;
margin-bottom: 10px;
}
em {
font-style: italic;
}
h1, h2, h3, h4, h5, h6 {
margin: 10px 0;
font-family: inherit;
font-weight: bold;
line-height: 20px;
color: inherit;
text-rendering: optimizelegibility;
}
h1 small, h2 small, h3 small, h4 small, h5 small, h6 small {
font-weight: normal;
color: #7b7b7b;
}
h1, h2, h3 {
line-height: 40px;
}
h1 {
font-size: 39px;
}
h2 {
font-size: 31px;
}
h3 {
font-size: 23px;
}
h4 {
font-size: 17px;
}
h5 {
font-size: 14px;
}
h6 {
font-size: 11px;
}
h1 small {
font-size: 24px;
}
h2 small {
font-size: 18px;
}
h3 small {
font-size: 16px;
}
h4 small {
font-size: 14px;
}
ul, ol {
margin: 0 0 10px 25px;
padding: 0;
}
ul ul, ul ol, ol ol, ol ul {
margin-bottom: 0;
}
li {
line-height: 20px;
}
a {
color: #05A5D1;
text-decoration: none;
}
a:hover, a:focus {
color: #0485A9;
text-decoration: underline;
}
a:focus {
outline: thin dotted #333;
outline: 5px auto -webkit-focus-ring-color;
outline-offset: -2px;
}
.center {
text-align: center;
}
html * {
color-profile: sRGB;
rendering-intent: auto;
}
.prism {
white-space: pre-wrap;
font-family: 'source-code-pro', Menlo, 'Courier New', Consolas, monospace;
font-size: 13px;
line-height: 20px;
border-left: 4px solid #05A5D1;
padding: 5px 10px;
margin-left: 20px;
background-color: rgba(5, 165, 209, 0.05);
}
.prism + .prism {
margin-top: 10px;
}
.token.keyword {
color: #1990B8;
}
.token.string, .token.regex {
color: #2F9C0A;
}
.token.boolean, .token.number {
color: #C92C2C;
}
.token.comment {
color: #7D8B99;
}
.side-by-side {
overflow: hidden;
}
.side-by-side > div {
width: 460;
margin-left: 0;
float: left;
}
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
border: none;
margin: 0;
padding: 0;
}
.left {
float: left;
}
.right {
float: right;
}
.container {
padding-top: 50px;
min-width: 960px;
}
.wrap {
width: 960px;
margin-left: auto;
margin-right: auto;
padding-left: 20px;
padding-right: 20px;
}
.skinnyWrap {
width: 690px;
margin-left: auto;
margin-right: auto;
padding-left: 20px;
padding-right: 20px;
}
hr {
height: 0;
border-top: 1px solid #ccc;
border-bottom: 1px solid #eee;
}
ul, li {
margin-left: 20px;
}
h1 .anchor, h2 .anchor, h3 .anchor, h4 .anchor, h5 .anchor, h6 .anchor {
margin-top: -50px;
position: absolute;
}
h1:hover .hash-link, h2:hover .hash-link, h3:hover .hash-link, h4:hover .hash-link, h5:hover .hash-link, h6:hover .hash-link {
visibility: visible;
}
.hash-link {
color: #aaa;
visibility: hidden;
}
.nav-main {
*zoom: 1;
background: #3B3738;
color: #fafafa;
position: fixed;
top: 0;
height: 50px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
width: 100%;
z-index: 100;
}
.nav-main:before, .nav-main:after {
content: " ";
display: table;
}
.nav-main:after {
clear: both;
}
.nav-main a {
color: #e9e9e9;
text-decoration: none;
}
.nav-main .nav-site {
float: right;
margin: 0;
}
.nav-main .nav-site li {
margin: 0;
}
.nav-main .nav-site a {
padding: 0 8px;
text-transform: uppercase;
letter-spacing: 1px;
line-height: 50px;
display: inline-block;
height: 50px;
color: #aaa;
}
.nav-main .nav-site a:hover {
color: #fafafa;
}
.nav-main .nav-site a.active {
color: #fafafa;
border-bottom: 3px solid #05A5D1;
background: #333;
}
.nav-main .nav-home {
font-size: 24px;
line-height: 50px;
}
.nav-home img {
vertical-align: -7px;
margin-right: 7px;
width: 30px;
height: 30px;
}
.nav-main ul {
display: inline;
}
.nav-main li {
display: inline;
}
.hero {
background: #05A5D1;
padding: 50px 0;
color: #FDF3E7;
font-weight: 300;
}
.hero .text {
font-size: 64px;
text-align: center;
}
.hero .minitext {
font-size: 16px;
text-align: center;
text-transform: uppercase;
}
.hero strong {
font-weight: 400;
}
.buttons-unit {
margin-top: 60px;
text-align: center;
}
.buttons-unit a {
color: #FA6900;
}
.buttons-unit .button {
font-size: 24px;
background: #05A5D1;
color: #fafafa;
}
.buttons-unit .button:active {
background: #0485A9;
}
.buttons-unit.downloads {
margin: 30px 0;
}
.nav-docs {
color: #2d2d2d;
font-size: 14px;
float: left;
width: 210px;
}
.nav-docs ul {
list-style: none;
margin: 0;
}
.nav-docs ul ul {
margin-left: 20px;
}
.nav-docs li {
margin: 0;
}
.nav-docs h3 {
text-transform: uppercase;
font-size: 14px;
}
.nav-docs a {
color: #666;
display: block;
}
.nav-docs a:hover {
text-decoration: none;
color: #0485A9;
}
.nav-docs a.active {
color: #0485A9;
}
.nav-docs .nav-docs-section {
border-bottom: 1px solid #ccc;
border-top: 1px solid #eee;
padding: 12px 0;
}
.nav-docs .nav-docs-section:first-child {
padding-top: 0;
border-top: 0;
}
.nav-docs .nav-docs-section:last-child {
padding-bottom: 0;
border-bottom: 0;
}
.nav-blog li {
margin-bottom: 5px;
}
.home-section {
margin: 50px 0;
}
.home-section ol {
margin-left: 0;
}
.home-divider {
border-top-color: #bbb;
margin: 0 auto;
width: 400px;
}
.marketing-row {
*zoom: 1;
margin: 50px 0;
}
.marketing-row:before, .marketing-row:after {
content: " ";
display: table;
}
.marketing-row:after {
clear: both;
}
.marketing-col {
float: left;
margin-left: 40px;
width: 280px;
}
.marketing-col h3 {
color: #2d2d2d;
font-size: 24px;
font-weight: normal;
text-transform: uppercase;
}
.marketing-col p {
font-size: 16px;
}
.marketing-col:first-child {
margin-left: 0;
}
#examples h3, .home-presentation h3 {
color: #2d2d2d;
font-size: 24px;
font-weight: normal;
margin-bottom: 5px;
}
#examples p {
margin: 0 0 25px 0;
max-width: 600px;
}
#examples .example {
margin-top: 60px;
}
#examples #todoExample {
font-size: 14px;
}
#examples #todoExample ul {
list-style-type: square;
margin: 0 0 10px 0;
}
#examples #todoExample input {
border: 1px solid #ccc;
font: 14px proxima-nova, "Helvetica Neue", Helvetica, Arial, sans-serif;
padding: 3px;
width: 150px;
}
#examples #todoExample button {
font: 14px proxima-nova, "Helvetica Neue", Helvetica, Arial, sans-serif;
margin-left: 5px;
padding: 4px 10px;
}
#examples #markdownExample textarea {
border: 1px solid #ccc;
font: 14px proxima-nova, "Helvetica Neue", Helvetica, Arial, sans-serif;
margin-bottom: 10px;
padding: 5px;
}
.home-bottom-section {
margin-bottom: 100px;
}
.docs-nextprev {
*zoom: 1;
}
.docs-nextprev:before, .docs-nextprev:after {
content: " ";
display: table;
}
.docs-nextprev:after {
clear: both;
}
.docs-prev {
float: left;
}
.docs-next {
float: right;
}
footer {
font-size: 13px;
font-weight: 600;
padding-top: 36px;
padding-bottom: 18px;
overflow: auto;
}
section.black content {
padding-bottom: 18px;
}
.blogContent {
*zoom: 1;
padding-top: 20px;
}
.blogContent:before, .blogContent:after {
content: " ";
display: table;
}
.blogContent:after {
clear: both;
}
.blogContent blockquote {
padding: 5px 15px;
margin: 20px 0;
background-color: #f8f5ec;
border-left: 5px solid #f7ebc6;
}
.documentationContent {
*zoom: 1;
padding-top: 20px;
}
.documentationContent:before, .documentationContent:after {
content: " ";
display: table;
}
.documentationContent:after {
clear: both;
}
.documentationContent .subHeader {
font-size: 24px;
}
.documentationContent h2 {
margin-top: 30px;
}
.documentationContent blockquote {
padding: 15px 30px 15px 15px;
margin: 20px 0;
background-color: rgba(204, 122, 111, 0.1);
border-left: 5px solid rgba(191, 87, 73, 0.2);
}
.documentationContent blockquote h4 {
margin-top: 0;
}
.documentationContent blockquote p {
margin-bottom: 0;
}
.documentationContent blockquote p:first-child {
font-weight: bold;
font-size: 17.5px;
line-height: 20px;
margin-top: 0;
text-rendering: optimizelegibility;
}
.docs-prevnext {
padding-top: 40px;
padding-bottom: 40px;
}
.button {
background: -webkit-linear-gradient( #9a9a9a, #646464);
background: linear-gradient( #9a9a9a, #646464);
border-radius: 4px;
padding: 8px 16px;
font-size: 18px;
font-weight: 400;
margin: 0 12px;
display: inline-block;
color: #fafafa;
text-decoration: none;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
text-decoration: none;
}
.button:hover {
text-decoration: none;
}
.button:active {
box-shadow: none;
}
.hero .button {
box-shadow: 1px 3px 3px rgba(0, 0, 0, 0.3);
}
.button.blue {
background: -webkit-linear-gradient( #77a3d2, #4783c2);
background: linear-gradient( #77a3d2, #4783c2);
}
.row {
padding-bottom: 4px;
}
.row .span4 {
width: 33.33%;
display: table-cell;
}
.row .span8 {
width: 66.66%;
display: table-cell;
}
.row .span6 {
width: 50%;
display: table-cell;
}
p {
margin: 10px 0;
}
.highlight {
padding: 10px;
margin-bottom: 20px;
}
figure {
text-align: center;
}
.inner-content {
float: right;
width: 650px;
}
.nosidebar .inner-content {
float: none;
margin: 0 auto;
}
.post-list-item+.post-list-item {
margin-top: 60px;
}
small code, li code, p code {
color: #555;
background-color: rgba(0, 0, 0, 0.04);
padding: 1px 3px;
}
.playground {
*zoom: 1;
}
.playground:before, .playground:after {
content: " ";
display: table;
}
.playground:after {
clear: both;
}
.playground-tab {
border-bottom: none !important;
border-radius: 3px 3px 0 0;
padding: 6px 8px;
font-size: 12px;
font-weight: bold;
color: #c2c0bc;
background-color: #f1ede4;
display: inline-block;
cursor: pointer;
}
.playgroundCode, .playground-tab, .playgroundPreview {
border: 1px solid rgba(16, 16, 16, 0.1);
}
.playground-tab-active {
color: #222;
}
.playgroundCode {
border-radius: 0 3px 3px 3px;
float: left;
overflow: hidden;
width: 600px;
}
.playgroundPreview {
background-color: white;
border-radius: 3px;
float: right;
padding: 15px 20px;
width: 280px;
}
.playgroundError {
color: #c5695c;
font-size: 15px;
}
.MarkdownEditor textarea {
width: 100%;
height: 100px;
}
.hll {
background-color: #f7ebc6;
border-left: 5px solid #f7d87c;
display: block;
margin-left: -14px;
margin-right: -14px;
padding-left: 9px;
}
.highlight .javascript .err {
background-color: transparent;
color: inherit;
}
.highlight {
position: relative;
margin-bottom: 14px;
padding: 30px 14px 14px;
border: none;
border-radius: 0;
overflow: auto;
}
.highlight pre {
padding: 0;
margin-top: 0;
margin-bottom: 0;
background-color: transparent;
border: 0;
}
.highlight pre code {
background: none;
font-size: inherit;
padding: 0;
}
.highlight pre .lineno {
display: inline-block;
width: 22px;
padding-right: 5px;
margin-right: 10px;
color: #bebec5;
text-align: right;
}
.highlight:after {
position: absolute;
top: 0;
right: 0;
left: 0;
padding: 3px 7px;
font-size: 12px;
font-weight: bold;
color: #c2c0bc;
background-color: #f1ede4;
content: "Code";
}
.downloadCenter {
text-align: center;
margin-top: 20px;
margin-bottom: 25px;
}
.downloadSection:hover {
text-decoration: none !important;
}
@media screen and (max-width: 960px) {
.nav-main {
position: static;
}
.container {
padding-top: 0;
}
}
.post {
margin-bottom: 30px;
}
.pagination {
margin-bottom: 30px;
width: 100%;
overflow: hidden;
}
.pagination .next {
float: right;
}
div[data-twttr-id] iframe {
margin: 10px auto !important;
}
.three-column {
*zoom: 1;
}
.three-column:before, .three-column:after {
content: " ";
display: table;
}
.three-column:after {
clear: both;
}
.three-column>ul {
float: left;
margin-left: 30px;
width: 190px;
}
.three-column > ul:first-child {
margin-left: 20px;
}
.home-why {
margin-top: 25px;
}
.home-why h3 {
text-align: center;
}
.home-why .blurb {
margin-bottom: 20px;
text-align: center;
}
.home-why .list {
margin: 0 auto;
max-width: 460px;
}
.home-getting-started {
width: 500px;
margin: 20px auto 40px auto;
}
.home-getting-started h3 {
text-align: center;
}
#content {
display: none;
}
@media only screen and (max-device-width : 1024px) {
#content {
display: inline;
}
.container {
min-width: 0;
overflow: auto;
}
.wrap {
width: auto;
}
.home-getting-started {
width: auto;
}
.inner-content {
width: auto;
float: none;
}
.marketing-col {
margin-left: 0;
float: none;
margin-bottom: 30px;
text-align: center;
}
.home-section, .marketing-row {
margin: 0;
}
.nav-main .nav-site a {
padding: 0 4px;
}
.nav-main .wrap {
padding: 0 2px 0 4px;
}
.home-divider {
display: none;
}
.hero {
padding: 10px 0 30px 0;
}
.prism {
padding: 4px 8px;
margin-left: -12px;
font-size: 11px;
}
.nav-docs .nav-docs-section {
border: none;
padding: 0;
}
.nav-docs h3 {
margin: 0;
}
.nav-docs {
float: none;
width: auto;
margin-top: -20px;
margin-bottom: 20px;
}
h1 {
font-size: 30px;
line-height: 30px;
}
ol {
margin: 0;
}
}

View File

@ -0,0 +1,85 @@
/**
* @generated
* @jsx React.DOM
*/
var React = require("React");
var layout = require("DocsLayout");
var content = `
Our first React Native implementation is \`ReactKit\`, targeting iOS. We are also
working on an Android implementation which we will release later. \`ReactKit\`
apps are built using the [React JS](https://github.com/facebook/react) framework, and render directly to
native UIKit elements using a fully asynchronous architecture. There is no
browser and no HTML. We have picked what we think is the best set of features
from these and other technologies to build what we hope to become the best
product development framework available, with an emphasis on iteration speed,
developer delight, continuity of technology, and absolutely beautiful and fast
products with no compromises in quality or capability.
## Requirements
1. OS X - This repo only contains the iOS implementation right now, and Xcode only runs on Mac.
2. New to Xcode? [Download it](https://developer.apple.com/xcode/downloads/) from the Mac App Store.
3. [Homebrew](http://brew.sh/) is the recommended way to install node, watchman, and flow.
4. New to node or npm? \`brew install node\`
5. We recommend installing [watchman](https://facebook.github.io/watchman/docs/install.html), otherwise you might hit a node file watching bug. \`brew install watchman\`
6. If you want to use [flow](http://www.flowtype.org), \`brew install flow\`
## Quick start
Get up and running with our Movies sample app:
1. Once you have the repo cloned and met all the requirements above, start the
packager that will transform your JS code on-the-fly:
\`\`\`
npm install
npm start
\`\`\`
2. Open the \`Examples/Movies/Movies.xcodeproj\` project in Xcode.
3. Make sure the target is set to \`Movies\` and that you have an iOS simulator
selected to run the app.
4. Build and run the project with the Xcode run button.
You should now see the Movies app running on your iOS simulator.
Congratulations! You've just successfully run your first React Native app.
Now try editing a JavaScript file and viewing your changes. Let's change the
movie search placeholder text:
1. Open the \`Examples/Movies/SearchScreen.js\` file in your favorite JavaScript
editor.
2. Look for the current search placeholder text and change it to "Search for an
awesome movie...".
3. Hit cmd+R ([twice](http://openradar.appspot.com/19613391)) in your iOS simulator to reload the app and see your change.
If you don't immediately see your changes, try restarting your app within Xcode.
Feel free to browse the Movies sample files and customize various properties to
get familiar with the codebase and React Native.
Also check out the UI Component Explorer for more sample code:
\`Examples/UIExplorer/UIExplorer.xcodeproj\`. **Make sure to close the Movies
project first - Xcode will break if you have two projects open that reference
the same library.**
## Troubleshooting
+ Xcode will break if you have two examples open at the same time.
+ If \`npm start\` fails with log spew like:
\`\`\`
2015-02-02 10:56 node[24294] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-21)
\`\`\`
then you've hit the node file watching bug - \`brew install watchman\` should fix the issue.
+ Jest testing does not yet work on node versions after 0.10.x.
+ You can verify the packager is working by loading the [bundle](http://localhost:8081/Examples/Movies/MoviesApp.includeRequire.runModule.bundle) in your browser and
inspecting the contents.
Please report any other issues you encounter so we can fix them ASAP.
`
var Post = React.createClass({
render: function() {
return layout({metadata: {"id":"getting-started","title":"Getting Started","layout":"docs","category":"Quick Start","permalink":"docs/getting-started.html"}}, content);
}
});
Post.content = content;
module.exports = Post;

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

34
website/src/react-native/index.js vendored Normal file
View File

@ -0,0 +1,34 @@
/**
* @jsx React.DOM
*/
var React = require('React');
var Site = require('Site');
var index = React.createClass({
render: function() {
return (
<Site>
<div className="hero">
<div className="wrap">
<div className="text"><strong>React Native</strong></div>
<div className="minitext">
Build native apps using React
</div>
</div>
</div>
<section className="content wrap">
<section className="home-bottom-section">
<div className="buttons-unit">
<a href="docs/getting-started.html#content" className="button">Learn more about React Native</a>
</div>
</section>
<p></p>
</section>
</Site>
);
}
});
module.exports = index;

44
website/src/react-native/support.js vendored Normal file
View File

@ -0,0 +1,44 @@
/**
* @jsx React.DOM
*/
var React = require('React');
var Site = require('Site');
var center = require('center');
var H2 = require('H2');
var support = React.createClass({
render: function() {
return (
<Site section="support">
<section className="content wrap documentationContent nosidebar">
<div className="inner-content">
<h1>Need help?</h1>
<div className="subHeader"></div>
<p>
<strong>React Native</strong> is worked on full-time by Facebook&#39;s
product infrastructure user interface
engineering teams. They&#39;re often around and available for
questions.
</p>
<H2>Stack Overflow</H2>
<p>Many members of the community use Stack Overflow to ask questions. Read through the <a href="http://stackoverflow.com/questions/tagged/reactnative">existing questions</a> tagged with <strong>reactnative</strong> or <a href="http://stackoverflow.com/questions/ask">ask your own</a>!</p>
<H2>IRC</H2>
<p>Many developers and users idle on Freenode.net&#39;s IRC network in <strong><a href="irc://chat.freenode.net/reactnative">#reactnative on freenode</a></strong>.</p>
<H2>Twitter</H2>
<p><a href="https://twitter.com/search?q=%23reactnative"><strong>#reactnative</strong> hash tag on Twitter</a> is used to keep up with the latest React Native news.</p>
<p><center><a className="twitter-timeline" data-dnt="true" data-chrome="nofooter noheader transparent" href="https://twitter.com/search?q=%23react+native" data-widget-id="464145350849085440"></a></center></p>
</div>
</section>
</Site>
);
}
});
module.exports = support;