diff --git a/assets/images/icons.png b/assets/images/icons.png
index b4eda14a..4dd556a4 100644
Binary files a/assets/images/icons.png and b/assets/images/icons.png differ
diff --git a/assets/images/icons@2x.png b/assets/images/icons@2x.png
index a505912d..0eb476f3 100644
Binary files a/assets/images/icons@2x.png and b/assets/images/icons@2x.png differ
diff --git a/assets/javascripts/news.json b/assets/javascripts/news.json
index 23f3095d..422c46e0 100644
--- a/assets/javascripts/news.json
+++ b/assets/javascripts/news.json
@@ -1,6 +1,6 @@
[
- [ "2014-12-20",
- "New RethinkDB documentation"
+ [ "2014-12-21",
+ "New React and RethinkDB documentations"
], [
"2014-11-30",
"New PHPUnit and Nokogiri documentations"
diff --git a/assets/javascripts/templates/pages/about_tmpl.coffee b/assets/javascripts/templates/pages/about_tmpl.coffee
index 5ab6e593..a0e5557a 100644
--- a/assets/javascripts/templates/pages/about_tmpl.coffee
+++ b/assets/javascripts/templates/pages/about_tmpl.coffee
@@ -253,6 +253,11 @@ credits = [
'1990-2014 Python Software Foundation
Python is a trademark of the Python Software Foundation.',
'PSFL',
'http://docs.python.org/3/license.html'
+ ], [
+ 'React',
+ '2013-2014 Facebook Inc.',
+ 'CC BY',
+ 'https://raw.githubusercontent.com/facebook/react/master/LICENSE-docs'
], [
'Redis',
'2009-2014 Salvatore Sanfilippo',
diff --git a/assets/javascripts/views/pages/react.coffee b/assets/javascripts/views/pages/react.coffee
new file mode 100644
index 00000000..1432200e
--- /dev/null
+++ b/assets/javascripts/views/pages/react.coffee
@@ -0,0 +1,9 @@
+#= require views/pages/base
+
+class app.views.ReactPage extends app.views.BasePage
+ afterRender: ->
+ for el in @findAllByTag 'pre'
+ switch el.getAttribute('data-lang')
+ when 'html' then @highlightCode el, 'markup'
+ when 'javascript' then @highlightCode el, 'javascript'
+ return
diff --git a/assets/stylesheets/application.css.scss b/assets/stylesheets/application.css.scss
index b6c27952..a1a09878 100644
--- a/assets/stylesheets/application.css.scss
+++ b/assets/stylesheets/application.css.scss
@@ -57,6 +57,7 @@
'pages/phpunit',
'pages/postgres',
'pages/rdoc',
+ 'pages/react',
'pages/redis',
'pages/requirejs',
'pages/rethinkdb',
diff --git a/assets/stylesheets/components/_page.scss b/assets/stylesheets/components/_page.scss
index 420d856a..30935d85 100644
--- a/assets/stylesheets/components/_page.scss
+++ b/assets/stylesheets/components/_page.scss
@@ -15,6 +15,7 @@
iframe {
display: block;
+ margin-bottom: 1em;
padding: 1px;
border: 1px dotted $boxBorder;
border-radius: 3px;
diff --git a/assets/stylesheets/global/_icons.scss b/assets/stylesheets/global/_icons.scss
index e4c71c31..ace3022f 100644
--- a/assets/stylesheets/global/_icons.scss
+++ b/assets/stylesheets/global/_icons.scss
@@ -73,3 +73,4 @@
._icon-phpunit:before { background-position: -3rem -11rem; }
._icon-nokogiri:before { background-position: -4rem -11rem; }
._icon-rethinkdb:before { background-position: 0 -12rem; }
+._icon-react:before { background-position: -1rem -12rem; }
diff --git a/assets/stylesheets/pages/_react.scss b/assets/stylesheets/pages/_react.scss
new file mode 100644
index 00000000..dbed0046
--- /dev/null
+++ b/assets/stylesheets/pages/_react.scss
@@ -0,0 +1,8 @@
+._react {
+ > h2 { @extend %block-heading; }
+ > h3 { @extend %block-label, %label-blue; }
+ > h4 { font-size: 1em; }
+
+ code { @extend %label; }
+ blockquote { @extend %note; }
+}
diff --git a/lib/docs/filters/react/clean_html.rb b/lib/docs/filters/react/clean_html.rb
new file mode 100644
index 00000000..a9a7d829
--- /dev/null
+++ b/lib/docs/filters/react/clean_html.rb
@@ -0,0 +1,31 @@
+module Docs
+ class React
+ class CleanHtmlFilter < Filter
+ def call
+ @doc = at_css('.inner-content')
+
+ if root_page?
+ at_css('h1').content = 'React Documentation'
+ end
+
+ css('.docs-prevnext', '.hash-link', '.edit-page-link').remove
+
+ css('a.anchor').each do |node|
+ node.parent['id'] = node['name']
+ end
+
+ css('.highlight').each do |node|
+ node.name = 'pre'
+ node['data-lang'] = node.at_css('[data-lang]')['data-lang']
+ node.content = node.content
+ end
+
+ css('blockquote > p:first-child').each do |node|
+ node.remove if node.content.strip == 'Note:'
+ end
+
+ doc
+ end
+ end
+ end
+end
diff --git a/lib/docs/filters/react/entries.rb b/lib/docs/filters/react/entries.rb
new file mode 100644
index 00000000..c6b707e2
--- /dev/null
+++ b/lib/docs/filters/react/entries.rb
@@ -0,0 +1,34 @@
+module Docs
+ class React
+ class EntriesFilter < Docs::EntriesFilter
+ API_SLUGS = %w(
+ top-level-api
+ component-api
+ component-specs
+ )
+
+ def get_name
+ at_css('h1').child.content
+ end
+
+ def get_type
+ link = at_css('.nav-docs-section .active')
+ section = link.ancestors('.nav-docs-section').first
+ section.at_css('h3').content
+ end
+
+ def additional_entries
+ return [] unless API_SLUGS.include?(slug)
+
+ css('.inner-content h3, .inner-content h4').map do |node|
+ name = node.content
+ name.remove! %r{[#\(\)]}
+ name.remove! %r{\w+\:}
+ id = node.at_css('.anchor')['name']
+ type = slug.include?('component') ? 'Component' : 'React'
+ [name, id, type]
+ end
+ end
+ end
+ end
+end
diff --git a/lib/docs/scrapers/react.rb b/lib/docs/scrapers/react.rb
new file mode 100644
index 00000000..80879542
--- /dev/null
+++ b/lib/docs/scrapers/react.rb
@@ -0,0 +1,23 @@
+module Docs
+ class React < UrlScraper
+ self.name = 'React'
+ self.type = 'react'
+ self.version = '0.12.2'
+ self.base_url = 'http://facebook.github.io/react/docs/'
+ self.root_path = 'getting-started.html'
+
+ html_filters.push 'react/entries', 'react/clean_html'
+
+ options[:container] = '.documentationContent'
+
+ options[:skip] = %w(
+ videos.html
+ complementary-tools.html
+ examples.html)
+
+ options[:attribution] = <<-HTML
+ © 2013–2014 Facebook Inc.
+ Licensed under the Creative Commons Attribution 4.0 International Public License.
+ HTML
+ end
+end
diff --git a/public/icons/docs/react/16.png b/public/icons/docs/react/16.png
new file mode 100644
index 00000000..2d384517
Binary files /dev/null and b/public/icons/docs/react/16.png differ
diff --git a/public/icons/docs/react/16@2x.png b/public/icons/docs/react/16@2x.png
new file mode 100644
index 00000000..016a0c3c
Binary files /dev/null and b/public/icons/docs/react/16@2x.png differ
diff --git a/public/icons/docs/react/SOURCE b/public/icons/docs/react/SOURCE
new file mode 100644
index 00000000..58f9cc30
--- /dev/null
+++ b/public/icons/docs/react/SOURCE
@@ -0,0 +1 @@
+https://github.com/facebook/react/blob/master/docs/img/logo.svg