Merge branch 'origin/main' into pcl_improve_clean_html

pull/1694/head
Simon Legner 2 years ago
commit 06233f71d2

@ -67,10 +67,11 @@ Follow the following steps to update documentations to their latest version:
2. Check if the license is still correct. If you update `options[:attribution]`, also update the documentation's entry in the array in [`assets/javascripts/templates/pages/about_tmpl.coffee`](../assets/javascripts/templates/pages/about_tmpl.coffee) to match.
3. If the documentation has a custom icon, ensure the icons in <code>public/icons/*your_scraper_name*/</code> are up-to-date. If you pull the updated icon from a place different than the one specified in the `SOURCE` file, make sure to replace the old link with the new one.
4. If `self.links` is defined, check if the urls are still correct.
5. Generate the docs using `thor docs:generate <doc@version>`.
6. Make sure `thor docs:generate` doesn't show errors and that the documentation still works well. Verify locally that everything works and that the categorization of entries is still good. Often, updates will require code changes in the scraper or its filters to tweak some new markup in the source website or to categorize new entries.
7. Repeat steps 5 and 6 for all versions that you updated.
8. Create a PR and make sure to fill the checklist in section B of the PR template (remove the other sections).
5. If the scraper inherits from `FileScraper` rather than `URLScraper`, follow the instructions for that scraper in [`file-scrapers.md`](../docs/file-scrapers.md) to obtain the source material for the scraper.
6. Generate the docs using `thor docs:generate <doc@version>`.
7. Make sure `thor docs:generate` doesn't show errors and that the documentation still works well. Verify locally that everything works and that the categorization of entries is still good. Often, updates will require code changes in the scraper or its filters to tweak some new markup in the source website or to categorize new entries.
8. Repeat steps 5 and 6 for all versions that you updated.
9. Create a PR and make sure to fill the checklist in section B of the PR template (remove the other sections).
## Coding conventions
@ -83,4 +84,4 @@ Check out [EditorConfig.org](https://editorconfig.org/) to learn how to make you
## Questions?
If you have any questions, please feel free to ask them on the contributor chat room on [Gitter](https://gitter.im/FreeCodeCamp/DevDocs).
If you have any questions, please feel free to ask them on the contributor chat room on [Discord](https://discord.gg/PRyKn3Vbay).

@ -1,8 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Question
about: "Ask questions and have discussions on Gitter"
url: "https://gitter.im/FreeCodeCamp/DevDocs"
about: "Ask questions and have discussions on Discord"
url: "https://discord.gg/PRyKn3Vbay"
- name: New Documentation
about: "Request a new documentation on Trello"
url: "https://trello.com/b/6BmTulfx/devdocs-documentation"

@ -11,15 +11,15 @@ jobs:
runs-on: ubuntu-20.04
if: github.repository == 'freeCodeCamp/devdocs'
steps:
- uses: actions/checkout@v2.4.0
- uses: actions/checkout@dc323e67f16fb5f7663d20ff7941f27f5809e9b6 # v2.6.0
- name: Set up Ruby
uses: ruby/setup-ruby@v1.92.0
uses: ruby/setup-ruby@319066216501fbd5e2d568f14b7d68c19fb67a5d # v1.133.1
with:
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- name: Run tests
run: bundle exec rake
- name: Deploy to Heroku
uses: akhileshns/heroku-deploy@v3.12.12
uses: akhileshns/heroku-deploy@79ef2ae4ff9b897010907016b268fd0f88561820 # tag=v3.12.12
with:
heroku_api_key: ${{secrets.HEROKU_API_KEY}}
heroku_app_name: "devdocs"

@ -8,9 +8,9 @@ jobs:
runs-on: ubuntu-20.04
if: github.repository == 'freeCodeCamp/devdocs'
steps:
- uses: actions/checkout@v2.4.0
- uses: actions/checkout@dc323e67f16fb5f7663d20ff7941f27f5809e9b6 # v2.6.0
- name: Set up Ruby
uses: ruby/setup-ruby@v1.92.0
uses: ruby/setup-ruby@319066216501fbd5e2d568f14b7d68c19fb67a5d # v1.133.1
with:
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- name: Generate report

@ -9,9 +9,9 @@ jobs:
test:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2.4.0
- uses: actions/checkout@dc323e67f16fb5f7663d20ff7941f27f5809e9b6 # v2.6.0
- name: Set up Ruby
uses: ruby/setup-ruby@v1.92.0
uses: ruby/setup-ruby@319066216501fbd5e2d568f14b7d68c19fb67a5d # v1.133.1
with:
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- name: Run tests

@ -1 +1 @@
2.7.5
2.7.7

@ -0,0 +1 @@
ruby 2.7.7

@ -1,4 +1,4 @@
Copyright 2013-2021 Thibaut Courouble and other contributors
Copyright 2013-2023 Thibaut Courouble and other contributors
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this

@ -1,4 +1,4 @@
FROM ruby:2.7.5
FROM ruby:2.7.7
ENV LANG=C.UTF-8
ENV ENABLE_SERVICE_WORKER=true

@ -1,4 +1,4 @@
FROM ruby:2.6.5-alpine
FROM ruby:2.7.7-alpine
ENV LANG=C.UTF-8
ENV ENABLE_SERVICE_WORKER=true

@ -39,6 +39,7 @@ group :development do
end
group :docs do
gem 'redcarpet'
gem 'progress_bar', require: false
gem 'unix_utils', require: false
gem 'tty-pager', require: false

@ -26,7 +26,7 @@ GEM
eventmachine (1.2.7)
execjs (2.7.0)
exifr (1.3.6)
ffi (1.12.2)
ffi (1.15.5)
fspath (3.1.2)
highline (2.0.3)
html-pipeline (2.12.0)
@ -46,16 +46,17 @@ GEM
image_size (2.0.2)
in_threads (1.5.3)
method_source (1.0.0)
mini_portile2 (2.6.1)
mini_portile2 (2.8.0)
minitest (5.14.4)
multi_json (1.13.1)
mustermann (1.0.3)
mustermann (1.1.2)
ruby2_keywords (~> 0.0.1)
net-sftp (3.0.0.beta1)
net-ssh (>= 5.0.0, < 6.0.0)
net-ssh (5.2.0)
newrelic_rpm (6.7.0.359)
nokogiri (1.12.5)
mini_portile2 (~> 2.6.1)
nokogiri (1.13.10)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
options (2.3.2)
progress (3.5.2)
@ -65,8 +66,8 @@ GEM
pry (0.14.1)
coderay (~> 1.1)
method_source (~> 1.0)
racc (1.6.0)
rack (2.2.3)
racc (1.6.1)
rack (2.2.4)
rack-protection (2.0.7)
rack
rack-ssl-enforcer (0.2.9)
@ -76,7 +77,9 @@ GEM
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
ffi (~> 1.0)
redcarpet (3.5.1)
rr (1.2.1)
ruby2_keywords (0.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
@ -114,7 +117,7 @@ GEM
rack (>= 1, < 3)
thor (0.20.3)
thread_safe (0.3.6)
tilt (2.0.10)
tilt (2.0.11)
tty-pager (0.12.1)
strings (~> 0.1.4)
tty-screen (~> 0.6)
@ -123,14 +126,14 @@ GEM
tty-which (0.4.1)
typhoeus (1.3.1)
ethon (>= 0.9.0)
tzinfo (1.2.9)
tzinfo (1.2.10)
thread_safe (~> 0.1)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
unicode-display_width (1.6.0)
unicode_utils (1.4.0)
unix_utils (0.0.15)
yajl-ruby (1.4.1)
yajl-ruby (1.4.3)
PLATFORMS
ruby
@ -155,6 +158,7 @@ DEPENDENCIES
rack-ssl-enforcer
rack-test
rake
redcarpet
rr
sass
sinatra

@ -6,11 +6,11 @@ DevDocs was created by [Thibaut Courouble](https://thibaut.me) and is operated b
## We are currently searching for maintainers
Please reach out to the community on [Gitter](https://gitter.im/FreeCodeCamp/DevDocs) if you would like to join the team!
Please reach out to the community on [Discord](https://discord.gg/PRyKn3Vbay) if you would like to join the team!
Keep track of development news:
* Join the contributor chat room on [Gitter](https://gitter.im/FreeCodeCamp/DevDocs)
* Join the devdocs chat room on [Discord](https://discord.gg/PRyKn3Vbay)
* Watch the repository on [GitHub](https://github.com/freeCodeCamp/devdocs/subscription)
* Follow [@DevDocs](https://twitter.com/DevDocs) on Twitter
@ -53,7 +53,16 @@ docker run --name devdocs -d -p 9292:9292 thibaut/devdocs
DevDocs aims to make reading and searching reference documentation fast, easy and enjoyable.
The app's main goals are to: keep load times as short as possible; improve the quality, speed, and order of search results; maximize the use of caching and other performance optimizations; maintain a clean and readable user interface; be fully functional offline; support full keyboard navigation; reduce “context switch” by using a consistent typography and design across all documentations; reduce clutter by focusing on a specific category of content (API/reference) and indexing only the minimum useful to most developers.
The app's main goals are to:
* Keep load times as short as possible
* Improve the quality, speed, and order of search results
* Maximize the use of caching and other performance optimizations
* Maintain a clean and readable user interface
* Be fully functional offline
* Support full keyboard navigation
* Reduce “context switch” by using a consistent typography and design across all documentations
* Reduce clutter by focusing on a specific category of content (API/reference) and indexing only the minimum useful to most developers.
**Note:** DevDocs is neither a programming guide nor a search engine. All our content is pulled from third-party sources and the project doesn't intend to compete with full-text search engines. Its backbone is metadata; each piece of content is identified by a unique, "obvious" and short string. Tutorials, guides and other content that don't meet this requirement are outside the scope of the project.
@ -143,32 +152,32 @@ Contributions are welcome. Please read the [contributing guidelines](./.github/C
## Related Projects
Made something cool? Feel free to open a PR to add a new row to this table!
| Project | Description | Last commit |
|---------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [Chrome web app](https://chrome.google.com/webstore/detail/devdocs/mnfehgbmkapmjnhcnbodoamcioleeooe) | Chrome Web App which adds a shortcut to DevDocs apps page. | N/A |
| [Ubuntu Touch app](https://uappexplorer.com/app/devdocsunofficial.berkes) | Application for devices running Ubuntu Touch. | N/A |
| [Sublime Text plugin](https://sublime.wbond.net/packages/DevDocs) | Sublime Text plugin to search DevDocs by selection or by input. | [![Latest GitHub commit](https://img.shields.io/github/last-commit/vitorbritto/sublime-devdocs?logo=github&label)](https://github.com/vitorbritto/sublime-devdocs) |
| [Atom plugin](https://atom.io/packages/devdocs) | Atom plugin adding the `doc` command to search DevDocs. | [![Latest GitHub commit](https://img.shields.io/github/last-commit/masnun/atom-devdocs?logo=github&label)](https://github.com/masnun/atom-devdocs) |
| [gruehle/dev-docs-viewer](https://github.com/gruehle/dev-docs-viewer) | Brackets extension for searching and viewing DevDocs content. | [![Latest GitHub commit](https://img.shields.io/github/last-commit/gruehle/dev-docs-viewer?logo=github&label)](https://github.com/gruehle/dev-docs-viewer) |
| [naquad/devdocs-shell](https://github.com/naquad/devdocs-shell) | GTK shell with Vim integration. | [![Latest GitHub commit](https://img.shields.io/github/last-commit/naquad/devdocs-shell?logo=github&label)](https://github.com/naquad/devdocs-shell) |
| [skeeto/devdocs-lookup](https://github.com/skeeto/devdocs-lookup) | Quick Emacs API lookup on DevDocs. | [![Latest GitHub commit](https://img.shields.io/github/last-commit/skeeto/devdocs-lookup?logo=github&label)](https://github.com/skeeto/devdocs-lookup) |
| [yannickglt/alfred-devdocs](https://github.com/yannickglt/alfred-devdocs) | Alfred workflow for DevDocs. | [![Latest GitHub commit](https://img.shields.io/github/last-commit/yannickglt/alfred-devdocs?logo=github&label)](https://github.com/yannickglt/alfred-devdocs) |
| [waiting-for-dev/vim-www](https://github.com/waiting-for-dev/vim-www) | Vim search plugin with DevDocs in its defaults. | [![Latest GitHub commit](https://img.shields.io/github/last-commit/waiting-for-dev/vim-www?logo=github&label)](https://github.com/waiting-for-dev/vim-www) |
| [vscode-devdocs for VS Code](https://marketplace.visualstudio.com/items?itemName=akfish.vscode-devdocs) | VS Code plugin to open and search DevDocs inside VS Code. | [![Latest GitHub commit](https://img.shields.io/github/last-commit/akfish/vscode-devdocs?logo=github&label)](https://github.com/akfish/vscode-devdocs) |
| [devdocs for VS Code](https://marketplace.visualstudio.com/items?itemName=deibit.devdocs) | VS Code plugin to open the browser to search selected text on DevDocs. | [![Latest GitHub commit](https://img.shields.io/github/last-commit/deibit/vscode-devdocs?logo=github&label)](https://github.com/deibit/vscode-devdocs) |
| [egoist/devdocs-desktop](https://github.com/egoist/devdocs-desktop) | Cross-platform desktop application for DevDocs. | [![Latest GitHub commit](https://img.shields.io/github/last-commit/egoist/devdocs-desktop?logo=github&label)](https://github.com/egoist/devdocs-desktop) |
| [qwfy/doc-browser](https://github.com/qwfy/doc-browser) | Native Linux app that supports DevDocs docsets. | [![Latest GitHub commit](https://img.shields.io/github/last-commit/qwfy/doc-browser?logo=github&label)](https://github.com/qwfy/doc-browser) |
| [hardpixel/devdocs-desktop](https://github.com/hardpixel/devdocs-desktop) | GTK3 application for DevDocs with search integrated in the headerbar. | [![Latest GitHub commit](https://img.shields.io/github/last-commit/hardpixel/devdocs-desktop?logo=github&label)](https://github.com/hardpixel/devdocs-desktop) |
| [dteoh/devdocs-macos](https://github.com/dteoh/devdocs-macos) | Native macOS application for DevDocs. | [![Latest GitHub commit](https://img.shields.io/github/last-commit/dteoh/devdocs-macos?logo=github&label)](https://github.com/dteoh/devdocs-macos) |
| [Merith-TK/devdocs_webapp_kotlin](https://github.com/Merith-TK/devdocs_webapp_kotlin) | Android application which shows DevDocs in a webview. | [![Latest GitHub commit](https://img.shields.io/github/last-commit/Merith-TK/devdocs_webapp_kotlin?logo=github&label)](https://github.com/Merith-TK/devdocs_webapp_kotlin) |
| [astoff/devdocs.el](https://github.com/astoff/devdocs.el) | Emacs viewer for DevDocs | [![Latest GitHub commit](https://img.shields.io/github/last-commit/astoff/devdocs.el?logo=github&label)](https://github.com/astoff/devdocs.el) |
| [DevDocs Tab for VS Code](https://github.com/mohamed3nan/DevDocs-Tab) | VS Code extension to search for documentation on DevDocs.io faster by displaying it in a tab inside VS Code.| [![Latest GitHub commit](https://img.shields.io/github/last-commit/mohamed3nan/DevDocs-Tab?logo=github&label)](https://github.com/mohamed3nan/DevDocs-Tab) |
Made something cool? Feel free to open a PR to add a new row to this table! You might want to discover new projects via https://github.com/topics/devdocs.
<!-- table is sorted by description -->
| Project | Description | Last commit | Stars |
| ------------------------------------------------------------------------------------------- | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| [yannickglt/alfred-devdocs](https://github.com/yannickglt/alfred-devdocs) | Alfred workflow | ![Latest GitHub commit](https://img.shields.io/github/last-commit/yannickglt/alfred-devdocs?logo=github&label) | ![GitHub stars](https://img.shields.io/github/stars/yannickglt/alfred-devdocs?logo=github&label) |
| [Merith-TK/devdocs_webapp_kotlin](https://github.com/Merith-TK/devdocs_webapp_kotlin) | Android application | ![Latest GitHub commit](https://img.shields.io/github/last-commit/Merith-TK/devdocs_webapp_kotlin?logo=github&label) | ![GitHub stars](https://img.shields.io/github/stars/Merith-TK/devdocs_webapp_kotlin?logo=github&label) |
| [gruehle/dev-docs-viewer](https://github.com/gruehle/dev-docs-viewer) | Brackets extension | ![Latest GitHub commit](https://img.shields.io/github/last-commit/gruehle/dev-docs-viewer?logo=github&label) | ![GitHub stars](https://img.shields.io/github/stars/gruehle/dev-docs-viewer?logo=github&label) |
| [egoist/devdocs-desktop](https://github.com/egoist/devdocs-desktop) | Electron application | ![Latest GitHub commit](https://img.shields.io/github/last-commit/egoist/devdocs-desktop?logo=github&label) | ![GitHub stars](https://img.shields.io/github/stars/egoist/devdocs-desktop?logo=github&label) |
| [skeeto/devdocs-lookup](https://github.com/skeeto/devdocs-lookup) | Emacs function | ![Latest GitHub commit](https://img.shields.io/github/last-commit/skeeto/devdocs-lookup?logo=github&label) | ![GitHub stars](https://img.shields.io/github/stars/skeeto/devdocs-lookup?logo=github&label) |
| [astoff/devdocs.el](https://github.com/astoff/devdocs.el) | Emacs viewer | ![Latest GitHub commit](https://img.shields.io/github/last-commit/astoff/devdocs.el?logo=github&label) | ![GitHub stars](https://img.shields.io/github/stars/astoff/devdocs.el?logo=github&label) |
| [naquad/devdocs-shell](https://github.com/naquad/devdocs-shell) | GTK shell with Vim integration | ![Latest GitHub commit](https://img.shields.io/github/last-commit/naquad/devdocs-shell?logo=github&label) | ![GitHub stars](https://img.shields.io/github/stars/naquad/devdocs-shell?logo=github&label) |
| [hardpixel/devdocs-desktop](https://github.com/hardpixel/devdocs-desktop) | GTK application | ![Latest GitHub commit](https://img.shields.io/github/last-commit/hardpixel/devdocs-desktop?logo=github&label) | ![GitHub stars](https://img.shields.io/github/stars/hardpixel/devdocs-desktop?logo=github&label) |
| [qwfy/doc-browser](https://github.com/qwfy/doc-browser) | Linux application | ![Latest GitHub commit](https://img.shields.io/github/last-commit/qwfy/doc-browser?logo=github&label) | ![GitHub stars](https://img.shields.io/github/stars/qwfy/doc-browser?logo=github&label) |
| [dteoh/devdocs-macos](https://github.com/dteoh/devdocs-macos) | macOS application | ![Latest GitHub commit](https://img.shields.io/github/last-commit/dteoh/devdocs-macos?logo=github&label) | ![GitHub stars](https://img.shields.io/github/stars/dteoh/devdocs-macos?logo=github&label) |
| [Sublime Text plugin](https://sublime.wbond.net/packages/DevDocs) | Sublime Text plugin | ![Latest GitHub commit](https://img.shields.io/github/last-commit/vitorbritto/sublime-devdocs?logo=github&label) | ![GitHub stars](https://img.shields.io/github/stars/vitorbritto/sublime-devdocs?logo=github&label) |
| [mohamed3nan/DevDocs-Tab](https://github.com/mohamed3nan/DevDocs-Tab) | VS Code extension (view as tab) | ![Latest GitHub commit](https://img.shields.io/github/last-commit/mohamed3nan/DevDocs-Tab?logo=github&label) | ![GitHub stars](https://img.shields.io/github/stars/mohamed3nan/DevDocs-Tab?logo=github&label) |
| [deibit/vscode-devdocs](https://marketplace.visualstudio.com/items?itemName=deibit.devdocs) | VS Code extension (open the browser) | ![Latest GitHub commit](https://img.shields.io/github/last-commit/deibit/vscode-devdocs?logo=github&label) | ![GitHub stars](https://img.shields.io/github/stars/deibit/vscode-devdocs?logo=github&label) |
| [mdh34/quickDocs](https://github.com/mdh34/quickDocs) | Vala/Python based viewer | ![Latest GitHub commit](https://img.shields.io/github/last-commit/mdh34/quickDocs?logo=github&label) | ![GitHub stars](https://img.shields.io/github/stars/mdh34/quickDocs?logo=github&label) |
| [romainl/vim-devdocs](https://github.com/romainl/vim-devdocs) | Vim plugin | ![Latest GitHub commit](https://img.shields.io/github/last-commit/romainl/vim-devdocs?logo=github&label) | ![GitHub stars](https://img.shields.io/github/stars/romainl/vim-devdocs?logo=github&label) |
| [waiting-for-dev/vim-www](https://github.com/waiting-for-dev/vim-www) | Vim plugin | ![Latest GitHub commit](https://img.shields.io/github/last-commit/waiting-for-dev/vim-www?logo=github&label) | ![GitHub stars](https://img.shields.io/github/stars/waiting-for-dev/vim-www?logo=github&label) |
## Copyright / License
Copyright 20132021 Thibaut Courouble and [other contributors](https://github.com/freeCodeCamp/devdocs/graphs/contributors)
Copyright 20132023 Thibaut Courouble and [other contributors](https://github.com/freeCodeCamp/devdocs/graphs/contributors)
This software is licensed under the terms of the Mozilla Public License v2.0. See the [COPYRIGHT](./COPYRIGHT) and [LICENSE](./LICENSE) files.
@ -178,4 +187,4 @@ We also wish that any documentation file generated using this software be attrib
## Questions?
If you have any questions, please feel free to ask them on the contributor chat room on [Gitter](https://gitter.im/FreeCodeCamp/DevDocs).
If you have any questions, please feel free to ask them on the contributor chat room on [Discord](https://discord.gg/PRyKn3Vbay).

@ -12,6 +12,7 @@ class app.Settings
'layout'
'size'
'tips'
'noAutofocus'
'autoInstall'
'spaceScroll'
'spaceTimeout'

@ -1,5 +1,5 @@
###
* Copyright 2013-2021 Thibaut Courouble and other contributors
* Copyright 2013-2023 Thibaut Courouble and other contributors
*
* This source code is licensed under the terms of the Mozilla
* Public License, v. 2.0, a copy of which may be obtained at:

@ -61,6 +61,7 @@ class app.models.Entry extends app.Model
'julia': 'jl'
'jquery': '$'
'knockout.js': 'ko'
'kubernetes': 'k8s'
'less': 'ls'
'lodash': '_'
'löve': 'love'

@ -1,6 +1,54 @@
[
[
"2021-01-12",
"2022-12-20",
"New documentations: <a href=\"/qunit/\">QUnit</a>, <a href=\"/wagtail/\">Wagtail</a>"
],
[
"2022-11-04",
"New documentation: <a href=\"/vueuse/\">VueUse</a>"
],
[
"2022-10-10",
"New documentation: <a href=\"/astro/\">Astro</a>"
],
[
"2022-10-09",
"New documentations: <a href=\"/fastapi/\">FastAPI</a>, <a href=\"/vitest/\">Vitest</a>"
],
[
"2022-10-02",
"New documentation: <a href=\"/svelte/\">Svelte</a>"
],
[
"2022-09-21",
"Added HTTP/3 to <a href=\"/http/\">HTTP</a>"
],
[
"2022-09-06",
"New documentation: <a href=\"/date_fns/\">date-fns</a>"
],
[
"2022-08-27",
"New documentations: <a href=\"/sanctuary/\">Sanctuary</a>, <a href=\"/requests/\">Requests</a>, <a href=\"/axios/\">Axios</a>"
],
[
"2022-05-03",
"New documentations: <a href=\"/kubernetes/\">Kubernetes</a>, <a href=\"/kubectl/\">Kubectl</a>"
],
[
"2022-04-25",
"New documentation: <a href=\"/nix/\">Nix</a>"
],
[
"2022-03-31",
"New documentation: <a href=\"/eigen3/\">Eigen3</a>"
],
[
"2022-02-21",
"New documentation: <a href=\"/tailwindcss/\">Tailwind CSS</a>"
],
[
"2022-01-12",
"New documentation: <a href=\"/react_router/\">React Router</a>"
],
[

@ -1,4 +1,9 @@
app.templates.aboutPage = -> """
app.templates.aboutPage = ->
all_docs = app.docs.all().concat(app.disabledDocs.all()...)
# de-duplicate docs by doc.name
docs = []
docs.push doc for doc in all_docs when not (docs.find (d) -> d.name == doc.name)
"""
<nav class="_toc" role="directory">
<h3 class="_toc-title">Table of Contents</h3>
<ul class="_toc-list">
@ -17,12 +22,12 @@ app.templates.aboutPage = -> """
<ul>
<li>Follow <a href="https://twitter.com/DevDocs">@DevDocs</a> on Twitter
<li>Watch the repository on <a href="https://github.com/freeCodeCamp/devdocs/subscription">GitHub</a> <iframe class="_github-btn" src="https://ghbtns.com/github-btn.html?user=freeCodeCamp&repo=devdocs&type=watch&count=true" allowtransparency="true" frameborder="0" scrolling="0" width="100" height="20" tabindex="-1"></iframe>
<li>Join the <a href="https://gitter.im/FreeCodeCamp/DevDocs">Gitter</a> chat room
<li>Join the <a href="https://discord.gg/PRyKn3Vbay">Discord</a> chat room
</ul>
<h2 class="_block-heading" id="copyright">Copyright and License</h2>
<p class="_note">
<strong>Copyright 2013&ndash;2021 Thibaut Courouble and <a href="https://github.com/freeCodeCamp/devdocs/graphs/contributors">other contributors</a></strong><br>
<strong>Copyright 2013&ndash;2023 Thibaut Courouble and <a href="https://github.com/freeCodeCamp/devdocs/graphs/contributors">other contributors</a></strong><br>
This software is licensed under the terms of the Mozilla Public License v2.0.<br>
You may obtain a copy of the source code at <a href="https://github.com/freeCodeCamp/devdocs">github.com/freeCodeCamp/devdocs</a>.<br>
For more information, see the <a href="https://github.com/freeCodeCamp/devdocs/blob/main/COPYRIGHT">COPYRIGHT</a>
@ -30,8 +35,6 @@ app.templates.aboutPage = -> """
<h2 class="_block-heading" id="plugins">Plugins and Extensions</h2>
<ul>
<li><a href="https://chrome.google.com/webstore/detail/devdocs/mnfehgbmkapmjnhcnbodoamcioleeooe">Chrome web app</a>
<li><a href="https://github.com/egoist/devdocs-app">Desktop app</a>
<li><a href="https://sublime.wbond.net/packages/DevDocs">Sublime Text package</a>
<li><a href="https://atom.io/packages/devdocs">Atom package</a>
<li><a href="https://marketplace.visualstudio.com/items?itemName=deibit.devdocs">Visual Studio Code extension</a>
@ -44,7 +47,7 @@ app.templates.aboutPage = -> """
<dt>Where can I suggest new docs and features?
<dd>You can suggest and vote for new docs on the <a href="https://trello.com/b/6BmTulfx/devdocs-documentation">Trello board</a>.<br>
If you have a specific feature request, add it to the <a href="https://github.com/freeCodeCamp/devdocs/issues">issue tracker</a>.<br>
Otherwise, come talk to us in the <a href="https://gitter.im/FreeCodeCamp/DevDocs">Gitter</a> chat room.
Otherwise, come talk to us in the <a href="https://discord.gg/PRyKn3Vbay">Discord</a> chat room.
<dt>Where can I report bugs?
<dd>In the <a href="https://github.com/freeCodeCamp/devdocs/issues">issue tracker</a>. Thanks!
</dl>
@ -63,9 +66,15 @@ app.templates.aboutPage = -> """
<table class="_credits">
<tr>
<th>Documentation
<th>Copyright
<th>License
#{("<tr><td>#{c[0]}<td>&copy; #{c[1]}<td><a href=\"#{c[3]}\">#{c[2]}</a>" for c in credits).join('')}
<th>Copyright/License
<th>Source code
#{(
"<tr>
<td><a href=\"#{doc.links?.home}\">#{doc.name}</a></td>
<td>#{doc.attribution}</td>
<td><a href=\"#{doc.links?.code}\">Source code</a></td>
</tr>" for doc in docs
).join('')}
</table>
</div>
@ -80,862 +89,3 @@ app.templates.aboutPage = -> """
<li>If you have any questions regarding privacy, please email <a href="mailto:privacy@freecodecamp.org">privacy@freecodecamp.org</a>.
</ul>
"""
credits = [
[
'Angular',
'2010-2021 Google, Inc.',
'CC BY',
'https://creativecommons.org/licenses/by/4.0/'
], [
'Angular.js',
'2010-2020 Google, Inc.',
'CC BY 3.0',
'https://creativecommons.org/licenses/by/3.0/'
], [
'Ansible',
'2012-2018 Michael DeHaan<br>&copy; 20182021 Red Hat, Inc.',
'GPLv3',
'https://raw.githubusercontent.com/ansible/ansible/devel/COPYING'
], [
'Apache HTTP Server<br>Apache Pig',
'2018 The Apache Software Foundation<br>Apache and the Apache feather logo are trademarks of The Apache Software Foundation.',
'Apache',
'https://www.apache.org/licenses/LICENSE-2.0'
], [
'Async',
'2010-2018 Caolan McMahon',
'MIT',
'https://raw.githubusercontent.com/caolan/async/master/LICENSE'
], [
'Babel',
'2014-present Sebastian McKenzie',
'MIT',
'https://raw.githubusercontent.com/babel/babel/master/LICENSE'
], [
'Backbone.js',
'2010-2019 Jeremy Ashkenas, DocumentCloud',
'MIT',
'https://raw.githubusercontent.com/jashkenas/backbone/master/LICENSE'
], [
'Bash',
'2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.',
'GFDL',
'https://www.gnu.org/licenses/fdl-1.3.en.html'
], [
'Bluebird',
'2013-2018 Petka Antonov',
'MIT',
'https://raw.githubusercontent.com/petkaantonov/bluebird/master/LICENSE'
], [
'Bootstrap',
'2011-2021 Twitter, Inc.<br>2011-2021 The Bootstrap Authors',
'CC BY',
'https://creativecommons.org/licenses/by/3.0/'
], [
'Bottle',
'2009-2017 Marcel Hellkamp',
'MIT',
'https://raw.githubusercontent.com/bottlepy/bottle/master/LICENSE'
], [
'Bower',
'2018 Bower contributors',
'MIT',
'https://github.com/bower/bower.github.io/blob/1057905c18d899106f91372e6cca7ef54a91d60f/package.json#L20'
], [
'C<br>C++',
'cppreference.com',
'CC BY-SA',
'http://en.cppreference.com/w/Cppreference:Copyright/CC-BY-SA'
], [
'CakePHP',
'2005-present The Cake Software Foundation, Inc.',
'MIT',
'https://raw.githubusercontent.com/cakephp/cakephp/master/LICENSE'
], [
'Chai',
'2017 Chai.js Assertion Library',
'MIT',
'https://raw.githubusercontent.com/chaijs/chai/master/LICENSE'
], [
'Chef&trade;',
'Chef Software, Inc.',
'CC BY',
'https://raw.githubusercontent.com/chef/chef-web-docs-2016/master/LICENSE'
], [
'Clojure',
'Rich Hickey',
'EPL',
'https://github.com/clojure/clojure/blob/master/epl-v10.html'
], [
'CMake',
'2000-2019 Kitware, Inc. and Contributors',
'BSD',
'https://cmake.org/licensing/'
], [
'Codeception',
'2011 Michael Bodnarchuk and contributors',
'MIT',
'https://raw.githubusercontent.com/Codeception/Codeception/master/LICENSE'
], [
'CodeceptJS',
'2015 DavertMik',
'MIT',
'https://raw.githubusercontent.com/Codeception/CodeceptJS/master/LICENSE'
], [
'CodeIgniter',
'2014-2021 British Columbia Institute of Technology',
'MIT',
'https://raw.githubusercontent.com/bcit-ci/CodeIgniter/develop/license.txt'
], [
'CoffeeScript',
'2009-2021 Jeremy Ashkenas',
'MIT',
'https://raw.githubusercontent.com/jashkenas/coffeescript/master/LICENSE'
], [
'Composer',
'Nils Adermann, Jordi Boggiano',
'MIT',
'https://raw.githubusercontent.com/composer/composer/master/LICENSE'
], [
'Cordova',
'2012, 2013, 2015 The Apache Software Foundation',
'Apache',
'https://raw.githubusercontent.com/apache/cordova-docs/master/LICENSE'
], [
'Crystal',
'2012-2022 Manas Technology Solutions',
'Apache',
'https://raw.githubusercontent.com/crystal-lang/crystal/master/LICENSE'
], [
'CSS<br>DOM<br>HTTP<br>HTML<br>JavaScript<br>SVG<br>XPath',
'2005-2021 MDN contributors',
'CC BY-SA',
'https://creativecommons.org/licenses/by-sa/2.5/'
], [
'Cypress',
'2017 Cypress.io',
'MIT',
'https://raw.githubusercontent.com/cypress-io/cypress-documentation/develop/LICENSE.md'
], [
'D',
'1999-2021 The D Language Foundation',
'Boost',
'https://raw.githubusercontent.com/dlang/phobos/master/LICENSE_1_0.txt'
], [
'D3.js',
'2010-2021 Michael Bostock',
'BSD',
'https://raw.githubusercontent.com/d3/d3/master/LICENSE'
], [
'Dart',
'2012 the Dart project authors',
'CC BY-SA',
'https://creativecommons.org/licenses/by-sa/4.0/'
], [
'Deno',
'20182021 the Deno authors',
'MIT',
'https://raw.githubusercontent.com/denoland/manual/main/LICENSE'
], [
'Django',
'Django Software Foundation and individual contributors',
'BSD',
'https://raw.githubusercontent.com/django/django/master/LICENSE'
], [
'Django REST Framework',
'2011-present Encode OSS Ltd.',
'BSD',
'https://raw.githubusercontent.com/encode/django-rest-framework/master/LICENSE.md'
], [
'Docker',
'2019 Docker, Inc.<br>Docker and the Docker logo are trademarks of Docker, Inc.',
'Apache',
'https://raw.githubusercontent.com/docker/docker.github.io/master/LICENSE'
], [
'Dojo',
'2005-2017 JS Foundation',
'BSD + AFL',
'http://dojotoolkit.org/license.html'
], [
'Drupal',
'2001-2015 by the original authors<br>Drupal is a registered trademark of Dries Buytaert.',
'GPLv2',
'https://api.drupal.org/api/drupal/LICENSE.txt'
], [
'Electron',
'GitHub Inc.',
'MIT',
'https://raw.githubusercontent.com/electron/electron/master/LICENSE'
], [
'Elisp',
'1990-1996, 1998-2021 Free Software Foundation, Inc.',
'GPLv3',
'https://www.gnu.org/licenses/gpl-3.0.html'
], [
'Elixir',
'2012 Plataformatec',
'Apache',
'https://raw.githubusercontent.com/elixir-lang/elixir/master/LICENSE'
], [
'Ember.js',
'2020 Yehuda Katz, Tom Dale and Ember.js contributors',
'MIT',
'https://raw.githubusercontent.com/emberjs/ember.js/master/LICENSE'
], [
'Enzyme',
'2015 Airbnb, Inc.',
'MIT',
'https://raw.githubusercontent.com/airbnb/enzyme/master/LICENSE.md'
], [
'Erlang',
'2010-2021 Ericsson AB',
'Apache',
'https://raw.githubusercontent.com/erlang/otp/maint/LICENSE.txt'
], [
'esbulid',
'2020 Evan Wallace',
'MIT',
'https://raw.githubusercontent.com/evanw/esbuild/blob/master/LICENSE.md'
], [
'ESLint',
'OpenJS Foundation and other contributors',
'MIT',
'https://raw.githubusercontent.com/eslint/eslint/master/LICENSE'
], [
'Express',
'2017 StrongLoop, IBM, and other expressjs.com contributors.',
'CC BY-SA',
'https://raw.githubusercontent.com/expressjs/expressjs.com/gh-pages/LICENSE.md'
], [
'Falcon',
'2019 by Falcon contributors',
'Apache',
'https://raw.githubusercontent.com/falconry/falcon/master/LICENSE'
], [
'Fish',
'20052009 Axel Liljencrantz, 20092021 fish-shell contributors',
'GPLv2',
'https://fishshell.com/docs/current/license.html'
], [
'Flask',
'2007-2021 Pallets',
'BSD',
'https://github.com/pallets/flask/blob/master/LICENSE.rst'
], [
'GCC<br>GNU Fortran<br>GNU Make',
'Free Software Foundation',
'GFDL',
'https://www.gnu.org/licenses/fdl-1.3.en.html'
], [
'Git',
'2012-2021 Scott Chacon and others',
'MIT',
'https://raw.githubusercontent.com/git/git-scm.com/master/MIT-LICENSE.txt'
], [
'GnuCOBOL',
'Free Software Foundation',
'GFDL',
'https://www.gnu.org/licenses/fdl-1.3.en.html'
], [
'Gnuplot',
'Copyright 1986 - 1993, 1998, 2004 Thomas Williams, Colin Kelley',
'gnuplot license',
'https://sourceforge.net/p/gnuplot/gnuplot-main/ci/master/tree/Copyright'
], [
'Go',
'Google, Inc.',
'CC BY',
'https://creativecommons.org/licenses/by/3.0/'
], [
'Godot',
'2014-2021 Juan Linietsky, Ariel Manzur, Godot Engine contributors',
'MIT',
'https://raw.githubusercontent.com/godotengine/godot/master/LICENSE.txt'
], [
'Graphite',
'2008-2012 Chris Davis<br>&copy; 2011-2016 The Graphite Project',
'Apache',
'https://raw.githubusercontent.com/graphite-project/graphite-web/master/LICENSE'
], [
'Groovy',
'2003-2020 The Apache Software Foundation',
'Apache',
'https://github.com/apache/groovy-website/blob/asf-site/LICENSE'
], [
'Grunt',
'GruntJS Team',
'MIT',
'https://github.com/gruntjs/grunt-docs/blob/master/package.json#L10'
], [
'GTK',
'The GNOME Project',
'LGPLv2.1+',
'https://gitlab.gnome.org/GNOME/gtk/-/blob/master/COPYING'
], [
'Handlebars',
'2011-2017 Yehuda Katz',
'MIT',
'https://raw.githubusercontent.com/wycats/handlebars.js/master/LICENSE'
], [
'HAProxy',
'2021 Willy Tarreau, HAProxy contributors',
'GPLv2',
'https://raw.githubusercontent.com/haproxy/haproxy/master/LICENSE'
], [
'Haskell',
'The University of Glasgow',
'BSD',
'https://www.haskell.org/ghc/license'
], [
'Haxe',
'2005-2018 Haxe Foundation',
'MIT',
'https://haxe.org/foundation/open-source.html'
], [
'Homebrew',
'2009-present Homebrew contributors',
'BSD',
'https://raw.githubusercontent.com/Homebrew/brew/master/LICENSE.txt'
], [
'i3',
'2009, Michael Stapelberg and contributors',
'BSD',
'https://raw.githubusercontent.com/i3/i3/next/LICENSE'
], [
'Immutable.js',
'2014present Lee Byron and other contributors',
'BSD',
'https://github.com/immutable-js/immutable-js/blob/main/LICENSE'
], [
'InfluxData',
'2015 InfluxData, Inc.',
'MIT',
'https://github.com/influxdata/docs.influxdata.com/blob/master/LICENSE'
], [
'Jasmine',
'2008-2019 Pivotal Labs',
'MIT',
'https://raw.githubusercontent.com/jasmine/jasmine/main/MIT.LICENSE'
], [
'Jekyll',
'2020 Jekyll Core Team and contributors',
'MIT',
'https://raw.githubusercontent.com/jekyll/jekyll/master/LICENSE'
], [
'Jest',
'2021 Facebook, Inc.',
'MIT',
'https://raw.githubusercontent.com/facebook/jest/master/LICENSE'
], [
'Jinja',
'2007-2021 Pallets',
'BSD',
'https://github.com/pallets/jinja/blob/master/LICENSE.rst'
], [
'jq',
'Stephen Dolan',
'CC-BY-3.0',
'https://github.com/stedolan/jq/blob/master/COPYING#L24-L28'
], [
'jQuery',
'Packt Publishing<br>&copy; jQuery Foundation and other contributors',
'MIT',
'https://raw.githubusercontent.com/jquery/api.jquery.com/master/LICENSE.txt'
], [
'jQuery Mobile',
'jQuery Foundation and other contributors',
'MIT',
'https://raw.githubusercontent.com/jquery/api.jquerymobile.com/master/LICENSE.txt'
], [
'jQuery UI',
'jQuery Foundation and other contributors',
'MIT',
'https://raw.githubusercontent.com/jquery/api.jqueryui.com/master/LICENSE.txt'
], [
'JSDoc',
'2011-2017 the contributors to the JSDoc 3 documentation project',
'CC BY-SA',
'https://raw.githubusercontent.com/jsdoc3/jsdoc3.github.com/master/LICENSE'
], [
'Julia',
'2009-2021 Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors',
'MIT',
'https://raw.githubusercontent.com/JuliaLang/julia/master/LICENSE.md'
], [
'Knockout.js',
'Steven Sanderson, the Knockout.js team, and other contributors',
'MIT',
'https://raw.githubusercontent.com/knockout/knockout/master/LICENSE'
], [
'Koa',
'2020 Koa contributors',
'MIT',
'https://raw.githubusercontent.com/koajs/koa/master/LICENSE'
], [
'Kotlin',
'2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors',
'Apache',
'https://raw.githubusercontent.com/JetBrains/kotlin/master/license/LICENSE.txt'
], [
'Laravel',
'Taylor Otwell',
'MIT',
'https://raw.githubusercontent.com/laravel/framework/master/LICENSE.txt'
], [
'LaTeX',
'Karl Berry',
'Public Domain',
'https://ctan.org/pkg/latex2e-help-texinfo/'
], [
'Leaflet',
'2010-2021 Vladimir Agafonkin<br>&copy; 2010-2011, CloudMade<br>Maps &copy; OpenStreetMap contributors.',
'BSD',
'https://raw.githubusercontent.com/Leaflet/Leaflet/master/LICENSE'
], [
'Less',
'2009-2020 The Core Less Team',
'CC BY',
'https://creativecommons.org/licenses/by/3.0/'
], [
'Liquid',
'2005, 2006 Tobias Luetke',
'MIT',
'https://raw.githubusercontent.com/Shopify/liquid/master/LICENSE'
], [
'Lo-Dash',
'JS Foundation and other contributors',
'MIT',
'https://raw.githubusercontent.com/lodash/lodash/master/LICENSE'
], [
'Lua',
'19942020 Lua.org, PUC-Rio',
'MIT',
'http://www.lua.org/license.html'
], [
'LÖVE',
'2006-2020 LÖVE Development Team',
'GFDL',
'http://www.gnu.org/copyleft/fdl.html'
], [
'MariaDB',
'2019 MariaDB',
'CC BY-SA & GFDL',
'https://mariadb.com/kb/en/library/documentation/+license/'
], [
'Marionette.js',
'2017 Muted Solutions, LLC',
'MIT',
'https://mutedsolutions.mit-license.org/'
], [
'Markdown',
'2004 John Gruber',
'BSD',
'https://daringfireball.net/projects/markdown/license'
], [
'Matplotlib',
'2012-2021 Matplotlib Development Team. All rights reserved.',
'Custom',
'https://raw.githubusercontent.com/matplotlib/matplotlib/master/LICENSE/LICENSE'
], [
'Meteor',
'2011-2017 Meteor Development Group, Inc.',
'MIT',
'https://raw.githubusercontent.com/meteor/meteor/master/LICENSE'
], [
'Minitest',
'Ryan Davis, seattle.rb',
'MIT',
'https://github.com/seattlerb/minitest/blob/master/README.rdoc#license'
], [
'Mocha',
'2011-2021 JS Foundation and contributors',
'CC BY',
'https://creativecommons.org/licenses/by/4.0/'
], [
'Modernizr',
'2009-2020 The Modernizr team',
'MIT',
'https://modernizr.com/license/'
], [
'Moment.js',
'JS Foundation and other contributors',
'MIT',
'https://raw.githubusercontent.com/moment/moment/master/LICENSE'
], [
'Mongoose',
'2010 LearnBoost',
'MIT',
'https://github.com/LearnBoost/mongoose/blob/master/README.md#license'
], [
'nginx',
'2002-2021 Igor Sysoev<br>&copy; 2011-2021 Nginx, Inc.',
'BSD',
'http://nginx.org/LICENSE'
], [
'nginx / Lua Module',
'2009-2017 Xiaozhe Wang (chaoslawful)<br>&copy; 2009-2018 Yichun "agentzh" Zhang (章亦春), OpenResty Inc.',
'BSD',
'https://github.com/openresty/lua-nginx-module#copyright-and-license'
], [
'Nim',
'2006-2021 Andreas Rumpf',
'MIT',
'https://github.com/nim-lang/Nim#license'
], [
'Node.js',
'Joyent, Inc. and other Node contributors<br>Node.js is a trademark of Joyent, Inc.',
'MIT',
'https://raw.githubusercontent.com/nodejs/node/master/LICENSE'
], [
'Nokogiri',
'20082021 Aaron Patterson, Mike Dalessio, Charles Nutter, Sergio Arbeo, Patrick Mahoney, Yoko Harada, Akinori MUSHA, John Shahid, Lars Kanis',
'MIT',
'https://raw.githubusercontent.com/sparklemotion/nokogiri/master/LICENSE.md'
], [
'npm',
'npm, Inc. and Contributors<br>npm is a trademark of npm, Inc.',
'npm',
'https://raw.githubusercontent.com/npm/npm/master/LICENSE'
], [
'NumPy',
'2005-2021 NumPy Developers',
'BSD',
'https://raw.githubusercontent.com/numpy/numpy/master/LICENSE.txt'
], [
'OCaml',
'1995-2021 INRIA',
'CC BY-SA',
'https://ocaml.org/docs/'
], [
'Octave',
'1996-2018 John W. Eaton',
'Octave',
'https://octave.org/doc/interpreter/'
], [
'OpenJDK',
'1993, 2021, Oracle and/or its affiliates. All rights reserved.<br>Licensed under the GNU General Public License, version 2, with the Classpath Exception.<br>Various third party code in OpenJDK is licensed under different licenses.<br>Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.',
'GPLv2',
'http://openjdk.java.net/legal/gplv2+ce.html'
], [
'OpenTSDB',
'2010-2016 The OpenTSDB Authors',
'LGPLv2.1',
'https://raw.githubusercontent.com/OpenTSDB/opentsdb.net/gh-pages/COPYING.LESSER'
], [
'Padrino',
'2010-2020 Padrino',
'MIT',
'https://raw.githubusercontent.com/padrino/padrino-framework/master/padrino/LICENSE.txt'
], [
'pandas',
'2008-2021, AQR Capital Management, LLC, Lambda Foundry, Inc. and PyData Development Team',
'BSD',
'https://raw.githubusercontent.com/pydata/pandas/master/LICENSE'
], [
'Perl',
'1993-2021 Larry Wall and others',
'GPLv1',
'https://perldoc.perl.org/index-licence.html'
], [
'Phalcon',
'2011-2017 Phalcon Framework Team',
'CC BY',
'https://docs.phalconphp.com/en/latest/reference/license.html'
], [
'Phaser',
'2016 Richard Davey, Photon Storm Ltd.',
'MIT',
'https://raw.githubusercontent.com/photonstorm/phaser/master/license.txt'
], [
'Phoenix',
'2014 Chris McCord',
'MIT',
'https://raw.githubusercontent.com/phoenixframework/phoenix/master/LICENSE.md'
], [
'PHP',
'1997-2021 The PHP Documentation Group',
'CC BY',
'https://secure.php.net/manual/en/copyright.php'
], [
'PHPUnit',
'2005-2017 Sebastian Bergmann',
'CC BY',
'https://creativecommons.org/licenses/by/3.0/'
], [
'PointCloudLibrary',
'20092012, Willow Garage, Inc.<br>&copy; 2012, Open Perception, Inc.',
'BSD',
'https://raw.githubusercontent.com/PointCloudLibrary/pcl/master/LICENSE.txt'
], [
'Pony',
'2016-2020, The Pony Developers & 2014-2015, Causality Ltd.',
'BSD',
'https://raw.githubusercontent.com/ponylang/ponyc/master/LICENSE'
], [
'PostgreSQL',
'1996-2021 The PostgreSQL Global Development Group<br>&copy; 1994 The Regents of the University of California',
'PostgreSQL',
'https://www.postgresql.org/about/licence/'
], [
'Prettier',
'James Long and contributors',
'MIT',
'https://raw.githubusercontent.com/prettier/prettier/main/LICENSE '
], [
'Puppeteer',
'2021 Google Inc',
'Apache',
'https://raw.githubusercontent.com/puppeteer/puppeteer/master/LICENSE'
], [
'Pygame',
'Pygame Developers',
'LGPLv2.1',
'https://raw.githubusercontent.com/pygame/pygame/master/LICENSE'
], [
'Python',
'2001-2021 Python Software Foundation<br>Python is a trademark of the Python Software Foundation.',
'PSFL',
'https://docs.python.org/3/license.html'
], [
'PyTorch',
'2019 Torch Contributors',
'BSD',
'https://raw.githubusercontent.com/pytorch/pytorch/master/LICENSE'
], [
'Q',
'2009-2017 Kristopher Michael Kowal',
'MIT',
'https://raw.githubusercontent.com/kriskowal/q/master/LICENSE'
], [
'Qt',
'2012-2018 The Qt Company Ltd',
'GFDL',
'https://doc.qt.io/qt-5/licensing.html'
], [
'R',
'19992012 R Foundation for Statistical Computing',
'GPL',
'https://svn.r-project.org/R/trunk/COPYING'
], [
'Ramda',
'2013-2020 Scott Sauyet and Michael Hurley',
'MIT',
'https://raw.githubusercontent.com/ramda/ramda/master/LICENSE.txt'
], [
'React, React Native, Flow, Relay',
'Facebook Inc. and its affiliates',
'MIT',
'https://raw.githubusercontent.com/facebook/react/master/LICENSE'
], [
'React Bootstrap',
'2014-present Stephen J. Collings, Matthew Honnibal, Pieter Vanderwerff',
'MIT',
'https://raw.githubusercontent.com/react-bootstrap/react-bootstrap/master/LICENSE'
], [
'React Router',
'React Training 2015-2019<br>Remix Software 2020-2021',
'MIT',
'https://raw.githubusercontent.com/remix-run/react-router/main/LICENSE.md'
], [
'ReactiveX',
'ReactiveX contributors',
'Apache',
'https://raw.githubusercontent.com/ReactiveX/reactivex.github.io/develop/LICENSE'
], [
'Redis',
'2009-2020 Salvatore Sanfilippo',
'CC BY-SA',
'https://creativecommons.org/licenses/by-sa/4.0/'
], [
'Redux',
'2015-2021 Dan Abramov',
'MIT',
'https://raw.githubusercontent.com/reactjs/redux/master/LICENSE.md'
], [
'RequireJS',
'jQuery Foundation and other contributors',
'MIT',
'https://raw.githubusercontent.com/requirejs/requirejs/master/LICENSE'
], [
'RethinkDB',
'RethinkDB contributors',
'CC BY-SA',
'https://raw.githubusercontent.com/rethinkdb/docs/master/LICENSE'
], [
'Ruby',
'1993-2017 Yukihiro Matsumoto',
'Ruby',
'https://www.ruby-lang.org/en/about/license.txt'
], [
'Ruby on Rails',
'2004-2021 David Heinemeier Hansson<br>Rails, Ruby on Rails, and the Rails logo are trademarks of David Heinemeier Hansson.',
'MIT',
'https://raw.githubusercontent.com/rails/rails/master/activerecord/MIT-LICENSE'
], [
'Rust',
'2010 The Rust Project Developers',
'MIT',
'https://raw.githubusercontent.com/rust-lang/book/master/LICENSE-MIT'
], [
'RxJS',
'2015-2021 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors',
'Apache',
'https://raw.githubusercontent.com/ReactiveX/rxjs/master/LICENSE.txt'
], [
'Salt Stack',
'2021 SaltStack',
'Apache',
'https://raw.githubusercontent.com/saltstack/salt/develop/LICENSE'
], [
'Sass',
'2006-2020 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein',
'MIT',
'https://raw.githubusercontent.com/sass/sass/stable/MIT-LICENSE'
], [
'Scala',
'2002-2019 EPFL, with contributions from Lightbend',
'Apache',
'https://raw.githubusercontent.com/scala/scala-lang/master/license.md'
], [
'scikit-image',
'2019 the scikit-image team',
'BSD',
'https://scikit-image.org/docs/dev/license.html'
], [
'scikit-learn',
'2007-2020 The scikit-learn developers',
'BSD',
'https://raw.githubusercontent.com/scikit-learn/scikit-learn/master/COPYING'
], [
'Sequelize',
'2014—present Sequelize contributors',
'MIT',
'https://raw.githubusercontent.com/sequelize/sequelize/master/LICENSE'
], [
'Sinon',
'2010-2021 Christian Johansen',
'BSD',
'https://raw.githubusercontent.com/sinonjs/sinon/master/LICENSE'
], [
'Socket.io',
'2014-2018 Automattic',
'MIT',
'https://raw.githubusercontent.com/Automattic/socket.io/master/LICENSE'
], [
'Spring Boot',
'2002-2021 Pivotal, Inc. All Rights Reserved.',
'Apache License 2.0',
'https://raw.githubusercontent.com/spring-projects/spring-boot/master/LICENSE.txt'
], [
'SQLite',
'n/a',
'Public Domain',
'https://sqlite.org/copyright.html'
], [
'Statsmodels',
'2009-2012 Statsmodels Developers<br>&copy; 2006-2008 Scipy Developers<br>&copy; 2006 Jonathan E. Taylor',
'BSD',
'https://raw.githubusercontent.com/statsmodels/statsmodels/master/LICENSE.txt'
], [
'Symfony',
'2004-2017 Fabien Potencier',
'MIT',
'https://symfony.com/doc/current/contributing/code/license.html'
], [
'Tcl/Tk',
'The Regents of the University of California, Sun Microsystems, Inc., Scriptics Corporation, and other parties',
'Tcl/Tk',
'http://tcl.tk/software/tcltk/license.html'
], [
'TensorFlow',
'2020 The TensorFlow Authors',
'CC BY',
'https://creativecommons.org/licenses/by/4.0/'
], [
'Terraform',
'2018 HashiCorp',
'MPL',
'https://raw.githubusercontent.com/hashicorp/terraform-website/master/LICENSE.md'
], [
'Trio',
'2017 Nathaniel J. Smith',
'MIT',
'https://raw.githubusercontent.com/python-trio/trio/master/LICENSE.MIT'
], [
'Twig',
'2009-2020 The Twig Team',
'BSD',
'https://twig.symfony.com/license'
], [
'TypeScript',
'2012-2021 Microsoft',
'Apache',
'https://raw.githubusercontent.com/Microsoft/TypeScript-Handbook/master/LICENSE'
], [
'Underscore.js',
'2009-2021 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors',
'MIT',
'https://raw.githubusercontent.com/jashkenas/underscore/master/LICENSE'
], [
'Vagrant',
'2010-2018 Mitchell Hashimoto',
'MPL',
'https://raw.githubusercontent.com/mitchellh/vagrant/master/website/LICENSE.md'
], [
'Vite',
'2019present, Yuxi (Evan) You and Vite contributors',
'MIT',
'https://github.com/vitejs/vite/blob/main/LICENSE'
], [
'Vue Router',
'2013-present Evan You',
'MIT',
'https://raw.githubusercontent.com/vuejs/vue-router/dev/LICENSE'
], [
'Vue.js',
'2013-present Yuxi Evan You',
'MIT',
'https://raw.githubusercontent.com/vuejs/vuejs.org/master/LICENSE'
], [
'Vuex',
'2015-present Evan You',
'MIT',
'https://raw.githubusercontent.com/vuejs/vuex/dev/LICENSE'
], [
'Vulkan',
'2014-2017 Khronos Group Inc.<br>Vulkan and the Vulkan logo are registered trademarks of the Khronos Group Inc.',
'CC BY',
'https://creativecommons.org/licenses/by/4.0/'
], [
'webpack',
'JS Foundation and other contributors',
'CC BY',
'https://creativecommons.org/licenses/by/4.0/'
], [
'Werkzeug',
'2007-2021 Pallets',
'BSD',
'https://github.com/pallets/werkzeug/blob/master/LICENSE.rst'
], [
'Wordpress',
'2003-2021 WordPress Foundation',
'GPLv2+',
'https://wordpress.org/about/license/'
], [
'Yarn',
'2016-present Yarn Contributors',
'BSD',
'https://raw.githubusercontent.com/yarnpkg/yarn/master/LICENSE'
], [
'Yii',
'2008-2017 by Yii Software LLC',
'BSD',
'https://raw.githubusercontent.com/yiisoft/yii/master/LICENSE'
], [
'Zig',
'20152021, Zig contributors',
'MIT',
'https://raw.githubusercontent.com/ziglang/zig/master/LICENSE'
]
]

@ -14,7 +14,7 @@ app.templates.intro = """
<li>Run <code>thor docs:download --installed</code> to update all downloaded documentations.
<li>To be notified about new versions, don't forget to <a href="https://github.com/freeCodeCamp/devdocs/subscription">watch the repository</a> on GitHub.
<li>The <a href="https://github.com/freeCodeCamp/devdocs/issues">issue tracker</a> is the preferred channel for bug reports and
feature requests. For everything else, use <a href="https://gitter.im/FreeCodeCamp/DevDocs">Gitter</a>.
feature requests. For everything else, use <a href="https://discord.gg/PRyKn3Vbay">Discord</a>.
<li>Contributions are welcome. See the <a href="https://github.com/freeCodeCamp/devdocs/blob/main/CONTRIBUTING.md">guidelines</a>.
<li>DevDocs is licensed under the terms of the Mozilla Public License v2.0. For more information,
see the <a href="https://github.com/freeCodeCamp/devdocs/blob/main/COPYRIGHT">COPYRIGHT</a> and
@ -36,7 +36,7 @@ app.templates.intro = """
<li>The search supports fuzzy matching (e.g. "bgcp" brings up "background-clip").
<li>To search a specific documentation, type its name (or an abbr.), then Tab.
<li>You can search using your browser's address bar &mdash; <a href="/help#browser_search">learn how</a>.
<li>DevDocs works <a href="/offline">offline</a>, on mobile, and can be installed on <a href="https://chrome.google.com/webstore/detail/devdocs/mnfehgbmkapmjnhcnbodoamcioleeooe">Chrome</a>.
<li>DevDocs works <a href="/offline">offline</a>, on mobile, and can be installed as web app.
<li>For the latest news, follow <a href="https://twitter.com/DevDocs">@DevDocs</a>.
<li>DevDocs is free and <a href="https://github.com/freeCodeCamp/devdocs">open source</a>.
<object data="https://img.shields.io/github/stars/freeCodeCamp/devdocs.svg?style=social" type="image/svg+xml" aria-hidden="true" height="20"></object>

@ -34,6 +34,9 @@ app.templates.settingsPage = (settings) -> """
<input type="checkbox" form="settings" name="layout" value="_sidebar-hidden"#{if settings['_sidebar-hidden'] then ' checked' else ''}>Automatically hide and show the sidebar
<small>Tip: drag the edge of the sidebar to resize it.</small>
</label>
<label class="_settings-label _hide-on-mobile">
<input type="checkbox" form="settings" name="noAutofocus" value="_no-autofocus"#{if settings.noAutofocus then ' checked' else ''}>Disable autofocus of search input
</label>
<label class="_settings-label">
<input type="checkbox" form="settings" name="autoInstall" value="_auto-install"#{if settings.autoInstall then ' checked' else ''}>Automatically download documentation for offline use
<small>Only enable this when bandwidth isn't a concern to you.</small>

File diff suppressed because one or more lines are too long

@ -14,6 +14,7 @@ class app.views.SettingsPage extends app.View
settings.theme = app.settings.get('theme')
settings.smoothScroll = !app.settings.get('fastScroll')
settings.arrowScroll = app.settings.get('arrowScroll')
settings.noAutofocus = app.settings.get('noAutofocus')
settings.autoInstall = app.settings.get('autoInstall')
settings.analyticsConsent = app.settings.get('analyticsConsent')
settings.spaceScroll = app.settings.get('spaceScroll')

@ -39,12 +39,16 @@ class app.views.Search extends app.View
return
focus: =>
@input.focus() unless document.activeElement is @input
return if document.activeElement is @input
return if app.settings.get('noAutofocus')
@input.focus()
return
autoFocus: =>
unless app.isMobile() or $.isAndroid() or $.isIOS()
@input.focus() unless document.activeElement?.tagName is 'INPUT'
return if app.isMobile() or $.isAndroid() or $.isIOS()
return if document.activeElement?.tagName is 'INPUT'
return if app.settings.get('noAutofocus')
@input.focus()
return
onWindowFocus: (event) =>

@ -3,7 +3,7 @@
//= depend_on sprites/docs.json
/*!
* Copyright 2013-2021 Thibaut Courouble and other contributors
* Copyright 2013-2023 Thibaut Courouble and other contributors
*
* This source code is licensed under the terms of the Mozilla
* Public License, v. 2.0, a copy of which may be obtained at:
@ -39,7 +39,7 @@
'pages/async',
'pages/bash',
'pages/bootstrap',
'pages/c',
'pages/cppref',
'pages/cakephp',
'pages/clojure',
'pages/codeception',
@ -52,11 +52,13 @@
'pages/dart',
'pages/dojo',
'pages/drupal',
'pages/eigen3',
'pages/elixir',
'pages/elisp',
'pages/ember',
'pages/erlang',
'pages/express',
'pages/fastapi',
'pages/git',
'pages/github',
'pages/gnuplot',
@ -66,12 +68,15 @@
'pages/gtk',
'pages/haproxy',
'pages/haskell',
'pages/jasmine',
'pages/jekyll',
'pages/jq',
'pages/jquery',
'pages/julia',
'pages/knockout',
'pages/kotlin',
'pages/kubectl',
'pages/kubernetes',
'pages/laravel',
'pages/liquid',
'pages/love',
@ -108,13 +113,14 @@
'pages/rubydoc',
'pages/rust',
'pages/rxjs',
'pages/sanctuary',
'pages/scala',
'pages/sinon',
'pages/socketio',
'pages/sphinx',
'pages/sphinx_simple',
'pages/sqlite',
'pages/support_tables',
'pages/tailwindcss',
'pages/tcl_tk',
'pages/tensorflow',
'pages/terraform',

@ -228,7 +228,7 @@
//
._credits {
width: 100%;
max-width: 100%;
}
//
@ -398,7 +398,12 @@
padding: .375rem;
cursor: pointer;
pre:hover > & { display: block; }
pre:hover > & {
display: block;
top: 0.1875rem;
padding: 0;
}
&:hover { opacity: 1; }
> svg {

@ -134,6 +134,9 @@ table {
border-collapse: separate;
border-spacing: 0;
border-radius: 3px;
display: inline-block;
overflow-x: auto;
max-width: 100%;
}
caption {

@ -1,8 +1,9 @@
._c {
._cppref {
> h2, > h3 { @extend %block-heading; }
> h4 { @extend %block-label, %label-blue; }
.fmbox { @extend %note; }
code, .t-mark, .t-mark-rev { @extend %label; }
.t-cc { @extend %code; }
.t-li1 { margin: 0 0 1em; }

@ -6,4 +6,10 @@
.note { @extend %note; }
.warning { @extend %note, %note-red; }
.note .label, .warning .label { font-weight: var(--boldFontWeight); }
.since {
color: var(--textColorLight);
font-weight: normal;
font-size: small;
}
}

@ -0,0 +1,22 @@
._fastapi {
> h2 { @extend %block-heading; }
> h3 { @extend %block-label, %label-blue; }
code { @extend %label; }
.tabbed-block {
border: 1px dashed black;
padding: 0.5rem 1rem 0;
margin-bottom: 1rem;
}
.tabbed-block label {
font-weight: var(--bolderFontWeight);
}
.admonition { @extend %note; }
.admonition.tip { @extend %note-green; }
.admonition.note { @extend %note-blue; }
.admonition-title {
font-weight: var(--bolderFontWeight);
}
}

@ -0,0 +1,4 @@
._jasmine {
.subsection-title, h2 { @extend %block-heading; }
h4 { @extend %block-label, %label-blue; }
}

@ -0,0 +1,4 @@
._kubectl {
@extend %simple;
}

@ -0,0 +1,4 @@
._kubernetes {
@extend %simple;
}

@ -132,7 +132,51 @@
dd { margin: 0; }
}
iframe.interactive {
width: 100%;
// based on https://github.com/mdn/yari/blob/63936bc42c/client/src/document/interactive-examples.scss
.interactive {
width: 100%;
height: 680px;
&.is-js-height {
height: 520px;
}
&.is-shorter-height {
height: 440px;
}
&.is-taller-height {
height: 730px;
}
&.is-tabbed-shorter-height {
height: 490px;
}
&.is-tabbed-standard-height {
height: 550px;
}
&.is-tabbed-taller-height {
height: 780px;
}
}
@media screen and (min-width: 993px) {
.interactive {
height: 380px;
&.is-js-height {
height: 450px;
}
&.is-shorter-height {
height: 370px;
}
&.is-taller-height {
height: 660px;
}
&.is-tabbed-shorter-height {
height: 360px;
}
&.is-tabbed-standard-height {
height: 430px;
}
&.is-tabbed-taller-height {
height: 640px;
}
}
}
}

@ -2,6 +2,7 @@
@extend %simple;
h4 { @extend %block-label; }
.code-header { @extend %code; }
.docblock { margin-left: 1em; }
div.information, div.important-traits {
@extend %note;

@ -0,0 +1,7 @@
._sanctuary {
@extend %simple;
pre > code {
font-size: inherit;
}
}

@ -1,4 +1,43 @@
._scala {
@extend %simple;
.deprecated { @extend %label-red; }
.attributes dl,
.attributes pre {
margin: 0;
}
.related-types {
@extend %pre;
margin: 0;
white-space: normal;
}
.links {
@extend %box;
margin-left: -1rem;
text-align: center;
padding: .5em;
a { padding: .4em }
@include print {
display: none;
}
}
.source-link {
float: right;
font-size: .75rem;
color: var(--linkColor);
cursor: pointer;
@extend %user-select-none;
&:hover { text-decoration: underline; }
@include print {
display: none;
}
}
}

@ -1,24 +0,0 @@
._socketio {
> h2 { @extend %block-heading; }
> h3 { @extend %block-label, %label-blue; }
> h2, > h3 { clear: both; }
h4 { font-size: 1em; }
.ezcol-one-half {
margin: .5em 0 1.5em;
float: left;
width: 50%;
padding-right: .5em;
@extend %border-box;
&.ezcol-last {
float: right;
padding: 0 0 0 .5em;
}
> h4 { margin: 0 0 1em; }
> pre { margin: 1em 0 0; }
}
code { @extend %label; }
}

@ -4,7 +4,7 @@
h4 { font-size: 1em; }
> dl:not(.docutils) > dt { @extend %block-label, %label-blue; }
dd > dl:not(.docutils) > dt { @extend %block-label; }
.class > dt { @extend %block-label, %label-blue; }
.class > dt, #main-interface .function > dt { @extend %block-label, %label-blue; }
dt + dt { margin-top: -.5em; }
.note, .admonition, div.versionadded, div.versionchanged, .deprecated-removed, .deprecated, .topic { @extend %note; }
@ -47,6 +47,11 @@
span.descclassname, span.descname { font-family: var(--monoFont) }
}
nav[aria-label="Page navigation"]{
display: flex !important;
justify-content: space-between !important;
}
._sphinx {
@extend %sphinx;
}

@ -0,0 +1,48 @@
._tailwindcss {
// Styling for customizing-colors page - color swatches (based on original tailwind display design)
.colors {
display: flex;
flex-direction: column;
gap: 1.2rem;
// Text offset
margin-bottom: 1rem;
}
// Color swatch title
.color > div:first-child {
font-weight: bold;
}
.color-swatch-group {
display: flex;
gap: 1rem;
flex-wrap: wrap;
}
.color-swatch-container {
display: inline-block;
}
// Tiny box with the color set as background
.color-swatch {
width: 120px;
height: 40px;
border-radius: 4px;
}
.color-tone-information {
display: flex;
justify-content: space-between;
}
// Styling for large quick-reference lookup tables
.long-quick-reference {
max-height: 40vh;
width: fit-content;
overflow-y: auto;
padding: .3rem;
border-top: 1px solid var(--textColor);
border-bottom: 1px solid var(--textColor);
}
}

@ -1,4 +1,4 @@
Adding a documentation may look like a daunting task but once you get the hang of it, it's actually quite simple. Don't hesitate to ask for help [in Gitter](https://gitter.im/FreeCodeCamp/DevDocs) if you ever get stuck.
Adding a documentation may look like a daunting task but once you get the hang of it, it's actually quite simple. Don't hesitate to ask for help [in Discord](https://discord.gg/PRyKn3Vbay) if you ever get stuck.
**Note:** please read the [contributing guidelines](../.github/CONTRIBUTING.md) before submitting a new documentation.

@ -23,9 +23,21 @@ and put it in `/path/to/devdocs/docs/`
Or run the following commands in your terminal:
```sh
curl https://storage.googleapis.com/dart-archive/channels/stable/release/$RELEASE/api-docs/dartdocs-gen-api-zip > dartApi.zip; \
curl https://storage.googleapis.com/dart-archive/channels/stable/release/$RELEASE/api-docs/dartdocs-gen-api.zip > dartApi.zip; \
unzip dartApi.zip; mv gen-dartdocs docs/dart~$VERSION
```
## date-fns
```sh
git clone https://github.com/date-fns/date-fns docs/date_fns
cd docs/date_fns
git checkout v2.29.2
yarn install
node scripts/build/docs.js
ls tmp/docs.json
```
## Django
Go to https://docs.djangoproject.com/, select the version from the
@ -53,7 +65,7 @@ Go to https://www.erlang.org/downloads and download the HTML documentation file.
```ah
mkdir --parent docs/erlang\~$VERSION/; \
curl http://erlang.org/download/otp_doc_html_$RELEASE.tar.gz | \
curl -L https://github.com/erlang/otp/releases/download/OTP-$RELEASE/otp_doc_html_$RELEASE.tar.gz | \
bsdtar --extract --file - --directory=docs/erlang\~$VERSION/
```
@ -151,11 +163,11 @@ bsdtar --extract --file=- --directory=docs/numpy~$VERSION/
## OCaml
Download from https://www.ocaml.org/docs/ the HTML reference:
https://ocaml.org/releases/4.11/ocaml-4.11-refman-html.tar.gz
https://v2.ocaml.org/releases/4.14/ocaml-4.14-refman-html.tar.gz
and extract it as `/path/to/devdocs/docs/ocaml`:
```sh
curl https://ocaml.org/releases/$VERSION/ocaml-$VERSION-refman-html.tar.gz | \
curl https://v2.ocaml.org/releases/$VERSION/ocaml-$VERSION-refman-html.tar.gz | \
tar xz --transform 's/htmlman/ocaml/' --directory docs/
```
@ -164,6 +176,13 @@ Search 'Openjdk' in https://www.debian.org/distrib/packages, find the `openjdk-$
download it, extract it with `dpkg -x $PACKAGE ./` and move `./usr/share/doc/openjdk-16-jre-headless/api/`
to `path/to/devdocs/docs/openjdk~$VERSION`
```
curl http://ftp.at.debian.org/debian/pool/main/o/openjdk-19/openjdk-19-doc_19+36-2_all.deb &&
tar xf openjdk-19-doc_19+36-2_all.deb
tar xf data.tar.xz
mv ./usr/share/doc/openjdk-19-jre-headless/api/ path/to/devdocs/docs/openjdk~$VERSION
```
If you use or have access to a Debian-based GNU/Linux distribution you can run the following command:
```sh
apt download openjdk-$VERSION-doc
@ -175,10 +194,7 @@ mv ./usr/share/doc/openjdk-16-jre-headless/api/ path/to/devdocs/docs/openjdk~$VE
## Pandas
```sh
mkdir docs/pandas~1
cd docs/pandas~1
curl https://pandas.pydata.org/docs/pandas.zip
bsdtar xf pandas.zip
curl https://pandas.pydata.org/docs/pandas.zip | bsdtar --extract --file - --directory=docs/pandas~1
```
## PHP
@ -266,5 +282,5 @@ Download the docs from https://sqlite.org/download.html, unzip it, and rename
it to `/path/to/devdocs/docs/sqlite`
```sh
curl https://sqlite.org/2021/sqlite-doc-3370000.zip | bsdtar --extract --file - --directory=docs/sqlite/```
curl https://sqlite.org/2022/sqlite-doc-3400000.zip | bsdtar --extract --file - --directory=docs/sqlite/ --strip-components=1
```

@ -49,16 +49,16 @@ In addition to the [publicly-documented commands](https://github.com/freeCodeCam
Packages can also be automatically generated during the scraping process by passing the `--package` option to `thor docs:generate`.
- `thor docs:upload`
This command does two operations:
1. sync the files for the specified documentations with S3 (used by the Heroku app);
2. upload the documentations' packages to DevDocs's S3 bundle zone (used by the `thor docs:download` command).
1. sync the files for the specified documentations with S3 (used by the Heroku app);
2. upload the documentations' packages to DevDocs's S3 bundle zone (used by the `thor docs:download` command).
For the command to work, you must have the AWS CLI configured as indicated above.
**Important:** the app should always be deployed immediately after this command has finished running. Do not run this command unless you are able and ready to deploy DevDocs.
To upload all documentations that are packaged on your computer, run `thor docs:upload --packaged`.
To test your configuration and the effect of this command without uploading anything, pass the `--dryrun` option.
@ -72,21 +72,21 @@ In addition to the [publicly-documented commands](https://github.com/freeCodeCam
## Deploying DevDocs
Once docs have been uploaded via `thor docs:upload` (if applicable), you can push to the DevDocs main branch (or merge the PR containing the updates). If the Travis build succeeds, the Heroku application will be deployed automatically.
Once docs have been uploaded via `thor docs:upload` (if applicable), you can push to the DevDocs main branch (or merge the PR containing the updates). This triggers a GitHub action which starts by running the tests. If they succeed, the Heroku application will be deployed automatically.
- If you're deploying documentation updates, verify that the documentations work properly once the deploy is done. Keep in mind that you'll need to wait a few seconds for the service worker to finish caching the new assets. You should see a "DevDocs has been updated" notification appear when the caching is done, after which you need to refresh the page to see the changes.
- If you're deploying frontend changes, monitor [Sentry](https://sentry.io/devdocs/devdocs-js/) for new JS errors once the deploy is done.
- If you're deploying server changes, monitor New Relic (accessible through [the Heroku dashboard](https://dashboard.heroku.com/apps/devdocs)) for Ruby exceptions and throughput or response time changes once the deploy is done.
If any issue arises, run `heroku rollback` to rollback to the previous version of the app (this can also be done via Heroku's UI). Note that this will not revert changes made to documentation files that were uploaded via `thor docs:upload`. Try and fix the issue as quickly as possible, then re-deploy the app. Reach out to other maintainers if you need help.
If any issue arises, run `heroku rollback` to rollback to the previous version of the app (this can also be done via Heroku's UI). Note that this will not revert changes made to documentation files that were uploaded via `thor docs:upload`. Try and fix the issue as quickly as possible, then re-deploy the app. Reach out to other maintainers if you need help.
If this is your first deploy, make sure another maintainer is around to assist.
If this is your first deploy, make sure another maintainer is around to assist.
## Infrastructure
The bundled documents are available at downloads.devdocs.io and the documents themselves at documents.devdocs.io. Download and document requests are proxied to S3 buckets devdocs-downloads.s3.amazonaws.com and devdocs-documents.s3.amazonaws.com respectively.
The bundled documents are available at downloads.devdocs.io and the documents themselves at documents.devdocs.io. Download and document requests are proxied to S3 buckets devdocs-downloads.s3.amazonaws.com and devdocs-documents.s3.amazonaws.com respectively.
New proxy VMs should be created from the `devdocs-proxy` snapshot. Before adding them to the load-balancer, it's necessary to add their IP addresses to the aws:SourceIp lists for both buckets, or their requests will be rejected.
New proxy VMs should be created from the `devdocs-proxy` snapshot. Before adding them to the load-balancer, it's necessary to add their IP addresses to the aws:SourceIp lists for both buckets, or their requests will be rejected.
When creating a new proxy VM and the `devdocs-proxy` snapshot is not available, then the new vm should be provisioned as follows:
@ -106,10 +106,10 @@ rm -rf /etc/nginx/.* 2> /dev/null
git clone https://github.com/freeCodeCamp/devdocs-nginx-config.git /etc/nginx
# at this point we need to add the certs from Cloudflare and test the config
nginx -t
nginx -t
# if nginx is already running, just
# ps aux | grep nginx
# if nginx is already running, just
# ps aux | grep nginx
# find the number and kill it
nginx
@ -130,6 +130,6 @@ The following people (used to) maintain DevDocs:
To reach out, please ping [@freeCodeCamp/devdocs](https://github.com/orgs/freeCodeCamp/teams/devdocs).
Interested in helping maintain DevDocs? Come talk to us on [Gitter](https://gitter.im/FreeCodeCamp/DevDocs) :)
Interested in helping maintain DevDocs? Come talk to us on [Discord](https://discord.gg/PRyKn3Vbay) :)
In addition, we appreciate the major contributions made by [these great people](https://github.com/freeCodeCamp/devdocs/graphs/contributors).

@ -187,6 +187,30 @@ More information about how filters work is available on the [Filter Reference](.
_Note: this filter is disabled by default._
### Processing responses before filters
These methods are runned before filter stacks, and can directly process responses.
* `process_response?(response)`
Determine whether a response should be processed. A response will be dropped if this method returns `false`.
It is useful to filter pages, such as empty, invalid, or redirecting pages, depending on the content.
Example: [lib/docs/scrapers/kotlin.rb](../lib/docs/scrapers/kotlin.rb)
* `parse(response)`
Parse HTTP/File response, and convert to a Nokogiri document by default.
Overrides this method if you want to modified HTML source code before Nokogiri.
It is useful to preserve whitespaces of code segments within non-pre blocks, because Nokogiri may delete them.
Example: [lib/docs/scrapers/go.rb](../lib/docs/scrapers/go.rb)
## Keeping scrapers up-to-date
In order to keep scrapers up-to-date the `get_latest_version(opts)` method should be overridden. If `self.release` is defined, this should return the latest version of the documentation. If `self.release` is not defined, it should return the Epoch time when the documentation was last modified. If the documentation will never change, simply return `1.0.0`. The result of this method is periodically reported in a "Documentation versions report" issue which helps maintainers keep track of outdated documentations.

@ -44,7 +44,7 @@ module Docs
end
def self.defaults
%w(css 'Web APIs' html http javascript).map(&method(:find))
%w(css dom html http javascript).map(&method(:find))
end
def self.installed

@ -87,8 +87,15 @@ module Docs
end
def store_page(store, id)
index = EntryIndex.new
pages = PageDb.new
store.open(path) do
if page = new.build_page(id) and store_page?(page)
index.add page[:entries]
pages.add page[:path], page[:output]
store_index(store, INDEX_FILENAME, index, false)
store_index(store, DB_FILENAME, pages, false)
store.write page[:store_path], page[:output]
true
else
@ -137,11 +144,11 @@ module Docs
page[:entries].present?
end
def store_index(store, filename, index)
old_json = store.read(filename) || '{}'
def store_index(store, filename, index, read_write=true)
old_json = read_write && store.read(filename) || '{}'
new_json = index.to_json
instrument "#{filename.remove('.json')}.doc", before: old_json, after: new_json
store.write(filename, new_json)
read_write && store.write(filename, new_json)
end
def store_meta(store)
@ -203,6 +210,8 @@ module Docs
[0, 1].each do |i|
break if i >= scraper_parts.length or i >= latest_parts.length
return 'Outdated major version' if i == 0 and latest_parts[i] > scraper_parts[i]
return 'Outdated major version' if i == 1 and latest_parts[i] > scraper_parts[i] and latest_parts[0] == 0 and scraper_parts[0] == 0
return 'Outdated major version' if i == 1 and latest_parts[i] > scraper_parts[i] and latest_parts[0] == 1 and scraper_parts[0] == 1
return 'Outdated minor version' if i == 1 and latest_parts[i] > scraper_parts[i]
return 'Up-to-date' if latest_parts[i] < scraper_parts[i]
end

@ -16,7 +16,11 @@ module Docs
def as_json
@docs.each_with_object [] do |doc, result|
next unless @store.exist?(doc.meta_path)
result << JSON.parse(@store.read(doc.meta_path))
json = JSON.parse(@store.read(doc.meta_path))
if doc.options[:attribution].is_a?(String)
json[:attribution] = doc.options[:attribution].strip
end
result << json
end
end

@ -12,6 +12,11 @@ module Docs
body.blank?
end
def content_length
value = headers['Content-Length'] || '0'
value.to_i
end
def mime_type
headers['Content-Type'] || 'text/plain'
end

@ -22,7 +22,7 @@ module Docs
private
def assert_source_directory_exists
unless Dir.exists?(source_directory)
unless Dir.exist?(source_directory)
raise SetupError, "The #{self.class.name} scraper requires the original documentation files to be stored in the \"#{source_directory}\" directory."
end
end

@ -0,0 +1,33 @@
module Docs
class Astro
class CleanHtmlFilter < Filter
def call
@doc = at_css('article > section')
css('.anchor-link').remove
css('.avatar-list').remove
css('header > h1').each do |node|
node.parent.before(node).remove
end
css('pre').each do |node|
node.content = node.css('.line').map(&:content).join("\n")
node['data-language'] = node.ancestors('figure').first['class'][/lang-(\w+)/, 1]
node.remove_attribute('style')
end
css('figcaption').each do |node|
node.name = 'div'
node['class'] = '_pre-heading'
end
css('figure').each do |node|
node.before(node.children).remove
end
doc
end
end
end
end

@ -0,0 +1,27 @@
module Docs
class Astro
class EntriesFilter < Docs::EntriesFilter
def get_name
name = at_css('h1').content
name.sub! %r{\s*#\s*}, ''
name
end
def get_type
aside = at_css('aside')
a = aside.at_css('a[aria-current="page"]', 'a[data-current-parent="true"]')
a.ancestors('details').at_css('summary').content
end
def additional_entries
return if slug.start_with?('guides/deploy')
return if slug.start_with?('guides/integrations-guide')
at_css('article').css('h2, h3').each_with_object [] do |node, entries|
type = node.content.strip
type.sub! %r{\s*#\s*}, ''
entries << ["#{name}: #{type}", node['id']]
end
end
end
end
end

@ -0,0 +1,18 @@
module Docs
class Axios
class CleanHtmlFilter < Filter
def call
if root_page?
return '<h1>Axios</h1><p>Promise based HTTP client for the browser and node.js</p><p>Axios is a simple promise based HTTP client for the browser and node.js. Axios provides a simple to use library in a small package with a very extensible interface.</p>'
end
@doc = at_css('main > .body')
css('.links').remove
css('pre').each do |node|
node.content = node.content
node['data-language'] = node['class'][/lang-(\w+)/, 1]
end
doc
end
end
end
end

@ -0,0 +1,13 @@
module Docs
class Axios
class EntriesFilter < Docs::EntriesFilter
def get_name
at_css('h1').content
end
def get_type
'axios'
end
end
end
end

@ -2,12 +2,15 @@ module Docs
class Bash
class CleanHtmlFilter < Filter
def call
@doc = at_css('> div[id]') if at_css('> div[id]')
# Remove the navigation header and footer and the lines underneath and above it
at_css('.header + hr').remove
line_above = at_xpath('//div[@class="header"]/preceding::hr[1]')
line_above.remove unless line_above.nil?
css('.header').remove
css('.copiable-anchor').remove
# Remove chapter and section numbers from title
title_node = at_css('h1, h2, h3, h4, h5, h6')
title_node.content = title_node.content.gsub(/(\d+\.?)+/, '').strip

@ -22,6 +22,9 @@ module Docs
end
def get_type
return "C keywords" if slug =~ /keyword/
type = at_css('.t-navbar > div:nth-child(4) > :first-child').try(:content)
type.strip!
type.remove! ' library'

@ -1,11 +0,0 @@
module Docs
class C
class FixUrlsFilter < Filter
def call
html.gsub! File.join(C.base_url, C.root_path), C.base_url[0..-2]
html.gsub! %r{#{C.base_url}([^"']+?)\.html}, "#{C.base_url}\\1"
html
end
end
end
end

@ -46,6 +46,13 @@ module Docs
next
end
size = response.content_length
if size > (context[:max_image_size] || DEFAULT_MAX_SIZE)
instrument 'too_big.image', url: url, size: size
next
end
image = response.body
unless context[:optimize_images] == false

@ -23,7 +23,7 @@ module Docs
end
def node(content)
node = Nokogiri::XML::Node.new 'h1', doc
node = Nokogiri::XML::Node.new 'h1', doc.document
node.content = content
node
end

@ -1,6 +1,8 @@
module Docs
class Cpp
class EntriesFilter < Docs::EntriesFilter
@@duplicate_names = []
REPLACE_NAMES = {
'Error directive' => '#error directive',
'Filename and line information' => '#line directive',
@ -11,7 +13,8 @@ module Docs
def get_name
name = at_css('#firstHeading').content.strip
name = format_name(name)
name.split(',').first
name = name.split(',').first
name
end
def get_type
@ -61,6 +64,21 @@ module Docs
REPLACE_NAMES[name] || name
end
# Avoid duplicate pages, these duplicate page are the same page for
# multiple functions that are organized in the same page because provide
# similar behavior but have different name.
def entries
entries = []
if !(@@duplicate_names.include?(name))
@@duplicate_names.push(name)
entries << default_entry if root_page? || include_default_entry?
entries.concat(additional_entries)
build_entries(entries)
end
end
end
end
end

@ -1,11 +0,0 @@
module Docs
class Cpp
class FixUrlsFilter < Filter
def call
html.gsub! File.join(Cpp.base_url, Cpp.root_path), Cpp.base_url[0..-2]
html.gsub! %r{#{Cpp.base_url}([^"']+?)\.html}, "#{Cpp.base_url}\\1"
html
end
end
end
end

@ -1,5 +1,5 @@
module Docs
class C
class Cppref
class CleanHtmlFilter < Filter
def call
css('h1').remove if root_page?
@ -109,6 +109,20 @@ module Docs
node['src'] = node['src'].sub! %r{http://en.cppreference.com/common/([^"']+?)\.svg}, 'http://upload.cppreference.com/mwiki/\1.svg'
end
# temporary solution due lack of mathjax/mathml support
css('.t-mfrac').each do |node|
fraction = Nokogiri::XML::Node.new('span', doc.document)
node.css('td').each do |node|
fraction.add_child("<span>#{node.content}</span>")
end
fraction.last_element_child().before("<span>/</span>")
node.before(fraction)
node.remove
end
doc
end
end

@ -1,5 +1,5 @@
module Docs
class C
class Cppref
class FixCodeFilter < Filter
def call
css('div > span.source-c', 'div > span.source-cpp').each do |node|

@ -9,10 +9,17 @@ module Docs
end
css('*[aria-label="Anchor"]').remove
css('*[class]').remove_attribute('class')
css('pre').each do |node|
css('pre', '.tw-1nkr705').each do |node|
node['data-language'] = 'typescript'
node.name = 'pre'
end
css('.tw-8ej7ai').each do |node|
code = node.at_css('.font-mono')
next unless code
code.parent.name = 'blockquote'
code.name = 'code'
end
css('*[class]').remove_attribute('class')
xpath('//a[text()="[src]"]').remove
doc

@ -11,7 +11,7 @@ module Docs
css('.promo a').remove_attribute('style')
# Translate source files links to DevDocs links
links = Nokogiri::XML::Node.new('p', doc)
links = Nokogiri::XML::Node.new('p', doc.document)
links['class'] = '_links'
css('a.github').each do |node|

@ -1,37 +0,0 @@
module Docs
class Docker
class CleanHtmlOldFilter < Filter
def call
if root_page?
doc.inner_html = "<h1>Docker Documentation</h1>"
return doc
end
@doc = at_css('#DocumentationText')
at_css('h2').name = 'h1' unless at_css('h1')
css('.anchorLink', '.reading-time', 'hr', '> div[style*="margin-top"]:last-child').remove
css('h1 + h1').each do |node|
node.name = 'h2'
end
css('pre').each do |node|
node.content = node.content
node['data-language'] = node.parent['class'][/language-(\w+)/, 1] if node.parent['class']
end
css('div.highlighter-rouge').each do |node|
node.before(node.children).remove
end
css('code.highlighter-rouge').each do |node|
node.content = node.content.gsub(/\s+/, ' ').strip
end
doc
end
end
end
end

@ -1,22 +0,0 @@
module Docs
class Docker
class CleanHtmlVeryOldFilter < Filter
def call
if root_page?
doc.inner_html = "<h1>Docker Documentation</h1>"
return doc
end
@doc = at_css('#content')
at_css('h2').name = 'h1' unless at_css('h1')
css('pre').each do |node|
node.content = node.content
end
doc
end
end
end
end

@ -10,20 +10,7 @@ module Docs
def get_name
return NAME_BY_SUBPATH[subpath] if NAME_BY_SUBPATH[subpath]
return at_css('h1').content unless nav_link
name = nav_link.content.strip
name.capitalize! if name == 'exoscale'
name.remove! ' (base command)'
if name =~ /\A[a-z\-\s]+\z/
name.prepend 'docker-compose ' if subpath =~ /compose\/reference\/./
name.prepend 'docker-machine ' if subpath =~ /machine\/reference\/./
else
name << " (#{product})" if name !~ /#{product}/i && !subpath.start_with?('get-started')
end
name
at_css('h1').content
end
def get_type
@ -37,11 +24,6 @@ module Docs
product
end
def nav_link
return @nav_link if defined?(@nav_link)
@nav_link = at_css('.currentPage')
end
def product
@product ||= subpath.split('/').first.capitalize
end

@ -1,75 +0,0 @@
module Docs
class Docker
class EntriesOldFilter < Docs::EntriesFilter
NAME_BY_SUBPATH = {
'engine/' => 'Engine',
'compose/' => 'Compose',
'machine/' => 'Machine'
}
def get_name
return NAME_BY_SUBPATH[subpath] if NAME_BY_SUBPATH[subpath]
return at_css('h1').content unless nav_link
name = nav_link.content.strip
name.capitalize! if name == 'exoscale'
name.remove! ' (base command)'
if name =~ /\A[a-z\-\s]+\z/
name.prepend 'docker-compose ' if subpath =~ /compose\/reference\/./
name.prepend 'docker-machine ' if subpath =~ /machine\/reference\/./
else
name << " (#{product})" if name !~ /#{product}/i
end
name
end
TYPE_BY_SUBPATH = {
'engine/' => 'Engine',
'compose/' => 'Compose',
'machine/' => 'Machine'
}
def get_type
return TYPE_BY_SUBPATH[subpath] if TYPE_BY_SUBPATH[subpath]
return 'Engine: CLI' if subpath.start_with?('engine/reference/commandline/')
return 'Engine: Admin Guide' if subpath.start_with?('engine/admin/')
return 'Engine: Security' if subpath.start_with?('engine/security/')
return 'Engine: Extend' if subpath.start_with?('engine/extend/')
return 'Engine: Get Started' if subpath.start_with?('engine/getstarted')
return 'Engine: Tutorials' if subpath.start_with?('engine/tutorials/')
return product if !nav_link && subpath =~ /\A\w+\/[\w\-]+\/\z/
leaves = nav_link.ancestors('li.leaf').reverse
return product if leaves.length <= 2
type = leaves[0..1].map { |node| node.at_css('> a').content.strip }.join(': ')
type.remove! %r{\ADocker }
type.remove! ' Engine'
type.sub! %r{Command[\-\s]line reference}i, 'CLI'
type.sub! 'CLI reference', 'CLI'
type
end
def nav_link
return @nav_link if defined?(@nav_link)
@nav_link = at_css('.currentPage')
unless @nav_link
link = at_css('#DocumentationText li a')
return unless link
link = at_css(".docsidebarnav_section a[href='#{link['href']}']")
return unless link
@nav_link = link.ancestors('.menu-closed').first.at_css('a')
end
@nav_link
end
def product
@product ||= subpath.split('/').first.capitalize
end
end
end
end

@ -1,56 +0,0 @@
module Docs
class Docker
class EntriesVeryOldFilter < Docs::EntriesFilter
def get_name
name = nav_link ? nav_link.content.strip : at_css('#content h1').content.strip
name.capitalize! if name == 'exoscale'
if name =~ /\A[a-z\-\s]+\z/
name.prepend 'docker ' if subpath =~ /engine\/reference\/commandline\/./
name.prepend 'docker-compose ' if subpath =~ /compose\/reference\/./
name.prepend 'docker-machine ' if subpath =~ /machine\/reference\/./
name.prepend 'swarm ' if subpath =~ /swarm\/reference\/./ && name != 'swarm'
else
name << " (#{product})" if name !~ /#{product}/i
end
name
end
def get_type
unless nav_link
return 'Engine: User guide' if subpath.start_with?('engine/userguide')
end
type = nav_link.ancestors('article').to_a.reverse.to_a[0..1].map do |node|
node.at_css('> button').content.strip
end.join(': ')
type.remove! %r{\ADocker }
type.remove! %r{ Engine}
type.sub! %r{Command[\-\s]line reference}i, 'CLI'
type = 'Engine: Reference' if type == 'Engine: reference'
type
end
def nav_link
return @nav_link if defined?(@nav_link)
@nav_link = at_css('#multiple .active')
unless @nav_link
link = at_css('#content li a')
return unless link
link = at_css("#multiple a[href='#{link['href']}']")
return unless link
@nav_link = link.ancestors('article').first.at_css('button')
end
@nav_link
end
def product
@product ||= subpath.split('/').first.capitalize
end
end
end
end

@ -0,0 +1,25 @@
module Docs
class Eigen3
class CleanHtmlFilter < Filter
def call
@doc = at_css('#doc-content')
css('#MSearchSelectWindow').remove
css('#MSearchResultsWindow').remove
css('.directory .levels').remove
css('.header .summary').remove
css('.ttc').remove
css('.top').remove
css('.dynheader.closed').remove
css('.permalink').remove
css('.groupheader').remove
css('.header').remove
css('#details').remove
css('*').each do |node|
node.remove_attribute('class')
end
doc
end
end
end
end

@ -0,0 +1,123 @@
module Docs
class Eigen3
class EntriesFilter < Docs::EntriesFilter
def get_type
group = at_css('.title .ingroups')
content = at_css('.contents').content
title = get_title()
downtitle = title.downcase
name = get_name
if slug.include?('unsupported')
return 'Unsupported'
elsif slug.start_with?('Topic') || downtitle.end_with?("topics")
return 'Topics'
elsif downtitle.end_with?("class template reference") || downtitle.end_with?("class reference")
return 'Classes'
elsif downtitle.end_with?("struct reference")
return 'Structs'
elsif downtitle.end_with?("typedefs")
return 'Typedefs'
elsif downtitle.end_with?("namespace reference")
return 'Namespaces'
elsif not group.nil? and group.content.include?('Reference') and (downtitle.end_with?("module") || downtitle.end_with?("modules"))
return "Modules"
elsif not group.nil?
if group.children.length > 0
return 'Chapter: ' + group.children[-1].content
else
return 'Chapter: ' + group.content
end
else
return 'Eigen'
end
end
def get_name
title = get_title().gsub(/[<(].*/, '').gsub(/(Class|Class Template|Namespace|Struct) Reference/, '').strip
end
def get_title
unless at_css('.title').nil?
group = at_css('.title .ingroups')
title = at_css('.title').content
if not group.nil?
title = title.delete_suffix(group.content)
end
return title.strip
else
return slug
end
end
def additional_entries
# return [] if slug.include?('unsupported')
name = get_name()
entries = []
css('table.memberdecls').map do |table|
doxygen_type = table.at_css("tr.heading").text.strip
case doxygen_type
when "Functions"
type = "Functions"
when "Public Member Functions", "Static Public Member Functions", "Public Types", "Additional Inherited Members"
type = nil
when "Classes"
type = "Classes"
when "Typedefs"
type = "Typedefs"
when "Variables"
type = "Variables"
else
next
end
tmp_entries = []
table.css('td.memItemRight,td.memTemplItemRight').map do |node_r|
node_l = node_r.parent.at_css('memItemLeft')
if (not node_l.nil? and node_l.text.strip == 'enum') || node_r.content.include?('{')
node_r.css("a").each {|n| tmp_entries << [n.content, n.attr('href')]}
else
n = node_r.at_css("a")
next if n.nil?
tmp_entries << [node_r.content, n.attr('href')]
end
end
tmp_entries.each do |args|
(content, href) = args
next if href.nil?
if not href.include?("#") and (name == 'Eigen' || type == "Classes") then
next
end
if slug.include?('unsupported')
if not (href.include?('unsupported') || href.include?('#'))
next
elsif href.include?('#') and not href.include?('unsupported')
href = 'unsupported/' + href
end
end
if doxygen_type == "Typedefs"
content = content.sub(/\s*=.*$/, "")
end
if not (name.end_with?('module') || name.end_with?('typedefs')) \
and not content.start_with?("Eigen::")
content = name + "::" + content
end
content.gsub! /^\s+/, ''
content.gsub! /\s+,\s+/, ', '
content.gsub! /\s\s+/, ' '
entries << [content, href, type]
end
end
entries
end
end
end
end

@ -4,8 +4,6 @@ module Docs
def call
@doc = at_css(".markdown")
css("header").before(at_css("h1"))
css(".theme-doc-toc-desktop").remove
css(".theme-doc-toc-mobile").remove
@ -14,6 +12,11 @@ module Docs
css("footer").remove
css('pre').each do |node|
node.content = node.css('.token-line').map(&:content).join("\n")
node['data-language'] = 'javascript'
end
doc
end
end

@ -27,6 +27,8 @@ module Docs
def api
css('.hover-link', 'footer', ':not(.detail-header) > .view-source').remove
css('h1 .settings').remove
css('.summary').each do |node|
node.name = 'dl'
end

@ -3,11 +3,11 @@ module Docs
class EntriesFilter < Docs::EntriesFilter
def get_name
css('h1 .app-vsn').remove
name = (at_css('h1 > span') or at_css('h1')).content.strip
if current_url.path.start_with?('/getting-started')
at_css('h1').content.strip.remove(/\.\z/)
name.remove(/\.\z/)
else
name = at_css('h1').content.strip
name = name.split(' ').first unless name.start_with?('mix ') # ecto
name
end

@ -2,7 +2,7 @@ module Docs
class Erlang
class CleanHtmlFilter < Filter
def call
@doc = at_css('#content')
@doc = at_css('#content .innertube', '#content')
# frontpage
@ -12,8 +12,6 @@ module Docs
node.before(node.children).remove
end
css('> br').remove
css('> font[size="+1"]:first-child').each do |node|
node.name = 'h1'
end
@ -30,63 +28,55 @@ module Docs
# others
css('a[name]').each do |node|
# parent = node.parent
# parent = parent.parent while parent.name == 'span'
(node.next_element || node.parent)['id'] ||= node['name']
node.before(node.children).remove
# Remove JS on-hover highlighting
css('h3.title-link', 'h4.title-link', 'div.data-type-name', 'div.func-head').each do |node|
node.remove_attribute('onmouseover')
node.remove_attribute('onmouseout')
end
css('h3').each do |node|
node.name = 'h2'
content = node.content
node.content = content.capitalize if content == content.upcase
end
css('p > .bold_code:first-child ~ br:last-child').each do |node|
parent = node.parent
parent.name = 'h3'
parent.css('> br').remove
parent.css('> code').each do |code|
code.css('*:not(a):not(br)').each { |n| n.before(n.children).remove }
code.inner_html = code.inner_html.gsub('<br>', "\n").strip
end
end
# Subsume "Types" heading under function head heading
css('h4.func-head + .fun-types > h3.func-types-title')
.each { |node| node.name = 'h5' }
css('pre:not(.REFTYPES) *:not(a)', 'a[href^=javascript]').each do |node|
node.before(node.children).remove
css('p > a[name]').each do |node|
parent = node.parent
parent.name = 'h4'
parent['id'] ||= node['name']
parent.css('> br:last-child').remove
end
css('a[name]:empty').each { |n| (n.next_element || n.parent)['id'] ||= n['name'] }
css('pre:not(.REFTYPES)').each do |node|
node['data-language'] = 'erlang'
node.inner_html = node.inner_html.strip_heredoc
css('h3', 'h4', 'h5').each do |node|
node.name = node.name.sub(/\d/) { |i| i.to_i - 1 }
end
css('.REFBODY').each do |node|
if node.element_children.length == 0
node.name = 'p'
# Convert <span/> code blocks to <code/> if inline otherwise <pre><code/></pre>
css('span.bold_code', 'span.code', '.func-head > span.title-name').each do |node|
node.remove_attribute('class')
node.css('span.bold_code', 'span.code')
.each { |n| n.before(n.children).remove }
if node.at_css('br') then
node.name = 'pre'
node.inner_html = "<code>" +
node.inner_html.remove(/\n/).gsub('<br>', "\n").strip +
"</code>"
else
node.before(node.children).remove
node.name = 'code'
node.inner_html = node.inner_html.strip.gsub(/\s+/, ' ')
end
end
css('.REFTYPES').each do |node|
next unless node.parent
html = "<pre>"
while node['class'] == 'REFTYPES'
node.inner_html = node.inner_html.remove(/\n/).gsub('<br>', "\n")
node.css('*:not(a)').each { |n| n.before(n.children).remove }
html << node.inner_html.strip + "\n"
node = node.next_element
node.previous_element.remove
end
html.gsub! %r{\n{2,}}, "\n"
html.strip!
html << "</pre>"
node.before(html)
css('*:not(.REFTYPES) > pre').each do |node|
node['data-language'] = 'erlang'
node.inner_html = node.inner_html.strip_heredoc
end
css('.REFTYPES').remove
css('a[href^=javascript]').each { |n| n.before(n.children).remove }
css('table').each do |node|
node.remove_attribute('border')
@ -99,8 +89,6 @@ module Docs
node.remove_attribute('valign')
end
css('.bold_code').remove_attr('class')
doc
end
end

@ -2,14 +2,14 @@ module Docs
class Erlang
class EntriesFilter < Docs::EntriesFilter
def get_name
name = at_css('h1').content.strip
name = at_css('#content h1').content.strip
name << " (#{type.remove('Guide: ')})" if name == '1 Introduction'
name.sub! %r{\A(\d+)}, '\1.'
name
end
def get_type
name = at_css('h1').content.strip
name = at_css('#content h1').content.strip
if subpath.start_with?('lib/')
type = subpath[/lib\/(.+?)[\-\/]/, 1]
@ -44,10 +44,9 @@ module Docs
if subpath.start_with?('lib/')
names = Set.new
entry_nodes.each_with_object [] do |node, entries|
id = node['name']
id = node['id'] || node['name']
name = id.remove %r{\-\d*\z}
name << ' (type)' if name.sub!(/\Atype-/, '')
name.remove! 'Module:'
name.prepend "#{self.name}:"
entries << [name, id] if names.add?(name)
end
@ -67,9 +66,13 @@ module Docs
def entry_nodes
@entry_nodes ||= if subpath.start_with?('lib/')
css('p + div.REFBODY').each_with_object [] do |node, result|
r18_funs = css('p + div.REFBODY').each_with_object [] do |node, result|
result.concat(node.previous_element.css('a[name]').to_a)
end
css('article.data-types-body > h4', 'article.func > h4',
'div.data-type-name a[name]', 'div.exports-body > a[name]',
'div.fun-type a[name]').entries +
r18_funs
elsif subpath.start_with?('erts')
link = at_css(".flipMenu a[href='#{File.basename(subpath, '.html')}']")
list = link.parent.parent

@ -4,15 +4,6 @@ module Docs
def call
css('.flipMenu li[title] > a').remove unless subpath.start_with?('erts') # perf
css('.REFTYPES').each do |node|
node.name = 'pre'
end
css('span.bold_code', 'span.code').each do |node|
node.name = 'code'
node.inner_html = node.inner_html.strip.gsub(/\s+/, ' ')
end
doc
end
end

@ -2,7 +2,8 @@ module Docs
class Eslint
class CleanHtmlFilter < Filter
def call
@doc = at_css('.doc') if at_css('.doc')
@doc = at_css('#main') if at_css('#main')
@doc = at_css('.docs-main__content') if at_css('.docs-main__content')
css('.eslint-ad').remove
css('.glyphicon').remove
@ -12,6 +13,7 @@ module Docs
node.before(node.children).remove
end
css('.line-numbers-wrapper').remove
css('pre.hljs').each do |node|
lang = node['class'][/highlight-(\w+)/, 1]
node['data-language'] = lang if lang
@ -22,6 +24,8 @@ module Docs
css('code', 'p').remove_attr('class')
css('.resource__image', '.resource__domain').remove
doc
end
end

@ -3,11 +3,6 @@ module Docs
class EntriesFilter < Docs::EntriesFilter
def get_name
name = at_css('h1').content.strip
if subpath.start_with?('rules/') && subpath != 'rules/'
name = name[/\(([\w\-]+?)\)\z/, 1] || name[/\A([\w\-]+?):/, 1]
end
name
end

@ -0,0 +1,34 @@
module Docs
class Fastapi
class CleanHtmlFilter < Filter
def call
doc.css('.headerlink').remove
if root_page?
doc.css('#sponsors ~ p', '#sponsors').remove
end
doc.css('.tabbed-set').each do |node|
labels = node.css('.tabbed-labels label')
blocks = node.css('.tabbed-content .tabbed-block')
blocks.each_with_index do |block_node, i|
block_node.prepend_child(labels[i]) if labels[i]
end
node.css('> input, .tabbed-labels').remove
end
doc.css('pre').each do |node|
node['class'] = "language-python"
node['data-language'] = "python"
node.content = node.at_css('code').content
end
doc
end
end
end
end

@ -0,0 +1,9 @@
module Docs
class Fastapi
class ContainerFilter < Filter
def call
at_css '.md-content > .md-content__inner'
end
end
end
end

@ -0,0 +1,40 @@
module Docs
class Fastapi
class EntriesFilter < Docs::EntriesFilter
def sanitized_path
path.gsub(/index$/, "")
end
def path_parts
sanitized_path.split("/")
end
def get_name
at_css('h1').content
end
def get_type
if path_parts.length <= 1
at_css('h1').content
else
path_parts[0...-1].join(": ").titleize + ": " + at_css('h1').content
end
end
def additional_entries
entries = []
type = get_type
css('h2').each do |node|
name = node.content
id = path + "#" + node['id']
entries << [name, id, type]
end
entries
end
end
end
end

@ -2,7 +2,7 @@ module Docs
class Fish
class CleanHtmlSphinxFilter < Filter
def call
@doc = at_css('.body')
@doc = at_css('.body > section') or at_css('.body')
css('pre[data-language="fish"]').each do |node|
node['data-language'] = 'shell'
end

@ -4,11 +4,11 @@ module Docs
def call
if root_page?
at_css('h1').content = 'Godot Engine'
at_css('.admonition.tip').remove
at_css('.admonition.note').remove
end
css('ul[id].simple li:first-child:last-child').each do |node|
heading = Nokogiri::XML::Node.new 'h3', doc
heading = Nokogiri::XML::Node.new 'h3', doc.document
heading['id'] = node.parent['id']
heading.children = node.children
node.parent.before(heading).remove

@ -0,0 +1,27 @@
module Docs
class Godot
class CleanHtmlV2Filter < Filter
def call
if root_page?
at_css('h1').content = 'Godot Engine'
at_css('.admonition.tip').remove
end
css('ul[id].simple li:first-child:last-child').each do |node|
heading = Nokogiri::XML::Node.new 'h3', doc.document
heading['id'] = node.parent['id']
heading.children = node.children
node.parent.before(heading).remove
end
css('h3 strong').each do |node|
node.before(node.children).remove
end
css('a.reference').remove_attr('class')
doc
end
end
end
end

@ -7,17 +7,11 @@ module Docs
name
end
TYPE_BY_LEARNING_PATH = {
'step_by_step' => 'Guides: Step by step',
'editor' => 'Guides: Editor',
'features' => 'Guides: Engine features',
'scripting' => 'Guides: Scripting',
'workflow' => 'Guides: Project workflow'
}
def get_type
if slug.start_with?('learning')
TYPE_BY_LEARNING_PATH[slug.split('/')[1]]
if slug.start_with?('getting_started')
# Getting started sections are different even between different minor
# versions from v3 so we're programmatically generating them instead.
"Getting started: " + slug.split('/')[1].tr_s('_', ' ').capitalize
else
name
end
@ -36,7 +30,7 @@ module Docs
end
def include_default_entry?
return false if subpath.start_with?('learning') && subpath.end_with?('index.html')
return false if subpath.start_with?('getting_started') && subpath.end_with?('index.html')
return false if subpath == 'classes/index.html'
true
end

@ -0,0 +1,45 @@
module Docs
class Godot
class EntriesV2Filter < Docs::EntriesFilter
def get_name
name = at_css('h1').content
name.remove! "\u{00B6}" # Remove the pilcrow
name
end
TYPE_BY_LEARNING_PATH = {
'step_by_step' => 'Guides: Step by step',
'editor' => 'Guides: Editor',
'features' => 'Guides: Engine features',
'scripting' => 'Guides: Scripting',
'workflow' => 'Guides: Project workflow'
}
def get_type
if slug.start_with?('learning')
TYPE_BY_LEARNING_PATH[slug.split('/')[1]]
else
name
end
end
def additional_entries
return [] unless slug.start_with?('classes')
css('.simple[id]').each_with_object [] do |node, entries|
name = node.at_css('strong').content
next if name == self.name
name.prepend "#{self.name}."
name << '()'
entries << [name, node['id']] unless entries.any? { |entry| entry[0] == name }
end
end
def include_default_entry?
return false if subpath.start_with?('learning') && subpath.end_with?('index.html')
return false if subpath == 'classes/index.html'
true
end
end
end
end

@ -2,7 +2,7 @@ module Docs
class Groovy
class CleanHtmlFilter < Filter
def new_node(content)
node = Nokogiri::XML::Node.new 'h1', doc
node = Nokogiri::XML::Node.new 'h1', doc.document
node.content = content
node
end

@ -29,8 +29,9 @@ module Docs
node['id'] = node.at_css('.anchor')['name']
end
css('.keyword > b').each do |node|
css('.keyword > b', '.keyword > span').each do |node|
node.content = node.content
node.remove_attribute('style')
end
css('.dropdown').each do |node|

@ -1,7 +1,6 @@
module Docs
class Html
class EntriesFilter < Docs::EntriesFilter
OBSOLETE = %w(frame frameset hgroup noframes)
ADDITIONAL_ENTRIES = { 'Element/Heading_Elements' => (1..6).map { |n| ["h#{n}"] } }
def get_name
@ -15,10 +14,10 @@ module Docs
def get_type
return 'Miscellaneous' if slug.include?('CORS') || slug.include?('Using')
if slug.start_with?('Global_attr')
if at_css('.deprecated', '.non-standard', '.obsolete')
'Obsolete'
elsif slug.start_with?('Global_attr')
'Attributes'
elsif at_css('#deprecated', '#non-standard', '#obsolete') || OBSOLETE.include?(slug.remove('Element/'))
'Obsolete'
elsif slug.start_with?('Element/')
'Elements'
else
@ -38,12 +37,14 @@ module Docs
css('.standard-table td:first-child').each_with_object [] do |node, entries|
next if node.next_element.content.include?('Global attribute')
name = "#{node.content.strip} (attribute)"
name = "#{node.at_css('code').content.strip} (attribute)" if node.at_css('code')
id = node.parent['id'] = name.parameterize
entries << [name, id, 'Attributes']
end
elsif slug == 'Link_types'
css('.standard-table td:first-child > code').map do |node|
name = node.content.strip
name = "#{node.at_css('code').content.strip} (attribute)" if node.at_css('code')
id = node.parent.parent['id'] = name.parameterize
name.prepend 'rel: '
[name, id, 'Attributes']

@ -25,6 +25,8 @@ module Docs
end
def ietf
raise "#{slug} is obsolete!" if at_css('.meta-info *:contains("Obsoleted by")')
@doc = at_css('.draftcontent')
doc.child.remove while doc.child.name != 'pre'
css('span.grey', '.invisible', '.noprint', 'a[href^="#page-"]').remove

@ -44,76 +44,62 @@ module Docs
end
SECTIONS = {
'rfc2616' => [
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15],
[14],
[]
],
'rfc4918' => [
[],
[11],
[]
[], []
],
'rfc7230' => [
(2..9).to_a,
[],
'rfc9110' => [
(3..18).to_a,
(3..17).to_a,
(7..15).to_a,
[]
],
'rfc7231' => [
[3, 8, 9],
'rfc9111' => [
(3..8).to_a,
(3..10).to_a,
[],
[4, 5, 6, 7]
[5]
],
'rfc7232' => [
[5, 6, 7, 8],
[2, 3, 4],
[]
],
'rfc7233' => [
[5, 6],
[2, 3, 4],
[]
],
'rfc7234' => [
[3, 6, 7, 8],
[4, 5],
[]
'rfc9112' => [
(2..12).to_a,
(2..11).to_a,
[], []
],
'rfc7235' => [
[2, 5, 6],
[3, 4],
[]
'rfc9113' => [
(3..11).to_a,
(3..10).to_a,
[], []
],
'rfc7540' => [
'rfc9114' => [
(3..11).to_a,
[],
[]
(3..10).to_a,
[7], []
],
'rfc5023' => [
[],
[],
[]
[], [], [], []
]
}
LEVEL_1 = /\A(\d+)\z/
LEVEL_2 = /\A(\d+)\.\d+\z/
LEVEL_3 = /\A(\d+)\.\d+\.\d+\z/
LEVEL_4 = /\A(\d+)\.\d+\.\d+\.\d+\z/
def additional_entries
return [] unless current_url.host == 'datatracker.ietf.org'
type = nil
css('a[href^="#section-"]').each_with_object([]) do |node, entries|
id = node['href'].remove('#')
css('*[id^="section-"]').each_with_object([]) do |node, entries|
id = node['id']
break entries if entries.any? { |e| e[1] == id }
content = node.next.content.strip
content = node.content.strip
content.remove! %r{\s*\.+\d*\z}
content.remove! %r{\A[\.\s]+}
name = "#{content} (#{rfc})"
number = node.content.strip
number = id.remove('section-')
if number =~ LEVEL_1
if SECTIONS[slug][0].include?($1.to_i)
@ -131,7 +117,11 @@ module Docs
type = self.name
end
elsif (number =~ LEVEL_2 && SECTIONS[slug][1].include?($1.to_i)) ||
(number =~ LEVEL_3 && SECTIONS[slug][2].include?($1.to_i))
(number =~ LEVEL_3 && SECTIONS[slug][2].include?($1.to_i)) ||
(number =~ LEVEL_4 && SECTIONS[slug][3].include?($1.to_i))
if type != self.name
name.remove! %r{\A(\d+\.)* }
end
entries << [name, id, (name =~ /\A\d\d\d/ ? 'Status' : type )]
end
end

@ -2,21 +2,7 @@ module Docs
class Jasmine
class CleanHtmlFilter < Filter
def call
@doc = at_css('.docs')
at_css('h1').content = 'Jasmine' if root_page?
css('header', 'article', 'section:not([class])', 'div.description').each do |node|
node.before(node.children).remove
end
css('h3.subsection-title').each do |node|
node.name = 'h2'
end
css('h4.name').each do |node|
node.name = 'h3'
end
@doc = at_css('.docs') unless root_page?
css('pre').each do |node|
node.content = node.content

@ -2,24 +2,17 @@ module Docs
class Jasmine
class EntriesFilter < Docs::EntriesFilter
def get_name
name = at_css('h1').content.strip
name.remove! %r{\A\w+:\s}
name
at_css('h1').content.strip
end
def get_type
at_css('h1').content.strip
name
end
def additional_entries
css('h3[id]').each_with_object [] do |node, entries|
name = node.content.strip
next if name.start_with?('new ')
static = name.sub! '(static) ', ''
name.sub! %r{\(.*\)}, '()'
name.remove! %r{\s.*}
name.prepend "#{self.name}#{static ? '.' : '#'}" unless slug == 'global'
entries << [name, node['id']]
css('h4[id]').each_with_object [] do |node, entries|
name = node['id']
entries << [name.sub(/\./, ''), name]
end
end
end

@ -9,11 +9,6 @@ module Docs
css('hr', '.hash-link', 'button', '.badge').remove
css('.anchor').each do |node|
node.parent['id'] = node['id']
node.remove
end
css('.prism-code').each do |node|
node.parent.parent.before(node)
node.name = 'pre'

@ -39,7 +39,7 @@ module Docs
name.remove! %r{[\s=<].*}
name.prepend 'jest ' if name.start_with?('--')
name.prepend 'Config: ' if slug == 'configuration'
id = node.at_css('.anchor')['id']
id = node['id']
entries << [name, id]
end

@ -12,24 +12,6 @@ module Docs
css('a > img').each do |node|
node.parent.before(node.parent.content).remove
end
css('div.code-block').each do |node|
node.name = 'pre'
node['data-language'] = node['data-lang']
node.content = node.content
# FIXME: newlines in code-block are lost because of <div>? (on https://kotlinlang.org/docs/typecasts.html for instance)
end
css('pre').each do |node|
node['data-language'] = 'kotlin' if node.at_css('code.language-kotlin')
node['data-language'] = 'groovy' if node.at_css('code.language-groovy')
node['data-language'] = 'javascript' if node.at_css('code.language-javascript')
node['data-language'] = 'xml' if node.at_css('code.language-xml')
node.content = node.content
node.parent.remove_attribute('data-highlight-only')
node.parent.remove_attribute('data-lang')
node.parent.remove_attribute('theme')
end
end
def api_page

@ -0,0 +1,15 @@
module Docs
class Kubectl
class CleanHtmlFilter < Filter
def call
css('pre').each do |node|
node.content = node.content.squish
node['data-language'] = 'bash'
end
doc
end
end
end
end

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save