Fix merge conflict

pull/970/head
Jasper van Merle 5 years ago
commit 0574de6812

@ -58,9 +58,20 @@ In addition to the [guidelines for contributing code](#contributing-code-and-fea
## Updating existing documentations
Please don't submit a pull request updating only the version number and/or the attribution of a documentation. Do submit a pull request if a bigger change is required in the scraper and you've verified that it works.
If the latest [documentation versions report](https://github.com/freeCodeCamp/devdocs/issues?utf8=%E2%9C%93&q=Documentation+versions+report+is%3Aissue+author%3Adevdocs-bot+sort%3Acreated-desc) wrongly shows a documentation to be up-to-date, please open an issue or a PR to fix it.
To ask that an existing documentation be updated, first check the latest [documentation versions report](https://github.com/freeCodeCamp/devdocs/issues?utf8=%E2%9C%93&q=Documentation+versions+report+is%3Aissue+author%3Adevdocs-bot+sort%3Acreated-desc). Only create an issue if the documentation has been wrongly marked as up-to-date.
**Important:** PR's that update documentation versions that do not contain the checklist shown to you in section B of the PR template may be closed without review.
Follow the following steps to update documentations to their latest version:
1. Make version/release changes in the scraper file.
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>`.
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. `thor docs:generate` accepts a `--version` argument to specify which version to scrape.
8. Create a PR and make sure to fill the checklist in section B of the PR template (remove the other sections).
## Coding conventions

@ -0,0 +1,31 @@
<!-- Remove the sections that don't apply to your PR. -->
<!-- Replace the `[ ]` with a `[x]` in checklists once youve completed each step. -->
<!-- Please create a draft PR when you haven't completed all steps yet upon creation of the PR. -->
<!-- SECTION A - Adding a new scraper -->
<!-- See https://github.com/freeCodeCamp/devdocs/blob/master/.github/CONTRIBUTING.md#contributing-new-documentations -->
If youre adding a new scraper, please ensure that you have:
- [ ] Tested the scraper on a local copy of DevDocs
- [ ] Ensured that the docs are styled similarly to other docs on DevDocs
<!-- If the docs dont have an icon, delete the next four items: -->
- [ ] Added these files to the <code>public/icons/*your_scraper_name*/</code> directory:
- [ ] `16.png`: a 16×16 pixel icon for the doc
- [ ] `16@2x.png`: a 32×32 pixel icon for the doc
- [ ] `SOURCE`: A text file containing the URL to the page the image can be found on or the URL of the original image itself
<!-- SECTION B - Updating an existing documentation to it's latest version -->
<!-- See https://github.com/freeCodeCamp/devdocs/blob/master/.github/CONTRIBUTING.md#updating-existing-documentations -->
If you're updating an existing documentation to it's latest version, please ensure that you have:
- [ ] Updated the versions and releases in the scraper file
- [ ] Ensured the license is up-to-date and that the documentation's entry in the array in `about_tmpl.coffee` matches it's data in `self.attribution`
- [ ] Ensured the icons and the `SOURCE` file in <code>public/icons/*your_scraper_name*/</code> are up-to-date if the documentation has a custom icon
- [ ] Ensured `self.links` contains up-to-date urls if `self.links` is defined
- [ ] Tested the changes locally to ensure:
- The scraper still works without errors
- The scraped documentation still looks consistent with the rest of DevDocs
- The categorization of entries is still good

@ -1,11 +0,0 @@
If youre adding a new scraper, please ensure that you have:
- [ ] Tested the scraper on a local copy of DevDocs
- [ ] Ensured that the docs are styled similarly to other docs on DevDocs
<!-- If the docs dont have an icon, delete the next four items: -->
- [ ] Added these files to the <code>public/icons/*your_scraper_name*/</code> directory:
- [ ] `16.png`: a 16×16 pixel icon for the doc
- [ ] `16@2x.png`: a 32×32 pixel icon for the doc
- [ ] `SOURCE`: A text file containing the URL to the page the image can be found on or the URL of the original image itself
<!-- Replace the `[ ]` with a `[x]` once youve completed each step. -->

@ -199,6 +199,8 @@ page.track = (fn) ->
return
track = ->
return unless app.config.env == 'production'
consentGiven = Cookies.get('analyticsConsent')
consentAsked = Cookies.get('analyticsConsentAsked')

@ -58,10 +58,12 @@ class app.models.Entry extends app.Model
'crystal': 'cr'
'elixir': 'ex'
'javascript': 'js'
'julia': 'jl'
'jquery': '$'
'knockout.js': 'ko'
'less': 'ls'
'lodash': '_'
'löve': 'love'
'marionette': 'mn'
'markdown': 'md'
'modernizr': 'mdr'

@ -211,8 +211,7 @@ credits = [
'2017 Cypress.io',
'MIT',
'https://raw.githubusercontent.com/cypress-io/cypress-documentation/develop/LICENSE.md'
],
[
], [
'D',
'1999-2018 The D Language Foundation',
'Boost',
@ -232,6 +231,11 @@ credits = [
'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.',
@ -294,9 +298,9 @@ credits = [
'https://www.gnu.org/licenses/fdl-1.3.en.html'
], [
'Git',
'2005-2018 Linus Torvalds and others',
'GPLv2',
'https://raw.githubusercontent.com/git/git/master/COPYING'
'2012-2018 Scott Chacon and others',
'MIT',
'https://raw.githubusercontent.com/git/git-scm.com/master/MIT-LICENSE.txt'
], [
'Go',
'Google, Inc.',
@ -359,8 +363,8 @@ credits = [
'https://raw.githubusercontent.com/jekyll/jekyll/master/LICENSE'
], [
'Jest',
'2014-present Facebook Inc.',
'BSD',
'Facebook, Inc. and its affiliates.',
'MIT',
'https://raw.githubusercontent.com/facebook/jest/master/LICENSE'
], [
'jQuery',
@ -379,7 +383,7 @@ credits = [
'https://raw.githubusercontent.com/jquery/api.jqueryui.com/master/LICENSE.txt'
], [
'Julia',
'2009-2018 Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors',
'2009-2019 Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors',
'MIT',
'https://raw.githubusercontent.com/JuliaLang/julia/master/LICENSE.md'
], [
@ -517,6 +521,11 @@ credits = [
'2008-2017 NumPy Developers',
'NumPy',
'https://raw.githubusercontent.com/numpy/numpy/master/LICENSE.txt'
], [
'Octave',
'1996-2018 John W. Eaton',
'Octave',
'https://octave.org/doc/interpreter/'
], [
'OpenJDK',
'1993-2017, 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.',
@ -567,6 +576,11 @@ credits = [
'2005-2017 Sebastian Bergmann',
'CC BY',
'https://creativecommons.org/licenses/by/3.0/'
], [
'Pony',
'2016-2018, The Pony Developers & 2014-2015, Causality Ltd.',
'BSD',
'https://raw.githubusercontent.com/ponylang/ponyc/master/LICENSE'
], [
'PostgreSQL',
'1996-2018 The PostgreSQL Global Development Group<br>&copy; 1994 The Regents of the University of California',
@ -646,14 +660,18 @@ credits = [
'Rust',
'2010 The Rust Project Developers',
'MIT',
'https://raw.githubusercontent.com/rust-lang/rust/master/LICENSE-MIT'
'https://raw.githubusercontent.com/rust-lang/book/master/LICENSE-MIT'
], [
'RxJS',
'2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors',
'Apache',
'https://raw.githubusercontent.com/ReactiveX/rxjs/master/LICENSE.txt'
], [
'Salt Stack',
'2019 SaltStack',
'Apache',
'https://raw.githubusercontent.com/saltstack/salt/develop/LICENSE'
],
[
], [
'Sass',
'2006-2016 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein',
'MIT',
@ -663,8 +681,7 @@ credits = [
'2002-2019 EPFL, with contributions from Lightbend',
'Apache',
'https://raw.githubusercontent.com/scala/scala-lang/master/license.md'
],
[
], [
'scikit-image',
'2011 the scikit-image team',
'BSD',
@ -714,6 +731,11 @@ credits = [
'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-2018 The Twig Team',
@ -734,16 +756,21 @@ credits = [
'2010-2018 Mitchell Hashimoto',
'MPL',
'https://raw.githubusercontent.com/mitchellh/vagrant/master/website/LICENSE.md'
], [
'Vue.js',
'2013-2018 Evan You, Vue.js contributors',
'MIT',
'https://raw.githubusercontent.com/vuejs/vue/master/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.',
@ -759,8 +786,7 @@ credits = [
'2003-2019 WordPress Foundation',
'GPLv2+',
'https://wordpress.org/about/license/'
],
[
], [
'Yarn',
'2016-present Yarn Contributors',
'BSD',

@ -19,7 +19,7 @@ app.templates.settingsPage = (settings) -> """
<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>
</label>
<label class="_settings-label">
<label class="_settings-label _hide-in-development">
<input type="checkbox" form="settings" name="analyticsConsent"#{if settings.analyticsConsent then ' checked' else ''}>Enable tracking cookies
<small>With this checked, we enable Google Analytics and Gauges to collect anonymous traffic information.</small>
</label>

File diff suppressed because it is too large Load Diff

@ -29,7 +29,8 @@
'components/path',
'components/notice',
'components/prism',
'components/mobile';
'components/mobile',
'components/environment';
@import 'pages/simple',
'pages/angular',
@ -71,11 +72,13 @@
'pages/lua',
'pages/mdn',
'pages/meteor',
'pages/mkdocs',
'pages/modernizr',
'pages/moment',
'pages/nginx',
'pages/node',
'pages/npm',
'pages/octave',
'pages/openjdk',
'pages/perl',
'pages/phalcon',
@ -95,6 +98,7 @@
'pages/rfc',
'pages/rubydoc',
'pages/rust',
'pages/rxjs',
'pages/scala',
'pages/sinon',
'pages/socketio',

@ -0,0 +1,3 @@
._hide-in-development {
<%= App.environment != :production ? 'display: none;' : '' %>
}

@ -0,0 +1,11 @@
._mkdocs {
h2 { @extend %block-heading; }
h3 { @extend %block-label, %label-blue; }
h4 { @extend %block-label; }
blockquote { @extend %note; }
strong { font-weight: var(--bolderFontWeight); }
p > code, li > code { @extend %label; }
}

@ -0,0 +1,9 @@
._octave {
@extend %simple;
dl:not([compact]) > dt { @extend %block-label, %label-blue; }
dl[compact] > dt { @extend %block-label; }
.footnotes-heading { @extend %block-heading; }
}

@ -0,0 +1,24 @@
._rxjs {
@extend %simple;
.pre-title { @extend %pre-heading; }
.breadcrumbs { @extend %note; }
.banner { @extend %note-green; }
code.stable { @extend %label-green; }
code.experimental { @extend %label-orange; }
code.deprecated { @extend %label-red; }
.alert.is-important { @extend %note-red; }
.alert.is-helpful, .breadcrumbs { @extend %note-blue; }
.breadcrumbs { padding-left: 2em; }
img { margin: 1em 0; }
.location-badge {
font-style: italic;
text-align: right;
}
td h3 { margin: 0 !important; }
}

@ -14,10 +14,7 @@ This document is intended for [DevDocs maintainers](#list-of-maintainers).
The process for updating docs is as follow:
- Make version/release changes in the scraper file.
- If needed, update the copyright notice of the documentation in the scraper file (`options[:attribution]`) and the about page (`about_tmpl.coffee`). The copyright notice must be the same as the one on the original documentation.
- Run `thor docs:generate`.
- Make sure the documentation still works well. The `thor docs:generate` command outputs a summary of the changes, which helps identifying issues (e.g. deleted files) and new pages to check out in the app. Verify locally that everything works, especially the files that were created (if any), and that the categorization of entries is still good. Often, updates will require code changes to tweak some new markup in the source website or categorize new entries.
- Follow the checklist in [CONTRIBUTING.md#updating-existing-documentations](../.github/CONTRIBUTING.md#updating-existing-documentations).
- Commit the changes (protip: use the `thor docs:commit` command documented below).
- Optional: do more updates.
- Run `thor docs:upload` (documented below).

@ -0,0 +1,30 @@
module Docs
class DjangoRestFramework
class CleanHtmlFilter < Docs::Filter
def call
css('hr').remove
css('.badges').remove
css('pre').attr('data-language', 'python')
css('h1').remove_attribute('style')
css('.promo a').remove_attribute('style')
# Translate source files links to DevDocs links
links = Nokogiri::XML::Node.new('p', doc)
links['class'] = '_links'
css('a.github').each do |node|
span = node.at_css('span')
node.content = span.content
node['class'] = '_links-link'
links.add_child(node)
end
doc.add_child(links)
doc
end
end
end
end

@ -0,0 +1,59 @@
module Docs
class DjangoRestFramework
class EntriesFilter < Docs::EntriesFilter
def get_name
name = css('h1').first.content
name.slice! 'Tutorial '
name = '0: ' + name if name.include? 'Quickstart'
name
end
def get_type
case subpath
when /\Atutorial/
'Tutorial'
when /\Aapi-guide/
'API Guide'
end
end
def additional_entries
return [] if type == nil || type == 'Tutorial'
# Framework classes are provided in two different ways:
# - as H2's after H1 category titled:
accepted_headers = ['API Reference', 'API Guide']
# - as headers (1 or 2) with these endings:
endings = ['Validator', 'Field', 'View', 'Mixin', 'Default', 'Serializer']
# To avoid writing down all the endings
# and to ensure all entries in API categories are matched
# two different ways of finding them are used
entries = []
local_type = 'Ref: ' + name
in_category = false
css('h1, h2').each do |node|
# Third party category contains entries that could be matched (and shouldn't be)
break if node.content === 'Third party packages'
if in_category
if node.name === 'h1'
in_category = false
next
end
entries << [node.content, node['id'], local_type]
elsif accepted_headers.include? node.content
in_category = true
elsif endings.any? { |word| node.content.ends_with?(word) }
entries << [node.content, node['id'], local_type]
end
end
entries
end
end
end
end

@ -2,6 +2,8 @@ module Docs
class Elixir
class EntriesFilter < Docs::EntriesFilter
def get_name
css('h1 .app-vsn').remove
if current_url.path.start_with?('/getting-started')
at_css('h1').content.strip.remove(/\.\z/)
else
@ -29,6 +31,8 @@ module Docs
else
if name.start_with?('Phoenix')
name.split('.')[0..2].join('.')
elsif name.start_with?('mix ')
'Mix Tasks'
else
name.split('.').first
end

@ -0,0 +1,13 @@
module Docs
class Gcc
class CleanHtmlFilter < Filter
def call
css('pre').each do |node|
node['data-language'] = 'cpp'
end
doc
end
end
end
end

@ -20,15 +20,23 @@ module Docs
def additional_entries
return [] unless !root_page? && self.type == self.name # api page
at_css('.mainContainer ul').css('li > a').map do |node|
name = node.at_css('code').content.strip
entries = []
at_css('.mainContainer ul').css('li > a').each do |node|
code = node.at_css('code')
next if code.nil?
name = code.content.strip
name.sub! %r{\(.*\)}, '()'
name.remove! %r{[\s=<].*}
name.prepend 'jest ' if name.start_with?('--')
name.prepend 'Config: ' if slug == 'configuration'
id = node['href'].remove('#')
[name, id]
entries << [name, id]
end
entries
end
end
end

@ -21,6 +21,7 @@ module Docs
css('pre').each do |node|
node.content = node.content
node['data-language'] = 'julia'
end
doc

@ -16,14 +16,21 @@ module Docs
def additional_entries
return [] unless slug.start_with?('stdlib')
css('.docstring-binding[id]').map do |node|
entries = []
used_names = {}
css('.docstring-binding[id]').each do |node|
name = node.content
name.gsub! '.:', '.'
name.remove! 'Base.'
category = node.parent.at_css('.docstring-category').content
name << '()' if category == 'Function' || category == 'Method'
[name, node['id']]
entries << [name, node['id']] unless used_names.key?(name)
used_names[name] = true
end
entries
end
end
end

@ -0,0 +1,17 @@
module Docs
class Mkdocs
class CleanHtmlFilter < Docs::Filter
def call
css('.toclink').each do |node|
node.parent.content = node.content
end
css('pre').each do |node|
node.content = node.at_css('code').content
end
at_css('#main-content')
end
end
end
end

@ -0,0 +1,46 @@
module Docs
class Octave
class CleanHtmlFilter < Filter
def call
root_page? ? root : other
doc
end
def root
@doc = at_css('.contents')
end
def other
css('.header', 'hr').remove
css('.footnote > h3').each do |node|
node.name = 'h5'
end
at_css('h2, h3, h4').name = 'h1'
css('.example').each do |node|
node.name = 'pre'
node['data-language'] = 'matlab'
node.content = node.content.strip
end
css('a[name] + dl, a[name] + h4').each do |node|
node['id'] = node.previous_element['name']
end
css('dt > a[name]', 'th > a[name]').each do |node|
node.parent['id'] = node['name']
node.parent.content = node.parent.content.strip
end
css('h5 > a').each do |node|
node.parent['id'] = node['name']
node.parent.content = node.content
end
xpath('//td[text()=" " and not(descendant::*)]').remove
end
end
end
end

@ -0,0 +1,22 @@
module Docs
class Octave
class EntriesFilter < Docs::EntriesFilter
def get_name
at_css('h1').content.sub(/(A?[0-9.]+ )/, '')
end
def get_type
return 'Manual: Appendices' if name.start_with?('Appendix')
return 'Manual: Indexes' if name.end_with?('Index')
'Manual'
end
def additional_entries
css('dl:not([compact]) > dt').each_with_object [] do |node, entries|
name = node.content.gsub(/[A-z0-9\,… ]*\=/, '').strip.split(' ')[0]
entries << [name, node['id'], 'Functions'] unless node['id'] =~ /-\d+\Z/
end
end
end
end
end

@ -0,0 +1,16 @@
module Docs
class Pony
class CleanHtmlFilter < Filter
def call
css('.headerlink').remove
css('hr').remove
css('pre').each do |node|
node.content = node.content
end
doc
end
end
end
end

@ -0,0 +1,35 @@
module Docs
class Pony
class EntriesFilter < Docs::EntriesFilter
def get_name
title = context[:html_title].sub(/ - .*/, '').split(' ').last
title = "1. #{type}" if title == 'Package'
title
end
def get_type
subpath.split(/-([^a-z])/)[0][0..-1].sub('-', '/')
end
def additional_entries
return [] if root_page? || name.start_with?("1. ")
entries = []
css('h3').each do |node|
member_name = node.content
is_field = member_name.start_with?('let ')
member_name = member_name[4..-1] if is_field
member_name = member_name.scan(/^([a-zA-Z0-9_]+)/)[0][0]
member_name += '()' unless is_field
entries << ["#{name}.#{member_name}", node['id']]
end
entries
end
end
end
end

@ -34,9 +34,11 @@ module Docs
end
css('a.header').each do |node|
unless node.first_element_child.nil?
node.first_element_child['id'] = node['name'] || node['id']
node.before(node.children).remove
end
end
css('.docblock > h1:not(.section-header)').each { |node| node.name = 'h4' }
css('h2.section-header').each { |node| node.name = 'h3' }
@ -53,7 +55,7 @@ module Docs
end
css('h1 > a', 'h2 > a', 'h3 > a', 'h4 > a', 'h5 > a').each do |node|
node.before(node.children).remove
node.before(node.children).remove if node.parent.at_css('.srclink').nil?
end
css('pre > code').each do |node|

@ -0,0 +1,139 @@
module Docs
class Rxjs
class CleanHtmlFilter < Filter
def call
if root_page?
css('.card-container').remove
at_css('h1').content = 'RxJS Documentation'
end
if at_css('h1').nil?
title = subpath.rpartition('/').last.titleize
doc.prepend_child("<h1>#{title}</h1>")
end
css('br', 'hr', '.material-icons', '.header-link', '.breadcrumb').remove
css('.content', 'article', '.api-header', 'section', '.instance-member').each do |node|
node.before(node.children).remove
end
css('label', 'h2 > em', 'h3 > em').each do |node|
node.name = 'code'
end
css('h1 + code').each do |node|
node.before('<p></p>')
while node.next_element.name == 'code'
node.previous_element << ' '
node.previous_element << node.next_element
end
node.previous_element.prepend_child(node)
end
css('td h3', '.l-sub-section > h3', '.alert h3', '.row-margin > h3', '.api-heading ~ h3', '.api-heading + h2', '.metadata-member h3').each do |node|
node.name = 'h4'
end
css('.l-sub-section', '.alert', '.banner').each do |node|
node.name = 'blockquote'
end
css('.file').each do |node|
node.content = node.content.strip
end
css('.filetree .children').each do |node|
node.css('.file').each do |n|
n.content = " #{n.content}"
end
end
css('.filetree').each do |node|
node.content = node.css('.file').map(&:inner_html).join("\n")
node.name = 'pre'
node.remove_attribute('class')
end
css('pre').each do |node|
node.content = node.content.strip
node['data-language'] = 'typescript' if node['path'].try(:ends_with?, '.ts')
node['data-language'] = 'html' if node['path'].try(:ends_with?, '.html')
node['data-language'] = 'css' if node['path'].try(:ends_with?, '.css')
node['data-language'] = 'js' if node['path'].try(:ends_with?, '.js')
node['data-language'] = 'json' if node['path'].try(:ends_with?, '.json')
node['data-language'] = node['language'].sub(/\Ats/, 'typescript').strip if node['language']
node['data-language'] ||= 'typescript' if node.content.start_with?('@')
node.before(%(<div class="pre-title">#{node['title']}</div>)) if node['title']
if node['class'] && node['class'].include?('api-heading')
node.name = 'h3'
unless node.ancestors('.instance-method').empty?
matches = node.inner_html.scan(/([^(& ]+)[(&]/)
unless matches.empty? || matches[0][0] == 'constructor'
node['name'] = matches[0][0]
node['id'] = node['name'].downcase + '-'
end
end
node.inner_html = "<code>#{node.inner_html}</code>"
end
node.remove_attribute('path')
node.remove_attribute('region')
node.remove_attribute('linenums')
node.remove_attribute('title')
node.remove_attribute('language')
node.remove_attribute('hidecopy')
node.remove_attribute('class')
end
css('td > .overloads').each do |node|
node.replace node.at_css('.detail-contents')
end
css('td.short-description p').each do |node|
signature = node.parent.parent.next_element.at_css('h3[id]')
signature.after(node) unless signature.nil?
end
css('.method-table').each do |node|
node.replace node.at_css('tbody')
end
css('.api-body > table > caption').each do |node|
node.name = 'center'
lift_out_of_table node
end
css('.api-body > table > tbody > tr:not([class]) > td > *').each do |node|
lift_out_of_table node
end
css('.api-body > table').each do |node|
node.remove if node.content.strip.blank?
end
css('h1[class]').remove_attr('class')
css('table[class]').remove_attr('class')
css('table[width]').remove_attr('width')
css('tr[style]').remove_attr('style')
css('code code').each do |node|
node.before(node.children).remove
end
doc
end
def lift_out_of_table(node)
table = node.ancestors('table').first
table.previous_element.after(node)
end
end
end
end

@ -0,0 +1,29 @@
module Docs
class Rxjs
class EntriesFilter < Docs::EntriesFilter
def get_name
title = at_css('h1')
name = title.nil? ? subpath.rpartition('/').last.titleize : title.content
name.prepend "#{$1}. " if subpath =~ /\-pt(\d+)/
name += '()' unless at_css('.api-type-label.function').nil?
name
end
def get_type
if slug.start_with?('guide')
'Guide'
elsif slug.start_with?('api/')
slug.split('/').second
else
'Miscellaneous'
end
end
def additional_entries
css('h3[id]').map do |node|
["#{name}.#{node['name']}()", node['id']]
end
end
end
end
end

@ -0,0 +1,58 @@
module Docs
class Trio
class CleanHtmlFilter < Filter
def call
@doc = at_css('div[role="main"]')
css('.section, [itemprop=articleBody]').each do |node|
node.replace node.children
end
css('.headerlink').remove
css('dt').each do |node|
node.name = 'h3'
if node.parent.classes.include? 'field-list'
node.name = 'h4'
node['style'] = 'margin: 0'
if node.text == 'Parameters' or node.text == 'Raises'
node.next_element.css('strong').each do |n|
n.name = 'code'
end
end
else
code = doc.document.create_element 'code'
if em = node.at_css('.property')
code.inner_html = "<em>#{em.text.strip}</em> "
em.remove
end
code.inner_html += node.inner_text.strip
node.inner_html = code
end
end
css('pre').each do |node|
node.content = node.content.strip
classes = node.parent.parent.classes
if classes.include? 'highlight-python3'
node['data-language'] = 'python'
end
node.parent.parent.replace(node)
end
css('.admonition').each do |node|
node.name = 'blockquote'
node.at_css('.admonition-title').name = 'h4'
end
doc
end
end
end
end

@ -0,0 +1,48 @@
module Docs
class Trio
class EntriesFilter < Docs::EntriesFilter
def get_name
at_css('h1').text[0...-1]
end
def get_type
at_css('h1').text[0...-1]
end
def additional_entries
css('.descname').each_with_object [] do |node, entries|
name = node.text
if node.previous.classes.include? 'descclassname'
name = node.previous.text + name
end
name.strip!
dl = node.parent.parent
if dl.classes.include?('attribute') \
or dl.classes.include?('method') \
or dl.classes.include?('data')
parent = dl.parent.previous_element
cls = ''
if n = parent.at_css('.descclassname')
cls += n.text
end
if n = parent.at_css('.descname')
if n.text == "The nursery interface"
cls += "Nursery."
else
cls += n.text + '.'
end
end
name = cls + name
end
entries << [name, node.parent['id']]
end
end
end
end
end

@ -16,10 +16,19 @@ module Docs
node['data-language'] = node['class'][/highlight (\w+)/, 1]
end
css('pre').each do |node|
node.content = node.content.strip
node['data-language'] = 'javascript'
end
css('iframe').each do |node|
node['sandbox'] = 'allow-forms allow-scripts allow-same-origin'
end
css('details').each do |node|
node.name = 'div'
end
doc
end
end

@ -2,11 +2,16 @@ module Docs
class Vue
class EntriesFilter < Docs::EntriesFilter
def get_name
if slug == 'api/'
if slug == 'api/' || slug == 'api/index'
'API'
elsif slug == 'style-guide/'
'Style Guide'
else
name = at_css('.content h1').content
node = at_css(".sidebar .menu-root a[href='#{File.basename(slug)}']")
return name if node.nil?
index = node.parent.parent.css('> li > a').to_a.index(node)
name.prepend "#{index + 1}. " if index
name
@ -16,6 +21,8 @@ module Docs
def get_type
if slug.start_with?('guide')
'Guide'
elsif slug == 'style-guide/'
'Style Guide'
else
'API'
end
@ -31,7 +38,15 @@ module Docs
else
name = node.content.strip
name.sub! %r{\(.*\)}, '()'
entries << [name, node['id'], "API: #{type}"]
name.sub! /(essential|strongly recommended|recommended|use with caution)\Z/, ''
current_type = "API: #{type}"
if slug == 'style-guide/'
current_type = "Style Guide: "
current_type += type.sub(/( Rules: )/, ': ').split('(')[0]
end
entries << [name, node['id'], current_type]
end
end
end

@ -0,0 +1,17 @@
module Docs
class Vuex
class CleanHtmlFilter < Filter
def call
@doc = at_css('.content')
# Remove video from root page
css('a[href="#"]').remove if root_page?
# Remove unneeded elements
css('.header-anchor').remove
doc
end
end
end
end

@ -0,0 +1,69 @@
module Docs
class Vuex
class EntriesFilter < Docs::EntriesFilter
def get_name
name = at_css('h1').content
name.remove! '# '
# Add index on guides
unless subpath.start_with?('api')
sidebar_link = at_css('.sidebar-link.active')
all_links = css('.sidebar-link:not([href="/"]):not([href="../index"])')
index = all_links.index(sidebar_link)
name.prepend "#{index + 1}. " if index
end
name
end
def get_type
'Guide'
end
def include_default_entry?
name != 'API Reference'
end
def additional_entries
return [] unless subpath.start_with?('api')
entries = [
['Component Binding Helpers', 'component-binding-helpers', 'API Reference'],
['Store', 'vuex-store', 'API Reference'],
]
css('h3').each do |node|
entry_name = node.content.strip
# Get the previous h2 title
title = node
title = title.previous_element until title.name == 'h2'
title = title.content.strip
title.remove! '# '
entry_name.remove! '# '
unless entry_name.start_with?('router.')
case title
when "Vuex.Store Constructor Options"
entry_name = "StoreOptions.#{entry_name}"
when "Vuex.Store Instance Properties"
entry_name = "Vuex.Store.#{entry_name}"
when "Vuex.Store Instance Methods"
entry_name = "Vuex.Store.#{entry_name}()"
when "Component Binding Helpers"
entry_name = "#{entry_name}()"
end
end
entries << [entry_name, node['id'], 'API Reference']
end
entries
end
end
end
end

@ -27,6 +27,9 @@ module Docs
css('a.toc', '.nav-tabs', '#select-platform', '.guide-controls + .list-group', '.guide-controls').remove
css('.install-select-os', '#install-instructions > .install-os-instructions:first-child').remove
css('.install-os-instructions[style]').remove_attribute('style')
css('.guide-content', '.tabs', '.tab-content').each do |node|
node.before(node.children).remove
end

@ -32,27 +32,27 @@ module Docs
version '2.8' do
self.release = '2.8.3'
self.base_url = 'https://docs.ansible.com/ansible/2.7/'
self.base_url = "https://docs.ansible.com/ansible/#{version}/"
end
version '2.7' do
self.release = '2.7.12'
self.base_url = 'https://docs.ansible.com/ansible/2.7/'
self.base_url = "https://docs.ansible.com/ansible/#{version}/"
end
version '2.6' do
self.release = '2.6.18'
self.base_url = 'https://docs.ansible.com/ansible/2.6/'
self.base_url = "https://docs.ansible.com/ansible/#{version}/"
end
version '2.5' do
self.release = '2.5.15'
self.base_url = 'https://docs.ansible.com/ansible/2.5/'
self.base_url = "https://docs.ansible.com/ansible/#{version}/"
end
version '2.4' do
self.release = '2.4.6'
self.base_url = 'https://docs.ansible.com/ansible/2.4/'
self.base_url = "https://docs.ansible.com/ansible/#{version}/"
options[:skip] = %w(
glossary.html

@ -1,7 +1,7 @@
module Docs
class Git < UrlScraper
self.type = 'git'
self.release = '2.19.1'
self.release = '2.23.0'
self.base_url = 'https://git-scm.com/docs'
self.initial_paths = %w(/git.html)
self.links = {
@ -16,8 +16,8 @@ module Docs
options[:skip] = %w(/howto-index.html)
options[:attribution] = <<-HTML
&copy; 2005&ndash;2018 Linus Torvalds and others<br>
Licensed under the GNU General Public License version 2.
&copy; 2012&ndash;2018 Scott Chacon and others<br>
Licensed under the MIT License.
HTML
def get_latest_version(opts)

@ -6,7 +6,7 @@ module Docs
home: 'https://gcc.gnu.org/'
}
html_filters.push 'title'
html_filters.push 'gcc/clean_html', 'title'
options[:root_title] = false
options[:title] = false
@ -46,13 +46,37 @@ module Docs
'Wtrigraphs.html' => 'Invocation.html'
}
version '9' do
self.release = '9.2.0'
self.base_url = "https://gcc.gnu.org/onlinedocs/gcc-#{release}/gcc/"
end
version '9 CPP' do
self.release = '9.2.0'
self.base_url = "https://gcc.gnu.org/onlinedocs/gcc-#{release}/cpp/"
options[:replace_paths] = CPP_PATHS
end
version '8' do
self.release = '8.3.0'
self.base_url = "https://gcc.gnu.org/onlinedocs/gcc-#{release}/gcc/"
end
version '8 CPP' do
self.release = '8.3.0'
self.base_url = "https://gcc.gnu.org/onlinedocs/gcc-#{release}/cpp/"
options[:replace_paths] = CPP_PATHS
end
version '7' do
self.release = '7.3.0'
self.release = '7.4.0'
self.base_url = "https://gcc.gnu.org/onlinedocs/gcc-#{release}/gcc/"
end
version '7 CPP' do
self.release = '7.3.0'
self.release = '7.4.0'
self.base_url = "https://gcc.gnu.org/onlinedocs/gcc-#{release}/cpp/"
options[:replace_paths] = CPP_PATHS

@ -1,11 +1,11 @@
module Docs
class Jest < UrlScraper
self.type = 'simple'
self.release = '23.5.0'
self.release = '24.9'
self.base_url = 'https://jestjs.io/docs/en/'
self.root_path = 'getting-started'
self.links = {
home: 'https://facebook.github.io/jest/',
home: 'https://jestjs.io/',
code: 'https://github.com/facebook/jest'
}
@ -14,8 +14,8 @@ module Docs
options[:container] = '.docMainWrapper'
options[:attribution] = <<-HTML
&copy; 2014&ndash;present Facebook Inc.<br>
Licensed under the BSD License.
&copy; 2019 Facebook, Inc. and its affiliates.<br>
Licensed under the MIT License.
HTML
def get_latest_version(opts)

@ -8,12 +8,32 @@ module Docs
options[:only_patterns] = [/\Amanual\//, /\Astdlib\//]
options[:attribution] = <<-HTML
&copy; 2009&ndash;2018 Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors<br>
&copy; 2009&ndash;2019 Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors<br>
Licensed under the MIT License.
HTML
version '1.2' do
self.release = '1.2.0'
self.base_url = "https://docs.julialang.org/en/v#{release}/"
self.type = 'julia'
html_filters.push 'julia/entries', 'julia/clean_html'
options[:container] = '#docs'
end
version '1.1' do
self.release = '1.1.1'
self.base_url = "https://docs.julialang.org/en/v#{release}/"
self.type = 'julia'
html_filters.push 'julia/entries', 'julia/clean_html'
options[:container] = '#docs'
end
version '1.0' do
self.release = '1.0.1'
self.release = '1.0.4'
self.base_url = "https://docs.julialang.org/en/v#{release}/"
self.type = 'julia'

@ -0,0 +1,29 @@
module Docs
class DjangoRestFramework < Mkdocs
self.name = 'Django REST Framework'
self.release = '3.9.3'
self.slug = 'django_rest_framework'
self.base_url = 'https://www.django-rest-framework.org/'
self.root_path = 'index.html'
self.links = {
home: 'https://www.django-rest-framework.org/',
code: 'https://github.com/encode/django-rest-framework'
}
html_filters.push 'django_rest_framework/clean_html', 'django_rest_framework/entries'
options[:skip_patterns] = [
/\Atopics\//,
/\Acommunity\//,
]
options[:attribution] = <<-HTML
Copyright &copy; 2011&ndash;present Encode OSS Ltd.<br>
Licensed under the BSD License.
HTML
def get_latest_version(opts)
get_latest_github_release('encode', 'django-rest-framework', opts)
end
end
end

@ -0,0 +1,19 @@
module Docs
class Mkdocs < UrlScraper
self.abstract = true
self.type = 'mkdocs'
html_filters.push 'mkdocs/clean_html'
private
def handle_response(response)
# Some scrapped urls don't have ending slash
# which leads to page duplication
if !response.url.path.ends_with?('/') && !response.url.path.ends_with?('index.html')
response.url.path << '/'
end
super
end
end
end

@ -0,0 +1,38 @@
module Docs
class Octave < UrlScraper
self.name = 'Octave'
self.type = 'octave'
self.release = '5.1.0'
self.base_url = 'https://octave.org/doc/interpreter/'
self.root_path = 'index.html'
self.links = {
home: 'http://www.octave.org/',
code: 'http://www.octave.org/hg/octave'
}
html_filters.push 'octave/clean_html', 'octave/entries', 'title'
options[:skip] = %w(
Copying.html
Preface.html
Acknowledgements.html
Citing-Octave-in-Publications.html
How-You-Can-Contribute-to-Octave.html
Distribution.html)
options[:title] = false
options[:root_title] = 'GNU Octave'
options[:attribution] = <<-HTML
&copy; 1996&ndash;2018 John W. Eaton<br>
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.<br/>
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.</br>
Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions.
HTML
def get_latest_version(opts)
doc = fetch_doc('https://octave.org/doc/interpreter/', opts)
doc.at_css('h1').content.scan(/([0-9.]+)/)[0][0]
end
end
end

@ -0,0 +1,27 @@
module Docs
class Pony < UrlScraper
self.type = 'simple'
self.release = '0.30.0'
self.base_url = 'https://stdlib.ponylang.io/'
self.links = {
home: 'https://www.ponylang.io/',
code: 'https://github.com/ponylang/ponyc'
}
html_filters.push 'pony/clean_html', 'pony/entries'
options[:attribution] = <<-HTML
&copy; 2016-2018, The Pony Developers<br>
&copy; 2014-2015, Causality Ltd.<br>
Licensed under the BSD 2-Clause License.
HTML
options[:container] = 'article'
options[:trailing_slash] = false
options[:skip_patterns] = [/src/, /stdlib--index/]
def get_latest_version(opts)
get_latest_github_release('ponylang', 'ponyc', opts)
end
end
end

@ -69,6 +69,10 @@ module Docs
Licensed under their own licenses.
HTML
version '2.6' do
self.release = '2.6.3'
end
version '2.5' do
self.release = '2.5.3'
end

@ -3,9 +3,9 @@
module Docs
class Rust < UrlScraper
self.type = 'rust'
self.release = '1.30.1'
self.release = '1.37.0'
self.base_url = 'https://doc.rust-lang.org/'
self.root_path = 'book/second-edition/index.html'
self.root_path = 'book/index.html'
self.initial_paths = %w(
reference/introduction.html
collections/index.html
@ -19,13 +19,13 @@ module Docs
html_filters.push 'rust/entries', 'rust/clean_html'
options[:only_patterns] = [
/\Abook\/second-edition\//,
/\Abook\//,
/\Areference\//,
/\Acollections\//,
/\Astd\// ]
options[:skip] = %w(book/second-edition/README.html)
options[:skip_patterns] = [/(?<!\.html)\z/, /\/print\.html/]
options[:skip] = %w(book/README.html book/ffi.html)
options[:skip_patterns] = [/(?<!\.html)\z/, /\/print\.html/, /\Abook\/second-edition\//]
options[:fix_urls] = ->(url) do
url.sub! %r{(#{Rust.base_url}.+/)\z}, '\1index.html'

@ -0,0 +1,94 @@
require 'yajl/json_gem'
module Docs
class Rxjs < UrlScraper
self.name = 'RxJS'
self.type = 'rxjs'
self.release = '6.5.2'
self.base_url = 'https://rxjs.dev/'
self.root_path = 'guide/overview'
self.links = {
home: 'https://rxjs.dev/',
code: 'https://github.com/ReactiveX/rxjs'
}
html_filters.push 'rxjs/clean_html', 'rxjs/entries'
options[:follow_links] = false
options[:only_patterns] = [/guide\//, /api\//]
options[:skip_patterns] = [/api\/([^\/]+)\.json/]
options[:fix_urls_before_parse] = ->(url) do
url.sub! %r{\A(\.\/)?guide/}, '/guide/'
url.sub! %r{\Aapi/}, '/api/'
url.sub! %r{\Agenerated/}, '/generated/'
url
end
options[:max_image_size] = 256_000
options[:attribution] = <<-HTML
&copy; 2015&ndash;2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors.<br>
Code licensed under an Apache-2.0 License. Documentation licensed under CC BY 4.0.
HTML
def get_latest_version(opts)
json = fetch_json('https://rxjs.dev/generated/navigation.json', opts)
json['__versionInfo']['raw']
end
private
def initial_urls
initial_urls = []
Request.run "#{self.class.base_url}generated/navigation.json" do |response|
data = JSON.parse(response.body)
dig = ->(entry) do
initial_urls << url_for("generated/docs/#{entry['url']}.json") if entry['url'] && entry['url'] != 'api'
entry['children'].each(&dig) if entry['children']
end
data['SideNav'].each(&dig)
end
Request.run "#{self.class.base_url}generated/docs/api/api-list.json" do |response|
data = JSON.parse(response.body)
dig = ->(entry) do
initial_urls << url_for("generated/docs/#{entry['path']}.json") if entry['path']
initial_urls << url_for("generated/docs/api/#{entry['name']}.json") if entry['name'] && !entry['path']
entry['items'].each(&dig) if entry['items']
end
data.each(&dig)
end
initial_urls.select do |url|
options[:only_patterns].any? { |pattern| url =~ pattern } &&
options[:skip_patterns].none? { |pattern| url =~ pattern }
end
end
def handle_response(response)
if response.mime_type.include?('json')
begin
response.options[:response_body] = JSON.parse(response.body)['contents']
rescue JSON::ParserError
response.options[:response_body] = ''
end
response.headers['Content-Type'] = 'text/html'
response.url.path = response.url.path.sub('/generated/docs/', '/').remove('.json')
response.effective_url.path = response.effective_url.path.sub('/generated/docs/', '/').remove('.json')
end
super
end
def parse(response)
response.body.gsub! '<code-example', '<pre'
response.body.gsub! '</code-example', '</pre'
response.body.gsub! '<code-pane', '<pre'
response.body.gsub! '</code-pane', '</pre'
response.body.gsub! '<live-example></live-example>', 'live example'
response.body.gsub! '<live-example', '<span'
response.body.gsub! '</live-example', '</span'
super
end
end
end

@ -0,0 +1,31 @@
module Docs
class Trio < UrlScraper
self.type = 'simple'
self.release = '0.12.1'
self.base_url = 'https://trio.readthedocs.io/en/v0.12.1/'
self.root_path = 'index.html'
self.links = {
home: 'https://trio.readthedocs.io/',
code: 'https://github.com/python-trio/trio'
}
html_filters.push 'trio/entries', 'trio/clean_html'
options[:only_patterns] = [
/reference-core/,
/reference-io/,
/reference-testing/,
/reference-hazmat/,
]
options[:attribution] = <<-HTML
&copy; 2017 Nathaniel J. Smith<br>
Licensed under the MIT License.
HTML
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]
end
end
end

@ -15,12 +15,12 @@ module Docs
options[:replace_paths] = { 'guide/' => 'guide/index.html' }
options[:attribution] = <<-HTML
&copy; 2013&ndash;2018 Evan You, Vue.js contributors<br>
&copy; 2013&ndash;present Yuxi Evan You<br>
Licensed under the MIT License.
HTML
version '2' do
self.release = '2.5.16'
self.release = '2.6.10'
self.base_url = 'https://vuejs.org/v2/'
self.root_path = 'guide/index.html'
self.initial_paths = %w(api/)

@ -0,0 +1,27 @@
module Docs
class Vuex < UrlScraper
self.type = 'simple'
self.release = '3.1.1'
self.base_url = 'https://vuex.vuejs.org/'
self.links = {
home: 'https://vuex.vuejs.org',
code: 'https://github.com/vuejs/vuex'
}
html_filters.push 'vuex/entries', 'vuex/clean_html'
options[:skip_patterns] = [
# Other languages
/^(zh|ja|ru|kr|fr|ptbr)\//,
]
options[:attribution] = <<-HTML
&copy; 2015&ndash;present Evan You<br>
Licensed under the MIT License.
HTML
def get_latest_version(opts)
get_npm_version('vuex', opts)
end
end
end

@ -1,7 +1,7 @@
module Docs
class Yarn < UrlScraper
self.type = 'simple'
self.release = '1.12.1'
self.release = '1.17.3'
self.base_url = 'https://yarnpkg.com/en/docs/'
self.links = {
home: 'https://yarnpkg.com/',

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

@ -0,0 +1 @@
https://github.com/encode/django-rest-framework/blob/master/docs_theme/img/favicon.ico

Binary file not shown.

Before

Width:  |  Height:  |  Size: 751 B

After

Width:  |  Height:  |  Size: 642 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

@ -0,0 +1 @@
https://www.gnu.org/software/octave/img/octave-logo.svg

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

@ -0,0 +1 @@
https://raw.githubusercontent.com/ponylang/ponylang-website/master/static/images/logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

@ -0,0 +1 @@
https://github.com/ReactiveX/reactivex.github.io/blob/develop/favicon.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 794 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -0,0 +1 @@
https://github.com/python-trio/trio/blob/37de153f858e29df3a19db9fffcd0fb3f2308951/logo/logo-transparent-no-text.svg

Binary file not shown.

After

Width:  |  Height:  |  Size: 534 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

@ -0,0 +1 @@
https://github.com/vuejs/vuejs.org/blob/master/assets/logo.ai

@ -37,20 +37,17 @@ self.addEventListener('fetch', event => {
try {
const response = await fetch(event.request);
if (!response.ok) {
throw new Error(`The HTTP request failed with status code ${response.status}`);
}
return response;
} catch (err) {
const url = new URL(event.request.url);
<%# Attempt to return the index page from the cache if the user is visiting a url like devdocs.io/offline or devdocs.io/javascript/global_objects/array/find %>
<%# The index page will make sure the correct documentation or a proper offline page is shown %>
const pathname = url.pathname;
const filename = pathname.substr(1 + pathname.lastIndexOf('/')).split(/\#|\?/g)[0];
if (url.origin === location.origin && !filename.includes('.')) {
const extensions = ['.html', '.css', '.js', '.json', '.png', '.ico', '.svg', '.xml'];
<%# Attempt to return the index page from the cache if the user is visiting a url like devdocs.io/offline or devdocs.io/javascript/global_objects/array/find %>
<%# The index page will make sure the correct documentation or a proper offline page is shown %>
if (url.origin === location.origin && !extensions.some(ext => filename.endsWith(ext))) {
const cachedIndex = await caches.match('/');
if (cachedIndex) return cachedIndex;
}

Loading…
Cancel
Save