Merge branch 'main' into add/threejs-docs

pull/2392/head
Simon Legner 1 day ago
commit 74aa661e3a

@ -13,13 +13,13 @@ jobs:
steps:
- uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2.7.0
- name: Set up Ruby
uses: ruby/setup-ruby@540484a3c0f308b08619664ec40bf6c371d172c3 # v1.205.0
uses: ruby/setup-ruby@32110d4e311bd8996b2a82bf2a43b714ccc91777 # v1.221.0
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@581dd286c962b6972d427fcf8980f60755c15520 # v3.13.15
uses: akhileshns/heroku-deploy@e3eb99d45a8e2ec5dca08735e089607befa4bf28 # v3.14.15
with:
heroku_api_key: ${{secrets.HEROKU_API_KEY}}
heroku_app_name: "devdocs"

@ -11,7 +11,7 @@ jobs:
steps:
- uses: actions/checkout@ee0669bd1cc54295c223e0bb666b733df41de1c5 # v2.7.0
- name: Set up Ruby
uses: ruby/setup-ruby@540484a3c0f308b08619664ec40bf6c371d172c3 # v1.205.0
uses: ruby/setup-ruby@32110d4e311bd8996b2a82bf2a43b714ccc91777 # v1.221.0
with:
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- name: Generate report

@ -11,7 +11,7 @@ jobs:
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Set up Ruby
uses: ruby/setup-ruby@540484a3c0f308b08619664ec40bf6c371d172c3 # v1.205.0
uses: ruby/setup-ruby@32110d4e311bd8996b2a82bf2a43b714ccc91777 # v1.221.0
with:
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
- name: Run tests

@ -1 +1 @@
3.3.6
3.4.2

@ -1 +1 @@
ruby 3.3.6
ruby 3.4.2

@ -1,4 +1,4 @@
Copyright 2013-2024 Thibaut Courouble and other contributors
Copyright 2013-2025 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:3.3.6
FROM ruby:3.4.2
ENV LANG=C.UTF-8
ENV ENABLE_SERVICE_WORKER=true

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

@ -1,5 +1,5 @@
source 'https://rubygems.org'
ruby '3.3.6'
ruby '3.4.2'
gem 'activesupport', require: false
gem 'html-pipeline'

@ -36,7 +36,8 @@ GEM
exifr (1.4.0)
ffi (1.15.5)
fspath (3.1.2)
highline (2.0.3)
highline (3.1.2)
reline
html-pipeline (2.14.3)
activesupport (>= 2)
nokogiri (>= 1.4)
@ -53,6 +54,7 @@ GEM
image_optim (~> 0.19)
image_size (3.3.0)
in_threads (1.6.0)
io-console (0.8.0)
logger (1.6.2)
method_source (1.0.0)
mini_portile2 (2.8.8)
@ -61,7 +63,7 @@ GEM
mustermann (3.0.3)
ruby2_keywords (~> 0.0.1)
newrelic_rpm (8.16.0)
nokogiri (1.17.2)
nokogiri (1.18.3)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
options (2.3.2)
@ -76,7 +78,7 @@ GEM
byebug (~> 11.0)
pry (>= 0.13, < 0.15)
racc (1.8.1)
rack (2.2.10)
rack (2.2.11)
rack-protection (3.2.0)
base64 (>= 0.1.0)
rack (~> 2.2, >= 2.2.4)
@ -88,6 +90,8 @@ GEM
rb-inotify (0.10.1)
ffi (~> 1.0)
redcarpet (3.6.0)
reline (0.6.0)
io-console (~> 0.5)
rexml (3.3.9)
rouge (1.11.1)
rr (3.1.1)
@ -126,14 +130,14 @@ GEM
strings-ansi (0.2.0)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
terser (1.2.4)
terser (1.2.5)
execjs (>= 0.3.0, < 3)
thin (1.8.2)
daemons (~> 1.0, >= 1.0.9)
eventmachine (~> 1.0, >= 1.0.4)
rack (>= 1, < 3)
thor (1.3.2)
tilt (2.4.0)
tilt (2.6.0)
tty-pager (0.14.0)
strings (~> 0.2.0)
tty-screen (~> 0.8)
@ -187,7 +191,7 @@ DEPENDENCIES
yajl-ruby
RUBY VERSION
ruby 3.3.6p108
ruby 3.4.2p28
BUNDLED WITH
2.4.6

@ -25,12 +25,12 @@ Unless you wish to contribute to the project, we recommend using the hosted vers
The easiest way to run DevDocs locally is using Docker:
```sh
docker run --name devdocs -d -p 9292:9292 ghcr.io/freecodcamp/devdocs:latest
docker run --name devdocs -d -p 9292:9292 ghcr.io/freecodecamp/devdocs:latest
```
This will start DevDocs at [localhost:9292](http://localhost:9292). We provide both regular and Alpine-based images:
- `ghcr.io/freecodcamp/devdocs:latest` - Standard image
- `ghcr.io/freecodcamp/devdocs:latest-alpine` - Alpine-based (smaller size)
- `ghcr.io/freecodecamp/devdocs:latest` - Standard image
- `ghcr.io/freecodecamp/devdocs:latest-alpine` - Alpine-based (smaller size)
Images are automatically built and updated monthly with the latest documentation.
@ -195,7 +195,7 @@ Made something cool? Feel free to open a PR to add a new row to this table! You
## Copyright / License
Copyright 20132024 Thibaut Courouble and [other contributors](https://github.com/freeCodeCamp/devdocs/graphs/contributors)
Copyright 20132025 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.

@ -1,5 +1,5 @@
/*
* Copyright 2013-2024 Thibaut Courouble and other contributors
* Copyright 2013-2025 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:

@ -457,13 +457,13 @@ $.noop = function () {};
$.popup = function (value) {
try {
window.open(value.href || value, "_blank", "noopener");
} catch (error) {
const win = window.open();
if (win.opener) {
win.opener = null;
}
win.location = value.href || value;
} catch (error) {
window.open(value.href || value, "_blank");
}
};
@ -526,21 +526,3 @@ $.highlight = function (el, options) {
el.classList.add(options.className);
setTimeout(() => el.classList.remove(options.className), options.delay);
};
$.copyToClipboard = function (string) {
let result;
const textarea = document.createElement("textarea");
textarea.style.position = "fixed";
textarea.style.opacity = 0;
textarea.value = string;
document.body.appendChild(textarea);
try {
textarea.select();
result = !!document.execCommand("copy");
} catch (error) {
result = false;
} finally {
document.body.removeChild(textarea);
}
return result;
};

@ -1,4 +1,8 @@
[
[
"2025-02-16",
"New documentation: <a href=\"/openlayers/\">OpenLayers</a>"
],
[
"2024-11-23",
"New documentation: <a href=\"/duckdb/\">DuckDB</a>"

@ -32,7 +32,7 @@ app.templates.aboutPage = function () {
<h2 class="_block-heading" id="copyright">Copyright and License</h2>
<p class="_note">
<strong>Copyright 2013&ndash;2024 Thibaut Courouble and <a href="https://github.com/freeCodeCamp/devdocs/graphs/contributors">other contributors</a></strong><br>
<strong>Copyright 2013&ndash;2025 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>

@ -96,16 +96,9 @@ app.views.EntryPage = class EntryPage extends app.View {
return content;
}
const links = (() => {
const result = [];
for (var link in this.entry.doc.links) {
var url = this.entry.doc.links[link];
result.push(
`<a href="${url}" class="_links-link">${EntryPage.LINKS[link]}</a>`,
);
}
return result;
})();
const links = Object.entries(this.entry.doc.links).map(([link, url]) => {
return `<a href="${url}" class="_links-link">${EntryPage.LINKS[link]}</a>`;
});
return `<p class="_links">${links.join("")}</p>${content}`;
}
@ -203,8 +196,8 @@ app.views.EntryPage = class EntryPage extends app.View {
}
restore() {
let path;
if (this.cacheMap[(path = this.entry.filePath())]) {
const path = this.entry.filePath();
if (this.cacheMap[[path]]) {
this.render(this.cacheMap[path], true);
return true;
}
@ -217,18 +210,17 @@ app.views.EntryPage = class EntryPage extends app.View {
this.load();
} else if (target.classList.contains("_pre-clip")) {
$.stopEvent(event);
target.classList.add(
$.copyToClipboard(target.parentNode.textContent)
? "_pre-clip-success"
: "_pre-clip-error",
navigator.clipboard.writeText(target.parentNode.textContent).then(
() => target.classList.add("_pre-clip-success"),
() => target.classList.add("_pre-clip-error"),
);
setTimeout(() => (target.className = "_pre-clip"), 2000);
}
}
onAltC() {
let link;
if (!(link = this.find("._attribution:last-child ._attribution-link"))) {
const link = this.find("._attribution:last-child ._attribution-link");
if (!link) {
return;
}
console.log(link.href + location.hash);
@ -236,8 +228,8 @@ app.views.EntryPage = class EntryPage extends app.View {
}
onAltO() {
let link;
if (!(link = this.find("._attribution:last-child ._attribution-link"))) {
const link = this.find("._attribution:last-child ._attribution-link");
if (!link) {
return;
}
this.delay(() => $.popup(link.href + location.hash));

@ -3,7 +3,7 @@
//= depend_on sprites/docs.json
/*!
* Copyright 2013-2024 Thibaut Courouble and other contributors
* Copyright 2013-2025 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:
@ -97,6 +97,7 @@
'pages/nushell',
'pages/octave',
'pages/openjdk',
'pages/openlayers',
'pages/perl',
'pages/phalcon',
'pages/phaser',

@ -28,6 +28,9 @@
p > code, li > code { @extend %label; }
details { @extend %box; }
summary > div { display: inline; }
> .note,
.notecard, // MDN 2021
.notice,

@ -0,0 +1,10 @@
._openlayers {
@extend %simple;
.nameContainer {
@extend %block-label;
> * { display: inline-block; margin: 0; }
> .tag-source { float: right; }
}
.card { @extend %box; margin-bottom: 1rem; padding: 1rem; }
.signature, .type-signature { @extend %code; }
}

@ -254,6 +254,17 @@ done
### Nokogiri
### Ruby / Minitest
```sh
git clone https://github.com/seattlerb/minitest
cd minitest/
bundle install
bundle add rdoc hoe
bundle exec rak docs
cd ..
cp -r minitest/docs $DEVDOCS/docs/minitest
```
### Ruby on Rails
* Download a release at https://github.com/rails/rails/releases or clone https://github.com/rails/rails.git (checkout to the branch of the rails' version that is going to be scraped)
* Open `railties/lib/rails/api/task.rb` and comment out any code related to sdoc (`configure_sdoc`)

@ -7,8 +7,10 @@ module Docs
css('devsite-feature-tooltip').remove
css('devsite-thumb-rating').remove
css('devsite-toc').remove
css('devsite-feedback').remove
css('a.button-with-icon').remove
css('button.devsite-heading-link').remove
css('.devsite-article-body > span:first-child[style="float: right; line-height: 36px"]').remove
doc
end

@ -42,7 +42,7 @@ module Docs
def fix_url(url)
if context[:redirections]
url = URL.parse(url)
path = url.path.downcase
path = url.path ? url.path.downcase : nil
if context[:redirections].key?(path)
url.path = context[:redirections][path]

@ -16,8 +16,12 @@ module Docs
name
else
return at_css('h1').content.strip unless at_css('.type-name')
name = at_css('.type-name').children.last.content.strip
name = at_css('.type-name').children.reject { |n| n.matches?('.kind') }
name.map! { |n| n.text.strip }
name.reject! &:empty?
name = name.join
name.remove! %r{\(.*\)}
name.strip!
name
end
end

@ -34,7 +34,9 @@ module Docs
node.name = 'h3'
node['id'] = id
source_href = node.at_css('a.icon-action[title="View Source"]').attr('href')
a = node.at_css('a.icon-action[title="View Source"]')
a ||= node.at_css('a.icon-action[aria-label="View Source"]')
source_href = a.attr('href')
node.content = node.at_css('.signature').inner_text
node << %(<a href="#{source_href}" class="source">Source</a>)

@ -3,7 +3,7 @@ module Docs
class CleanHtmlFilter < Filter
def call
i = 1
n = at_css("#navmenu a[href='#{result[:path].split('/').last}']").parent
n = at_css("#navmenu .submenu-content a[href='#{result[:path].split('/').last}']").parent
i += 1 while n && n = n.previous_element
at_css('h1')['data-level'] = i

@ -0,0 +1,18 @@
module Docs
class Openlayers
class CleanHtmlFilter < Filter
def call
@doc = at_css('section')
at_css('h2').name = 'h1' if at_css('h2')
css('pre.prettyprint').each do |node|
node['data-language'] = node['class'].include?('html') ? 'html' : 'js'
node.content = node.content
end
doc
end
end
end
end

@ -0,0 +1,23 @@
module Docs
class Openlayers
class EntriesFilter < Docs::EntriesFilter
def get_name
at_css('h2').text.split('~').last.strip
end
def get_type
slug[/ol_([^_]+)_/, 1] or 'ol'
end
def additional_entries
css('h4.name').each_with_object [] do |node, entries|
node['id'] = node.previous_element['id']
next if node.at_css('.inherited')
name = node.children.find {|n| n.text? }.text.strip
name.prepend "#{self.name}."
entries << [name, node['id']]
end
end
end
end
end

@ -2,7 +2,7 @@ module Docs
class Phpunit
class CleanHtmlFilter < Filter
def call
@doc = at_css('.section') if not root_page?
@doc = at_css('section') if not root_page?
css('pre').each do |node|
node['class'] = 'highlight'

@ -13,8 +13,11 @@ module Docs
meta = Nokogiri::XML::Node.new 'dl', doc.document
meta['class'] = 'meta'
if parent = at_css('#parent-class-section')
meta << %(<dt>Parent:</dt><dd class="meta-parent">#{parent.at_css('.link').inner_html.strip}</dd>)
parent = at_css('#parent-class-section')
if parent && link = parent.at_css('.link')
meta << %(<dt>Parent:</dt><dd class="meta-parent">#{link.inner_html.strip}</dd>)
elsif parent && link = parent.at_css('a')
meta << %(<dt>Parent:</dt><dd class="meta-parent">#{link.to_html}</dd>)
end
if includes = at_css('#includes-section')

@ -71,7 +71,7 @@ module Docs
# name from the HTML because companion object classes may be broken out into
# their own entries (by the source documentation). When that happens,
# we want to group these classes (like `scala.reflect.api.Annotations.Annotation`)
# under the package name, and not the fully-qualfied name which would
# under the package name, and not the fully-qualified name which would
# include the companion object.
def package_name
name = package_drop_last(slug_parts)

@ -3,7 +3,8 @@ module Docs
class EntriesFilter < Docs::EntriesFilter
def get_name
name = at_css('h1').content.strip
name.remove! "\u{00b6}"
name.delete_suffix! ""
name.delete_suffix! "#"
if slug.start_with?('api')
name.remove! 'Module: '

@ -2,6 +2,7 @@ module Docs
class ScikitLearn
class CleanHtmlFilter < Filter
def call
@doc = at_css('main article', 'main')
if root_page?
css('.row').each do |node|
html = '<dl>'

@ -46,6 +46,9 @@ module Docs
node.replace("<p>#{node.to_html}</p>")
end
css('span[slot="popout-heading"]').remove
css('span[slot="popout-contents"]').remove
doc
end
end

@ -248,6 +248,10 @@ module Docs
"text": "usePreferredReducedMotion",
"link": "/core/usePreferredReducedMotion/"
},
{
"text": "usePreferredReducedTransparency",
"link": "/core/usePreferredReducedTransparency/"
},
{
"text": "useScreenOrientation",
"link": "/core/useScreenOrientation/"
@ -264,6 +268,10 @@ module Docs
"text": "useShare",
"link": "/core/useShare/"
},
{
"text": "useSSRWidth",
"link": "/core/useSSRWidth/"
},
{
"text": "useStyleTag",
"link": "/core/useStyleTag/"
@ -313,6 +321,10 @@ module Docs
"text": "onClickOutside",
"link": "/core/onClickOutside/"
},
{
"text": "onElementRemoval",
"link": "/core/onElementRemoval/"
},
{
"text": "onKeyStroke",
"link": "/core/onKeyStroke/"
@ -788,6 +800,10 @@ module Docs
{
"text": "Time",
"items": [
{
"text": "useCountdown",
"link": "/core/useCountdown/"
},
{
"text": "useDateFormat",
"link": "/shared/useDateFormat/"

@ -12,6 +12,11 @@ module Docs
Licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License.
HTML
version '8.0' do
self.release = '8.0.0'
self.base_url = 'https://bazel.build/versions/8.0.0/reference/be/'
end
version '7.0' do
self.release = '7.0.0'
self.base_url = 'https://bazel.build/versions/7.0.0/reference/be/'

@ -2,7 +2,7 @@ module Docs
class Crystal < UrlScraper
include MultipleBaseUrls
self.type = 'crystal'
self.release = '1.14.0'
self.release = '1.15.1'
self.base_urls = [
"https://crystal-lang.org/api/#{release}/",
"https://crystal-lang.org/reference/#{release[0..2]}/",
@ -21,6 +21,7 @@ module Docs
options[:skip_patterns] = [
%r{\ACrystal/System/},
%r{\ACrystal/PointerPairingHeap/},
%r{\AIO/Evented.html\z},
%r{\ARegex/PCRE2.html\z}
]
@ -34,7 +35,7 @@ module Docs
HTML
else
<<-HTML
&copy; 2012&ndash;2024 Manas Technology Solutions.<br>
&copy; 2012&ndash;2025 Manas Technology Solutions.<br>
Licensed under the Apache License, Version 2.0.
HTML
end

@ -96,7 +96,7 @@ module Docs
def get_latest_version(opts)
doc = fetch_doc('https://docs.docker.com/engine/release-notes/', opts)
latest_version = doc.at_css('.DocSearch-content > h2 > a').content.strip
latest_version = doc.at_css('h2.scroll-mt-20 > a').content.strip
latest_version.rpartition(' ')[-1]
end
end

@ -30,6 +30,18 @@ module Docs
"https://hexdocs.pm/mix/#{self.class.release}/Mix.html" ]
end
version '1.18' do
self.release = '1.18.1'
self.base_urls = [
"https://hexdocs.pm/elixir/#{release}/",
"https://hexdocs.pm/eex/#{release}/",
"https://hexdocs.pm/ex_unit/#{release}/",
"https://hexdocs.pm/iex/#{release}/",
"https://hexdocs.pm/logger/#{release}/",
"https://hexdocs.pm/mix/#{release}/"
]
end
version '1.17' do
self.release = '1.17.2'
self.base_urls = [

@ -2,7 +2,7 @@ module Docs
class Express < UrlScraper
self.name = 'Express'
self.type = 'express'
self.release = '4.18.1'
self.release = '4.21.2'
self.base_url = 'https://expressjs.com/en/'
self.root_path = '4x/api.html'
self.initial_paths = %w(

@ -2,7 +2,7 @@ module Docs
class Fastapi < UrlScraper
self.name = 'FastAPI'
self.type = 'fastapi'
self.release = '0.111.1'
self.release = '0.115.6'
self.base_url = 'https://fastapi.tiangolo.com/'
self.root_path = '/'
self.links = {

@ -18,6 +18,11 @@ module Docs
Licensed under the BSD 3-clause License.
HTML
version do
self.release = '3.1.1'
self.base_url = "https://flask.palletsprojects.com/en/stable/"
end
version '3.0' do
self.release = '3.0.x'
self.base_url = "https://flask.palletsprojects.com/en/#{self.release}/"

@ -1,7 +1,7 @@
module Docs
class Git < UrlScraper
self.type = 'git'
self.release = '2.47.1'
self.release = '2.48.1'
self.base_url = 'https://git-scm.com/docs'
self.initial_paths = %w(/git.html)
self.links = {

@ -1,7 +1,7 @@
module Docs
class Go < UrlScraper
self.type = 'go'
self.release = '1.23.0'
self.release = '1.24.0'
self.base_url = 'https://golang.org/pkg/'
self.links = {
home: 'https://golang.org/',
@ -10,10 +10,19 @@ module Docs
# Run godoc locally, since https://golang.org/pkg/ redirects to https://pkg.go.dev/std with rate limiting / scraping protection.
# podman run --net host --rm -it docker.io/golang:1.23.0
# podman run --net host --rm -it docker.io/golang:1.24.0
#podman# go install golang.org/x/tools/cmd/godoc@latest
#podman# rm -r /usr/local/go/test/
#podman# godoc -http 0.0.0.0:6060 -v
# or using alpine
# podman run --net host --rm -it alpine:latest
#podman# apk add curl
#podman# curl -LO https://go.dev/dl/go1.24.0.linux-amd64.tar.gz
#podman# tar xf go1.24.0.linux-amd64.tar.gz
#podman# go/bin/go install golang.org/x/tools/cmd/godoc@latest
#podman# /root/go/bin/godoc -http 0.0.0.0:6060 -v
self.base_url = 'http://localhost:6060/pkg/'
html_filters.push 'clean_local_urls'

@ -59,7 +59,7 @@ module Docs
end
version '9' do
self.release = '9.4.2'
self.release = '9.12.1'
self.base_url = "https://downloads.haskell.org/~ghc/#{release}/docs/"
options[:container] = ->(filter) {filter.subpath.start_with?('users_guide') ? '.document' : '#content'}
end

@ -2,7 +2,7 @@ module Docs
class JqueryUi < Jquery
self.name = 'jQuery UI'
self.slug = 'jqueryui'
self.release = '1.13.0'
self.release = '1.14.1'
self.base_url = 'https://api.jqueryui.com'
self.root_path = '/category/all'

@ -1,6 +1,6 @@
module Docs
class Dom < Mdn
# release = '2023-08-20'
# release = '2025-01-30'
self.name = 'Web APIs'
self.slug = 'dom'
self.base_url = 'https://developer.mozilla.org/en-US/docs/Web/API'

@ -3,7 +3,7 @@ module Docs
prepend FixInternalUrlsBehavior
prepend FixRedirectionsBehavior
# release = '2024-11-18'
# release = '2025-01-30'
self.name = 'JavaScript'
self.base_url = 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference'
self.links = {

@ -47,8 +47,7 @@ module Docs
end
def get_latest_version(opts)
doc = fetch_doc('https://docs.meteor.com/#/full/', opts)
doc.at_css('select.version-select > option').content
get_npm_version('meteor', opts)
end
end
end

@ -23,9 +23,7 @@ module Docs
def get_latest_version(opts)
doc = fetch_doc('https://nixos.org/manual/nix/stable/', opts)
json = JSON.parse(doc.at_css('body')['data-nix-channels'])
channel = json.find { |c| c['channel'] == 'stable' }
channel['version']
doc.at_css('a.active')['href'].scan(/([0-9.]+)/)[0][0]
end
end
end

@ -0,0 +1,24 @@
module Docs
class Openlayers < UrlScraper
self.name = 'OpenLayers'
self.type = 'openlayers'
self.slug = 'openlayers'
self.release = '10.4.0'
self.base_url = "https://openlayers.org/en/latest/apidoc/"
self.links = {
home: 'https://openlayers.org/',
code: 'https://github.com/openlayers/openlayers'
}
html_filters.push 'openlayers/entries', 'openlayers/clean_html'
options[:attribution] = <<-HTML
&copy; 2005-present, OpenLayers Contributors All rights reserved.
Licensed under the BSD 2-Clause License.
HTML
def get_latest_version(opts)
get_npm_version('ol', opts)
end
end
end

@ -17,12 +17,21 @@ module Docs
options[:title] = false
options[:attribution] = <<-HTML
&copy; 2005&ndash;2020 Sebastian Bergmann<br>
&copy; 2005&ndash;2025 Sebastian Bergmann<br>
Licensed under the Creative Commons Attribution 3.0 Unported License.
HTML
FILTERS = %w(phpunit/clean_html phpunit/entries title)
version do
self.release = '12.0'
self.base_url = "https://docs.phpunit.de/en/#{release}/"
html_filters.push FILTERS
options[:container] = '.document'
end
version '9' do
self.release = '9.5'
self.base_url = "https://phpunit.readthedocs.io/en/#{release}/"
@ -77,8 +86,8 @@ module Docs
def get_latest_version(opts)
doc = fetch_doc('https://phpunit.readthedocs.io/', opts)
label = doc.at_css('.rst-current-version').content.strip
label.scan(/v: ([0-9.]+)/)[0][0]
label = doc.at_css('meta[name="readthedocs-version-slug"]')["content"]
label
end
end

@ -1,14 +1,9 @@
module Docs
class Minitest < Rdoc
# Instructions:
# 1. Run "gem update rdoc hoe"
# 2. Download the source code at https://github.com/seattlerb/minitest
# 3. Run "rake docs" (in the Minitest directory)
# 4. Copy the "docs" directory to "docs/minitest"
self.name = 'Ruby / Minitest'
self.slug = 'minitest'
self.release = '5.20.0'
self.release = '5.25.4'
self.links = {
code: 'https://github.com/minitest/minitest'
}

@ -75,6 +75,10 @@ module Docs
end
end
version '8.0' do
self.release = '8.0.1'
end
version '7.2' do
self.release = '7.2.1'
end

@ -63,12 +63,16 @@ module Docs
/\AXMP/]
options[:attribution] = <<-HTML
Ruby Core &copy; 1993&ndash;2022 Yukihiro Matsumoto<br>
Ruby Core &copy; 1993&ndash;2024 Yukihiro Matsumoto<br>
Licensed under the Ruby License.<br>
Ruby Standard Library &copy; contributors<br>
Licensed under their own licenses.
HTML
version '3.4' do
self.release = '3.4.1'
end
version '3.3' do
self.release = '3.3.0'
end

@ -22,8 +22,7 @@ module Docs
def get_latest_version(opts)
body = fetch('http://download.redis.io/redis-stable/00-RELEASENOTES', opts)
body = body.lines[1..-1].join
body.scan(/Redis ([0-9.]+)/)[0][0]
body.scan(/Redis Community Edition ([0-9.]+)/)[0][0]
end
private

@ -3,7 +3,7 @@
module Docs
class Rust < UrlScraper
self.type = 'rust'
self.release = '1.83.0'
self.release = '1.84.1'
self.base_url = 'https://doc.rust-lang.org/'
self.root_path = 'book/index.html'
self.initial_paths = %w(

@ -1,7 +1,7 @@
module Docs
class Sass < UrlScraper
self.type = 'yard'
self.release = '1.82.9'
self.release = '1.85.0'
self.base_url = 'https://sass-lang.com/documentation'
self.root_path = 'index.html'
self.links = {
@ -17,16 +17,16 @@ module Docs
options[:trailing_slash] = false
options[:attribution] = <<-HTML
&copy; 2006&ndash;2024 the Sass team, and numerous contributors<br>
&copy; 2006&ndash;2025 the Sass team, and numerous contributors<br>
Licensed under the MIT License.
HTML
private
def get_latest_version(opts)
get_npm_version('sass', opts)
end
private
def parse(response)
response.body.gsub! '<span class="widont">&nbsp;</span>', '&nbsp;'
end

@ -3,8 +3,10 @@ module Docs
self.name = 'scikit-image'
self.slug = 'scikit_image'
self.type = 'sphinx'
self.release = '0.18.1'
self.base_url = 'https://scikit-image.org/docs/0.18.x/'
self.release = '0.25.0'
v = self.release[/\d+\.\d+/]
self.base_url = "https://scikit-image.org/docs/#{v}.x/"
self.initial_paths = %w(/ /api/ /user_guide/)
self.links = {
home: 'https://scikit-image.org/',
code: 'https://github.com/scikit-image/scikit-image'
@ -12,7 +14,7 @@ module Docs
html_filters.push 'scikit_image/entries', 'sphinx/clean_html'
options[:container] = '.span9'
options[:container] = 'main article'
options[:skip] = %w(api_changes.html)
options[:only_patterns] = [/\Aapi/, /\Auser_guide/]

@ -3,8 +3,9 @@ module Docs
self.name = 'scikit-learn'
self.slug = 'scikit_learn'
self.type = 'sphinx'
self.release = '1.1.3'
self.base_url = "https://scikit-learn.org/1.1/"
self.release = '1.6.1'
v = self.release[/\d+\.\d+/]
self.base_url = "https://scikit-learn.org/#{v}/"
self.root_path = 'index.html'
self.force_gzip = true
self.links = {
@ -14,7 +15,6 @@ module Docs
html_filters.push 'scikit_learn/entries', 'scikit_learn/clean_html', 'sphinx/clean_html', 'title'
options[:container] = ->(filter) { filter.root_page? ? 'body > .container' : '#sk-page-content-wrapper > .body' }
options[:skip] = %w(modules/generated/sklearn.experimental.enable_iterative_imputer.html
modules/generated/sklearn.experimental.enable_hist_gradient_boosting.html)
options[:only_patterns] = [/\Amodules/, /\Adatasets/, /\Atutorial/, /\Aauto_examples/]
@ -24,7 +24,7 @@ module Docs
options[:max_image_size] = 256_000
options[:attribution] = <<-HTML
&copy; 2007&ndash;2022 The scikit-learn developers<br>
&copy; 2007&ndash;2025 The scikit-learn developers<br>
Licensed under the 3-clause BSD License.
HTML

@ -19,6 +19,11 @@ module Docs
Code samples licensed under the Apache 2.0 License.
HTML
version do
self.release = "2.18.0"
self.base_url = "https://www.tensorflow.org/api_docs/python/tf"
end
version '2.9' do
self.release = "2.9.1"
self.base_url = "https://www.tensorflow.org/versions/r#{version}/api_docs/python/tf"

@ -3,6 +3,11 @@ module Docs
self.name = 'TensorFlow C++'
self.slug = 'tensorflow_cpp'
version do
self.release = "2.18.0"
self.base_url = "https://www.tensorflow.org/api_docs/cc"
end
version '2.9' do
self.release = "2.9.1"
self.base_url = "https://www.tensorflow.org/versions/r#{version}/api_docs/cc"

@ -1,7 +1,7 @@
module Docs
class Trio < UrlScraper
self.type = 'simple'
self.release = '0.22.2'
self.release = '0.29.0'
self.base_url = "https://trio.readthedocs.io/en/v#{self.release}/"
self.root_path = 'index.html'
self.links = {
@ -25,7 +25,7 @@ module Docs
def get_latest_version(opts)
doc = fetch_doc('https://trio.readthedocs.io/en/stable/', opts)
doc.at_css('.rst-other-versions a[href^="/en/v"]').content[1..-1]
doc.at_css('div.trio-version').content[0..-1]
end
end
end

@ -22,7 +22,7 @@ module Docs
html_filters.push 'vite/entries', 'vite/clean_html'
version do
self.release = '6.0.1'
self.release = '6.1.0'
self.base_url = 'https://vite.dev/'
end

@ -22,7 +22,7 @@ module Docs
Licensed under the MIT License.
HTML
self.release = '12.0.0'
self.release = '12.5.0'
self.base_url = 'https://vueuse.org/'
self.initial_paths = %w(functions.html)
html_filters.push 'vueuse/entries', 'vite/clean_html', 'vueuse/clean_html'

@ -17,6 +17,11 @@ module Docs
Licensed under the BSD 3-clause License.
HTML
version do
self.release = '3.1.1'
self.base_url = "https://werkzeug.palletsprojects.com/en/latest/"
end
version '3.0' do
self.release = '3.0.x'
self.base_url = "https://werkzeug.palletsprojects.com/en/#{self.release}/"

@ -239,7 +239,7 @@ class DocsCLI < Thor
['index.json', 'meta.json'].each do |filename|
json = "https://documents.devdocs.io/#{doc.path}/#{filename}?#{time}"
begin
URI.open(json) do |file|
URI.open(json, "Accept-Encoding" => "identity") do |file|
mutex.synchronize do
path = File.join(dir, filename)
File.write(path, file.read)

Binary file not shown.

After

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 B

@ -0,0 +1,2 @@
https://github.com/openlayers
https://avatars.githubusercontent.com/u/240579?s=64

@ -64,7 +64,7 @@ class ManifestTest < Minitest::Spec
it "includes the doc's meta representation" do
json = manifest.as_json
assert_equal 1, json.length
assert_equal "{\"name\"=>\"Test\", \"db_size\"=>776533, :attribution=>\"foo\", :alias=>nil}", json[0].to_s
assert_equal "{\"name\" => \"Test\", \"db_size\" => 776533, attribution: \"foo\", alias: nil}", json[0].to_s
end
end

Loading…
Cancel
Save