Skip to content

Commit

Permalink
Merge pull request #2375 from gombosg/master
Browse files Browse the repository at this point in the history
feat: React.dev docs
  • Loading branch information
simon04 authored Dec 12, 2024
2 parents ba661e7 + 7d26432 commit 78f1c87
Show file tree
Hide file tree
Showing 9 changed files with 180 additions and 25 deletions.
1 change: 1 addition & 0 deletions assets/stylesheets/application.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
'pages/qt',
'pages/ramda',
'pages/rdoc',
'pages/react',
'pages/react_native',
'pages/reactivex',
'pages/redis',
Expand Down
24 changes: 24 additions & 0 deletions assets/stylesheets/pages/_react.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
._react {
@extend %simple;

.note {
@extend %note;
h4 {
margin-top: .25rem;
margin-bottom: .5rem;
}
}

.note-orange {
@extend %note-orange;
}

.note-blue {
@extend %note-blue;
}

.note-green {
@extend %note-green;
}

}
2 changes: 1 addition & 1 deletion docs/adding-docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Adding a documentation may look like a daunting task but once you get the hang o
6. Generate the full documentation using the `thor docs:generate [my_doc] --force` command. Additionally, you can use the `--verbose` option to see which files are being created/updated/deleted (useful to see what changed since the last run), and the `--debug` option to see which URLs are being requested and added to the queue (useful to pin down which page adds unwanted URLs to the queue).
7. Start the server, open the app, enable the documentation, and see how everything plays out.
8. Tweak the scraper/filters and repeat 5) and 6) until the pages and metadata are ok.
9. To customize the pages' styling, create an SCSS file in the `assets/stylesheets/pages/` directory and import it in both `application.css.scss` AND `application-dark.css.scss`. Both the file and CSS class should be named `_[type]` where [type] is equal to the scraper's `type` attribute (documentations with the same type share the same custom CSS and JS). Setting the type to `simple` will apply the general styling rules in `assets/stylesheets/pages/_simple.scss`, which can be used for documentations where little to no CSS changes are needed.
9. To customize the pages' styling, create an SCSS file in the `assets/stylesheets/pages/` directory and import it in `application.css.scss`. Both the file and CSS class should be named `_[type]` where [type] is equal to the scraper's `type` attribute (documentations with the same type share the same custom CSS and JS). Setting the type to `simple` will apply the general styling rules in `assets/stylesheets/pages/_simple.scss`, which can be used for documentations where little to no CSS changes are needed.
10. To add syntax highlighting or execute custom JavaScript on the pages, create a file in the `assets/javascripts/views/pages/` directory (take a look at the other files to see how it works).
11. Add the documentation's icon in the `public/icons/docs/[my_doc]/` directory, in both 16x16 and 32x32-pixels formats. The icon spritesheet is automatically generated when you (re)start your local DevDocs instance.
12. Add the documentation's copyright details to `options[:attribution]`. This is the data shown in the table on the [about](https://devdocs.io/about) page, and is ordered alphabetically. Please see an existing scraper for the typesetting.
Expand Down
77 changes: 77 additions & 0 deletions lib/docs/filters/react/clean_html_react_dev.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
module Docs
class React
class CleanHtmlReactDevFilter < Filter
def call
@doc = at_css('article')

# Remove breadcrumbs before h1
css('h1').each do |node|
if node.previous
node.previous.remove
end
end

remove_selectors = [
'div.grid > a', # prev-next links
'button', # "show more" etc. buttons
'div.order-last', # code iframe containers
'div.dark-image', # dark images
'a[title="Open in CodeSandbox"]', # codesandbox links
]
css(*remove_selectors).each do |node|
node.remove
end

# Fix images not loading
css('img').remove_attr('srcset')

# Remove recipe blocks - TODO transform to outgoing link to docs
css('h4[id^="examples-"]').each do |node|
node.parent.parent.parent.remove
end

# Transform callout blocks
class_transform = {
'.expandable-callout[class*=yellow]' => 'note note-orange', # pitfalls, experimental
'.expandable-callout[class*=green]' => 'note note-green', # note
'.expandable-callout[class*=gray]' => 'note', # canary
'.bg-card' => 'note', # you will learn
'details' => 'note note-blue' # deep dive
}

class_transform.each do |old_class, new_class|
css(old_class).each do |node|
node.set_attribute('class', new_class)
end
end

# Transform h3 to h4 inside callouts
css('.note h3', '.note h2').each do |node|
new_node = Nokogiri::XML::Node.new('h4', @doc)
new_node.content = node.content
node.replace(new_node)
end

# Remove styling divs while lifting children
styling_prefixes = %w[ps- mx- my- px- py- mb- sp- rounded-]
selectors = styling_prefixes.map { |prefix| "div[class*=\"#{prefix}\"]:not(.note)" }
css(*selectors, 'div[class=""]', 'div.cm-line').each do |node|
node.before(node.children).remove
end

# Syntax highlighting
css('pre br').each do |node|
node.replace("\n")
end
css('pre').each do |node|
node['data-language'] = 'jsx'
end

# Remove styling except for callouts and images
css('*:not([class*=image]):not(.note)').remove_attr('class').remove_attr('style')

doc
end
end
end
end
32 changes: 32 additions & 0 deletions lib/docs/filters/react/entries_react_dev.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module Docs
class React
class EntriesReactDevFilter < Docs::EntriesFilter
def get_name
name = at_css('article h1')&.content

update_canary_copy(name)
end

def get_type
# Category is the opened category in the sidebar
category = css('a:has(> span.text-link) > div').first&.content
# The grey category in the sidebar
top_category = css('h3:has(~ li a.text-link)')
.last&.content
&.sub(/@.*$/, '') # remove version tag
&.sub(/^./, &:upcase) # capitalize first letter
&.concat(": ")
is_learn_page = path.start_with?('learn/') || slug == 'learn'
prefix = is_learn_page ? 'Learn: ' : top_category || ''

update_canary_copy(prefix + (category || 'Miscellaneous'))
end

def update_canary_copy(string)
canary_copy = '- This feature is available in the latest Canary'

string.sub(canary_copy, ' (Canary)')
end
end
end
end
65 changes: 43 additions & 22 deletions lib/docs/scrapers/react.rb
Original file line number Diff line number Diff line change
@@ -1,38 +1,59 @@
module Docs
class React < UrlScraper

self.name = 'React'
self.type = 'simple'
self.release = '18.2.0'
self.base_url = 'https://reactjs.org/docs/'
self.root_path = 'hello-world.html'
self.type = 'react'
self.links = {
home: 'https://reactjs.org/',
home: 'https://react.dev/',
code: 'https://github.com/facebook/react'
}

html_filters.push 'react/entries', 'react/clean_html'

options[:skip] = %w(
codebase-overview.html
design-principles.html
how-to-contribute.html
implementation-notes.html
)

options[:replace_paths] = {
'more-about-refs.html' => 'refs-and-the-dom.html',
'interactivity-and-dynamic-uis.html' => 'state-and-lifecycle.html',
'working-with-the-browser.html' => 'refs-and-the-dom.html',
'top-level-api.html' => 'react-api.html',
}

options[:attribution] = <<-HTML
&copy; 2013&ndash;present Facebook Inc.<br>
Licensed under the Creative Commons Attribution 4.0 International Public License.
HTML

version do
self.release = '19'
self.base_url = 'https://react.dev'
self.initial_paths = %w(/reference/react /learn)
html_filters.push 'react/entries_react_dev', 'react/clean_html_react_dev'

options[:only_patterns] = [/\A\/learn/, /\A\/reference/]
end

version '18' do
self.release = '18.3.1'
self.base_url = 'https://18.react.dev'
self.initial_paths = %w(/reference/react /learn)
html_filters.push 'react/entries_react_dev', 'react/clean_html_react_dev'

options[:only_patterns] = [/\A\/learn/, /\A\/reference/]
end

version '17' do
self.release = '17.0.2'
self.base_url = 'https://17.reactjs.org/docs/'
self.root_path = 'hello-world.html'
html_filters.push 'react/entries', 'react/clean_html'

options[:skip] = %w(
codebase-overview.html
design-principles.html
how-to-contribute.html
implementation-notes.html
)

options[:replace_paths] = {
'more-about-refs.html' => 'refs-and-the-dom.html',
'interactivity-and-dynamic-uis.html' => 'state-and-lifecycle.html',
'working-with-the-browser.html' => 'refs-and-the-dom.html',
'top-level-api.html' => 'react-api.html',
}
end

def get_latest_version(opts)
doc = fetch_doc('https://reactjs.org/docs/getting-started.html', opts)
doc = fetch_doc('https://react.dev/', opts)
doc.at_css('a[href="/versions"]').content.strip[1..-1]
end
end
Expand Down
Binary file modified public/icons/docs/react/16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/icons/docs/react/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions public/icons/docs/react/SOURCE
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
https://es.m.wikipedia.org/wiki/React#/media/Archivo%3AReact.svg
https://github.com/facebook/react/blob/master/docs/img/logo.svg
https://github.com/reactjs/react.dev/blob/master/public/favicon-16x16.png
https://github.com/reactjs/react.dev/blob/master/public/favicon-32x32.png

0 comments on commit 78f1c87

Please sign in to comment.