diff --git a/media/css/readthedocs-doc-embed.css b/media/css/readthedocs-doc-embed.css
deleted file mode 100644
index 6a2ccd64a1d..00000000000
--- a/media/css/readthedocs-doc-embed.css
+++ /dev/null
@@ -1,301 +0,0 @@
-/* Left for CSS overrides we need to make in the future */
-
-/* Fix badge on RTD Theme */
-
-/* Please keep RTD badge displayed on your site */
-.rst-versions.rst-badge {
- display: block;
-
- bottom: 50px;
-
- /* Workaround for mkdocs which set a specific height for this element */
- height: auto;
-}
-
-.rst-other-versions {
- text-align: left;
-}
-
-.rst-other-versions a {
- border: 0;
-}
-
-.rst-other-versions dl {
- margin: 0;
-}
-
-.rtd-current-item {
- font-weight: bold;
-}
-
-
-/* Fix RTD theme bottom margin */
-.rst-content .line-block {
- margin-bottom: 24px
-}
-
-/* Fix for nav bottom padding with flyout */
-nav.wy-nav-side {
- padding-bottom: 3em;
-}
-
-/* bookmark icon */
-.bookmark-added-msg {display: none;}
-.bookmark-active {display: none;}
-.bookmark-inactive {display: none;}
-
-
-/* Read the Docs promotional block, only applicable to RTD.org
-
-To support sphinx_rtd_theme, a `wy-menu` element is added. Other themes are
-targeted using the theme identifier and use custom elements instead of a CSS
-framework html structure.
-
-*/
-
-div.ethical-sidebar,
-div.ethical-footer {
- display: block !important;
-}
-.ethical-sidebar,
-.ethical-footer {
- padding: 0.5em;
- margin: 1em 0;
-}
-.ethical-sidebar img,
-.ethical-footer img {
- width: 120px;
- height: 90px;
- display: inline-block;
-}
-.ethical-sidebar .ethical-callout,
-.ethical-footer .ethical-callout {
- padding-top: 1em;
- clear: both;
-}
-.ethical-sidebar .ethical-pixel,
-.ethical-footer .ethical-pixel,
-.ethical-fixedfooter .ethical-pixel {
- display: none !important;
-}
-.ethical-sidebar .ethical-text,
-.ethical-footer .ethical-text {
- margin-top: 1em;
-}
-.ethical-sidebar .ethical-image-link,
-.ethical-footer .ethical-image-link {
- border: 0;
-}
-
-.ethical-sidebar,
-.ethical-footer {
- background-color: #eee;
- border: 1px solid #ccc;
- border-radius: 5px;
- color: #0a0a0a;
- font-size: 14px;
- line-height: 20px;
-}
-
-/* Techstack badging */
-.ethical-sidebar ul {
- margin: 0 !important;
- padding-left: 0;
- list-style: none;
-}
-.ethical-sidebar ul li {
- display: inline-block;
- background-color: lightskyblue;
- color: black;
- padding: 0.25em 0.4em;
- font-size: 75%;
- font-weight: 700;
- margin: 0.25em;
- border-radius: 0.25rem;
- text-align: center;
- vertical-align: baseline;
- white-space: nowrap;
- line-height: 1.41;
-}
-.ethical-sidebar ul li:not(:last-child) {
- margin-right: .25rem;
-}
-
-.ethical-sidebar a,
-.ethical-sidebar a:visited,
-.ethical-sidebar a:hover,
-.ethical-sidebar a:active,
-.ethical-footer a,
-.ethical-footer a:visited,
-.ethical-footer a:hover,
-.ethical-footer a:active {
- color: #0a0a0a;
- text-decoration: none !important;
- border-bottom: 0 !important;
-}
-
-.ethical-callout a {
- color: #707070 !important;
- text-decoration: none !important;
-}
-
-/* Sidebar promotions */
-.ethical-sidebar {
- text-align: center;
- max-width: 300px;
- margin-left: auto;
- margin-right: auto;
-}
-
-/* Footer promotions */
-.ethical-footer {
- text-align: left;
-
- font-size: 14px;
- line-height: 20px;
-}
-.ethical-footer img {
- float: right;
- margin-left: 25px;
-}
-.ethical-footer .ethical-callout {
- text-align: center;
-}
-.ethical-footer small {
- font-size: 10px;
-}
-
-/* Fixed footer promotions */
-.ethical-fixedfooter {
- box-sizing: border-box;
- position: fixed;
- bottom: 0;
- left: 0;
- z-index: 100;
- background-color: #eee;
- border-top: 1px solid #bfbfbf;
- font-size: 12px;
- line-height: 1.5;
- padding: 0.5em 1.5em;
- text-align: center;
- color: #404040;
- width: 100%; /* Fallback for Opera Mini */
- width: 100vw;
-}
-@media (min-width: 769px) {
- /* Improve viewing on non-mobile */
- .ethical-fixedfooter {
- font-size: 13px;
- padding: 1em 1.5em;
- }
-}
-.ethical-fixedfooter .ethical-text:before {
- margin-right: 4px;
- padding: 2px 6px;
- border-radius: 3px;
- background-color: #4caf50;
- color: #fff;
- content: "Sponsored";
-}
-.ethical-fixedfooter .ethical-callout {
- color: #999;
- padding-left: 6px;
- white-space: nowrap;
-}
-.ethical-fixedfooter a,
-.ethical-fixedfooter a:hover,
-.ethical-fixedfooter a:active,
-.ethical-fixedfooter a:visited {
- color: #404040;
- text-decoration: none;
-}
-.ethical-fixedfooter .ethical-close {
- position: absolute;
- top: 0;
- right: 5px;
- font-size: 20px;
- line-height: 20px;
-}
-
-/* RTD Theme specific customizations */
-.wy-nav-side .ethical-rtd {
- /* RTD theme doesn't correctly set the sidebar width */
- max-width: 300px;
- padding: 0 1em;
-}
-.ethical-rtd .ethical-sidebar {
- /* RTD theme doesn't set sidebar text color */
- color: #b3b3b3;
-
- font-size: 14px;
- line-height: 20px;
-}
-
-@media (min-width: 769px) {
- /* Make sure the fixed footer ad is under the RTD theme version selector */
- .wy-body-for-nav .ethical-fixedfooter {
- padding-left: 300px;
- }
-}
-
-/* Alabaster specific customizations */
-.ethical-alabaster a.ethical-image-link {
- /* Alabaster adds a border even to image links on hover */
- border: 0 !important;
-}
-.ethical-alabaster hr {
- /* Alabaster needs some extra spacing before the footer ad */
- margin-top: 2em;
-}
-.ethical-alabaster::before {
- /* Alabaster's search box above the ad is floating */
- clear: both;
- content: '';
- display: table;
- margin-top: 3em;
-}
-
-/* Dark theme */
-.ethical-dark-theme .ethical-sidebar {
- background-color: #4e4b4b;
- border: 1px solid #a0a0a0;
- color: #c2c2c2 !important;
-}
-.ethical-dark-theme a,
-.ethical-dark-theme a:visited {
- color: #e6e6e6 !important;
- border-bottom: 0 !important;
-}
-.ethical-dark-theme .ethical-callout a {
- color: #b3b3b3 !important;
-}
-
-
-/* Ad block nag */
-.keep-us-sustainable {
- padding: .5em;
- margin: 1em auto;
- text-align: center;
- border: 1px dotted #8ECC4C;
- max-width: 300px;
-}
-.keep-us-sustainable a,
-.keep-us-sustainable a:hover,
-.keep-us-sustainable a:visited {
- text-decoration: none;
-}
-/* Read the Docs theme specific fixes */
-.wy-nav-side .keep-us-sustainable {
- margin: 1em 2em 1em 1em;
- color: #b3b3b3;
-}
-.wy-nav-side .keep-us-sustainable a {
- color: #efefef;
- font-size: 14px;
- line-height: 20px;
-}
-
-/* Margin between the search results */
-.rtd_search_hits_spacing {
- margin: 10px 0;
-}
diff --git a/readthedocs/api/v2/permissions.py b/readthedocs/api/v2/permissions.py
index 8bc30ecd4e2..03a486116f2 100644
--- a/readthedocs/api/v2/permissions.py
+++ b/readthedocs/api/v2/permissions.py
@@ -29,7 +29,7 @@ class IsAuthorizedToViewVersion(permissions.BasePermission):
"""
Checks if the user from the request has permissions to see the version.
- This permission class used in the FooterHTML and PageSearchAPIView views.
+ This permission class used in PageSearchAPIView views.
.. note::
diff --git a/readthedocs/api/v2/proxied_urls.py b/readthedocs/api/v2/proxied_urls.py
index 031f44af303..e527e37dfb1 100644
--- a/readthedocs/api/v2/proxied_urls.py
+++ b/readthedocs/api/v2/proxied_urls.py
@@ -8,14 +8,13 @@
from django.urls import path
from readthedocs.analytics.proxied_api import AnalyticsView
-from readthedocs.api.v2.views.proxied import ProxiedEmbedAPI, ProxiedFooterHTML
+from readthedocs.api.v2.views.proxied import ProxiedEmbedAPI
from readthedocs.search.api.v2.views import ProxiedPageSearchAPIView
-api_footer_urls = [
- path("footer_html/", ProxiedFooterHTML.as_view(), name="footer_html"),
+api_proxied_urls = [
path("search/", ProxiedPageSearchAPIView.as_view(), name="search_api"),
path("embed/", ProxiedEmbedAPI.as_view(), name="embed_api"),
path("analytics/", AnalyticsView.as_view(), name="analytics_api"),
]
-urlpatterns = api_footer_urls
+urlpatterns = api_proxied_urls
diff --git a/readthedocs/api/v2/templates/restapi/footer.html b/readthedocs/api/v2/templates/restapi/footer.html
deleted file mode 100644
index ef6b23aba0d..00000000000
--- a/readthedocs/api/v2/templates/restapi/footer.html
+++ /dev/null
@@ -1,145 +0,0 @@
-
-{% load i18n %}
-
-
- {% if not new_theme %}
-
-
-
- v: {{ current_version.explicit_name }}
-
-
-
- {% endif %}
-
- {% block versions %}
- {% if translations %}
-
- - {% trans "Languages" %}
-
- {# Output the main project language since it isn't included in translations list #}
-
- -
- {{ main_project.language }}
-
-
- {# regroup to make language_list unique per language #}
- {% regroup translations by language as language_list %}
- {% for group in language_list %}
- {% for translation in group.list %}
- {% if translation.language != main_project.language %}
- -
- {{ translation.language }}
-
- {% endif %}
- {% endfor %}
- {% endfor %}
-
-
- {% endif %}
- {% if project.supports_multiple_versions and versions|length >= 1 %}
-
- - {% trans "Versions" %}
- {% for version in versions %}
- -
- {{ version.verbose_name }}
-
- {% endfor %}
-
- {% endif %}
- {% endblock %}
-
- {% block downloads %}
- {% if downloads %}
-
- - {% trans "Downloads" %}
- {% for name, url in downloads.items %}
- - {{ name }}
- {% endfor %}
-
- {% endif %}
- {% endblock %}
-
- {% block readthedocs %}
-
- {# We hardcode the URLS because we don't have access to the URLCONF of the main app from proxito #}
-
- - {% trans "On Read the Docs" %}
- -
- {% trans "Project Home" %}
-
- -
- {% trans "Builds" %}
-
- -
- {% trans "Downloads" %}
-
-
- {% endblock %}
-
- {% block vcs %}
-
- {% if github_edit_url %}
-
- - {% trans "On GitHub" %}
- -
- {% trans "View" %}
-
- {% if version.is_editable %}
- -
- {% trans "Edit" %}
-
- {% endif %}
-
- {% elif bitbucket_url %}
-
- - {% trans "On Bitbucket" %}
- -
- {% trans "Edit" %}
-
-
- {% elif gitlab_edit_url %}
-
- - {% trans "On GitLab" %}
- -
- {% trans "View" %}
-
- {% if version.is_editable %}
- -
- {% trans "Edit" %}
-
- {% endif %}
-
- {% endif %}
- {% endblock %}
-
- {% block search %}
-
- - {% trans "Search" %}
- -
-
- {# We hardcode the URLS because we don't have access to the URLCONF of the main app from proxito #}
-
-
-
-
- {% endblock %}
-
-
-
- {% block footer %}
-
- {% trans "Hosted by" %} Read the Docs
- ·
- {% trans "Privacy Policy" %}
-
- {% endblock %}
-
- {% if not new_theme %}
-
-
- {% endif %}
-
-
diff --git a/readthedocs/api/v2/urls.py b/readthedocs/api/v2/urls.py
index 673b2b6f00f..a7359a6b049 100644
--- a/readthedocs/api/v2/urls.py
+++ b/readthedocs/api/v2/urls.py
@@ -3,7 +3,7 @@
from django.urls import include, path, re_path
from rest_framework import routers
-from readthedocs.api.v2.views import core_views, footer_views, integrations, task_views
+from readthedocs.api.v2.views import core_views, integrations, task_views
from readthedocs.constants import pattern_opts
from readthedocs.gold.views import StripeEventView
@@ -56,7 +56,6 @@
function_urls = [
path("docurl/", core_views.docurl, name="docurl"),
- path("footer_html/", footer_views.FooterHTML.as_view(), name="footer_html"),
]
task_urls = [
diff --git a/readthedocs/api/v2/views/footer_views.py b/readthedocs/api/v2/views/footer_views.py
deleted file mode 100644
index 856b6b00b01..00000000000
--- a/readthedocs/api/v2/views/footer_views.py
+++ /dev/null
@@ -1,233 +0,0 @@
-"""Endpoint to generate footer HTML."""
-
-import re
-from functools import lru_cache
-
-import structlog
-from django.conf import settings
-from django.shortcuts import get_object_or_404
-from django.template import loader as template_loader
-from rest_framework.renderers import JSONRenderer
-from rest_framework.response import Response
-from rest_framework.views import APIView
-from rest_framework_jsonp.renderers import JSONPRenderer
-
-from readthedocs.api.mixins import CDNCacheTagsMixin
-from readthedocs.api.v2.permissions import IsAuthorizedToViewVersion
-from readthedocs.builds.constants import LATEST, TAG
-from readthedocs.builds.models import Version
-from readthedocs.core.utils.extend import SettingsOverrideObject
-from readthedocs.projects.constants import MKDOCS, SPHINX_HTMLDIR
-from readthedocs.projects.models import Project
-from readthedocs.projects.version_handling import (
- highest_version,
- parse_version_failsafe,
-)
-
-log = structlog.get_logger(__name__)
-
-
-def get_version_compare_data(project, base_version=None, user=None):
- """
- Retrieve metadata about the highest version available for this project.
-
- :param base_version: We assert whether or not the base_version is also the
- highest version in the resulting "is_highest" value.
- """
- if not project.show_version_warning or (base_version and base_version.is_external):
- return {"is_highest": False}
-
- versions_qs = Version.internal.public(project=project, user=user).filter(
- built=True, active=True
- )
-
- # Take preferences over tags only if the project has at least one tag
- if versions_qs.filter(type=TAG).exists():
- versions_qs = versions_qs.filter(type=TAG)
-
- # Optimization
- versions_qs = versions_qs.select_related("project")
-
- highest_version_obj, highest_version_comparable = highest_version(
- versions_qs,
- )
- ret_val = {
- "project": str(highest_version_obj),
- "version": str(highest_version_comparable),
- "is_highest": True,
- }
- if highest_version_obj:
- # Never link to the dashboard,
- # users reading the docs may don't have access to the dashboard.
- ret_val["url"] = highest_version_obj.get_absolute_url()
- ret_val["slug"] = highest_version_obj.slug
- if base_version and base_version.slug != LATEST:
- try:
- base_version_comparable = parse_version_failsafe(
- base_version.verbose_name,
- )
- if base_version_comparable:
- # This is only place where is_highest can get set. All error
- # cases will be set to True, for non- standard versions.
- ret_val["is_highest"] = (
- base_version_comparable >= highest_version_comparable
- )
- else:
- ret_val["is_highest"] = True
- except (Version.DoesNotExist, TypeError):
- ret_val["is_highest"] = True
- return ret_val
-
-
-class BaseFooterHTML(CDNCacheTagsMixin, APIView):
-
- """
- Render and return footer markup.
-
- Query parameters:
-
- - project
- - version
- - page: Sphinx's page name (name of the source file),
- used to build the "edit on" links.
- - theme: Used to decide how to integrate the flyout menu.
- - docroot: Path where all the source documents are.
- Used to build the ``edit_on`` URL.
- - source_suffix: Suffix from the source document.
- Used to build the ``edit_on`` URL.
-
- .. note::
-
- The methods `_get_project` and `_get_version`
- are called many times, so a basic cache is implemented.
- """
-
- http_method_names = ["get"]
- permission_classes = [IsAuthorizedToViewVersion]
- renderer_classes = [JSONRenderer, JSONPRenderer]
- project_cache_tag = "rtd-footer"
-
- @lru_cache(maxsize=1)
- def _get_project(self):
- project_slug = self.request.GET.get("project", None)
- project = get_object_or_404(Project, slug=project_slug)
- return project
-
- @lru_cache(maxsize=1)
- def _get_version(self):
- version_slug = self.request.GET.get("version", None)
-
- # Hack in a fix for missing version slug deploy
- # that went out a while back
- if version_slug == "":
- version_slug = LATEST
-
- project = self._get_project()
- version = get_object_or_404(
- project.versions.all(),
- slug__iexact=version_slug,
- )
- return version
-
- def _get_active_versions_sorted(self):
- """Get all versions that the user has access, sorted."""
- project = self._get_project()
- versions = project.ordered_active_versions(
- user=self.request.user,
- include_hidden=False,
- )
- return versions
-
- def _get_context(self):
- theme = self.request.GET.get("theme", False)
- docroot = self.request.GET.get("docroot", "")
- source_suffix = self.request.GET.get("source_suffix", ".rst")
-
- new_theme = theme == "sphinx_rtd_theme"
-
- project = self._get_project()
- main_project = project.main_language_project or project
- version = self._get_version()
-
- page_slug = self.request.GET.get("page", "")
- path = ""
- if page_slug and page_slug != "index":
- if version.documentation_type in {SPHINX_HTMLDIR, MKDOCS}:
- path = re.sub("/index$", "", page_slug) + "/"
- else:
- path = page_slug + ".html"
-
- context = {
- "project": project,
- "version": version,
- "path": path,
- "downloads": version.get_downloads(pretty=True),
- "current_version": version,
- "versions": self._get_active_versions_sorted(),
- "main_project": main_project,
- "translations": main_project.translations.all(),
- "current_language": project.language,
- "new_theme": new_theme,
- "settings": settings,
- "github_edit_url": version.get_github_url(
- docroot,
- page_slug,
- source_suffix,
- "edit",
- ),
- "github_view_url": version.get_github_url(
- docroot,
- page_slug,
- source_suffix,
- "view",
- ),
- "gitlab_edit_url": version.get_gitlab_url(
- docroot,
- page_slug,
- source_suffix,
- "edit",
- ),
- "gitlab_view_url": version.get_gitlab_url(
- docroot,
- page_slug,
- source_suffix,
- "view",
- ),
- "bitbucket_url": version.get_bitbucket_url(
- docroot,
- page_slug,
- source_suffix,
- ),
- }
- return context
-
- def get(self, request, format=None):
- project = self._get_project()
- version = self._get_version()
- version_compare_data = get_version_compare_data(
- project,
- base_version=version,
- user=request.user,
- )
-
- context = self._get_context()
- html = template_loader.get_template("restapi/footer.html").render(
- context,
- request,
- )
-
- show_version_warning = project.show_version_warning and not version.is_external
-
- resp_data = {
- "html": html,
- "show_version_warning": show_version_warning,
- "version_active": version.active,
- "version_compare": version_compare_data,
- "version_supported": version.supported,
- }
-
- return Response(resp_data)
-
-
-class FooterHTML(SettingsOverrideObject):
- _default_class = BaseFooterHTML
diff --git a/readthedocs/api/v2/views/proxied.py b/readthedocs/api/v2/views/proxied.py
index 729b3370422..80a1de43f3e 100644
--- a/readthedocs/api/v2/views/proxied.py
+++ b/readthedocs/api/v2/views/proxied.py
@@ -1,17 +1,8 @@
-from readthedocs.api.v2.views.footer_views import BaseFooterHTML
from readthedocs.core.mixins import ProxiedAPIMixin
from readthedocs.core.utils.extend import SettingsOverrideObject
from readthedocs.embed.views import EmbedAPI
-class BaseProxiedFooterHTML(ProxiedAPIMixin, BaseFooterHTML):
- pass
-
-
-class ProxiedFooterHTML(SettingsOverrideObject):
- _default_class = BaseProxiedFooterHTML
-
-
class ProxiedEmbedAPIBase(ProxiedAPIMixin, EmbedAPI):
pass
diff --git a/readthedocs/core/static-src/core/js/doc-embed/footer.js b/readthedocs/core/static-src/core/js/doc-embed/footer.js
deleted file mode 100644
index 3f1beedc0a9..00000000000
--- a/readthedocs/core/static-src/core/js/doc-embed/footer.js
+++ /dev/null
@@ -1,103 +0,0 @@
-var rtddata = require('./rtd-data');
-var versionCompare = require('./version-compare');
-
-var EXPLICIT_FLYOUT_PLACEMENT_SELECTOR = '#readthedocs-embed-flyout';
-
-
-function injectFooter(data) {
- // Injects the footer into the page
- // There are 3 main cases:
- // * EXPLICIT_FLYOUT_PLACEMENT_SELECTOR is defined, inject it there
- // * The page looks like our Sphinx theme, updated the existing div
- // * All other pages just get it appended to the
-
- var config = rtddata.get();
- let placement = document.querySelector(EXPLICIT_FLYOUT_PLACEMENT_SELECTOR);
- if (placement !== null) {
- placement.innerHTML = data['html'];
- }
- else if (config.is_sphinx_builder() && config.is_rtd_like_theme()) {
- let placement = document.querySelector('div.rst-other-versions');
- if (placement !== null) {
- placement.innerHTML = data['html'];
- }
- } else {
- document.body.insertAdjacentHTML('beforeend', data['html']);
- }
-
- if (!data['version_active']) {
- for (let element of document.getElementsByClassName('rst-current-version')) {
- element.classList.add('rst-out-of-date');
- }
- } else if (!data['version_supported']) {
- //$('.rst-current-version').addClass('rst-active-old-version')
- }
-}
-
-
-function init() {
- var rtd = rtddata.get();
-
- var get_data = {
- project: rtd['project'],
- version: rtd['version'],
- // Page is a sphinx concept only,
- // avoid serializing this as a literal `null` instead of empty.
- page: rtd['page'] || "",
- theme: rtd.get_theme_name(),
- };
-
- // Crappy heuristic, but people change the theme name on us.
- // So we have to do some duck typing.
- if ("docroot" in rtd) {
- get_data['docroot'] = rtd['docroot'];
- }
-
- if ("source_suffix" in rtd) {
- get_data['source_suffix'] = rtd['source_suffix'];
- }
-
- if (window.location.pathname.indexOf('/projects/') === 0) {
- get_data['subproject'] = true;
- }
-
- // Get footer HTML from API and inject it into the page.
- let footer_api_url = rtd.proxied_api_host + "/api/v2/footer_html/?" + new URLSearchParams(get_data).toString();
- fetch(footer_api_url, {method: 'GET'})
- .then(response => {
- if (!response.ok) {
- throw new Error();
- }
- return response.json();
- })
- .then(data => {
- if (data.show_version_warning) {
- versionCompare.init(data.version_compare);
- }
- injectFooter(data);
- })
- .catch(error => {
- console.error('Error loading Read the Docs footer');
- });
-
- // Register page view.
- let data = {
- project: rtd['project'],
- version: rtd['version'],
- absolute_uri: window.location.href,
- };
- let url = rtd.proxied_api_host + '/api/v2/analytics/?' + new URLSearchParams(data).toString();
- fetch(url, {method: 'GET', cache: 'no-store'})
- .then(response => {
- if (!response.ok) {
- throw new Error();
- }
- })
- .catch(error => {
- console.error('Error registering page view');
- });
-}
-
-module.exports = {
- init: init
-};
diff --git a/readthedocs/core/static-src/core/js/doc-embed/sponsorship.js b/readthedocs/core/static-src/core/js/doc-embed/sponsorship.js
deleted file mode 100644
index 186a9b33b4c..00000000000
--- a/readthedocs/core/static-src/core/js/doc-embed/sponsorship.js
+++ /dev/null
@@ -1,221 +0,0 @@
-/* Read the Docs - Documentation promotions */
-
-var constants = require('./constants');
-var rtddata = require('./rtd-data');
-
-var rtd;
-
-var EXPLICIT_PLACEMENT_SELECTOR = "[data-ea-publisher]";
-
-// Old way to control the exact placement of an ad
-var OLD_EXPLICIT_PLACEMENT_SELECTOR = '#ethical-ad-placement';
-
-
-/*
- * Inject the EthicalAds ad client
- */
-function inject_ads_client() {
- var script = document.createElement("script");
- script.src = "https://media.ethicalads.io/media/client/beta/ethicalads.min.js";
- script.type = "text/javascript";
- script.async = true;
- script.id = "ethicaladsjs";
- document.getElementsByTagName("head")[0].appendChild(script);
-}
-
-/*
- * Creates a div where the ad could go
- */
-function create_ad_placement() {
- var selector = null;
- var class_name; // Used for theme specific CSS customizations
- var style_name;
- var ad_type = "readthedocs-sidebar";
- var element;
- var offset;
-
- if ($(EXPLICIT_PLACEMENT_SELECTOR).length > 0) {
- $(EXPLICIT_PLACEMENT_SELECTOR).attr("data-ea-publisher", "readthedocs");
- $(EXPLICIT_PLACEMENT_SELECTOR).attr("data-ea-manual", "true");
- if ($(EXPLICIT_PLACEMENT_SELECTOR).attr("data-ea-type") !== "image" && $(EXPLICIT_PLACEMENT_SELECTOR).attr("data-ea-type") !== "text") {
- $(EXPLICIT_PLACEMENT_SELECTOR).attr("data-ea-type", "readthedocs-sidebar");
- }
- return $(EXPLICIT_PLACEMENT_SELECTOR);
- } else if ($(OLD_EXPLICIT_PLACEMENT_SELECTOR).length > 0) {
- selector = OLD_EXPLICIT_PLACEMENT_SELECTOR;
- if (rtd.is_rtd_like_theme()) {
- class_name = 'ethical-rtd ethical-dark-theme';
- } else {
- class_name = 'ethical-alabaster';
- }
- } else if (rtd.is_mkdocs_builder() && rtd.is_rtd_like_theme()) {
- selector = 'nav.wy-nav-side';
- class_name = 'ethical-rtd ethical-dark-theme';
- } else if (rtd.is_rtd_like_theme()) {
- selector = 'nav.wy-nav-side > div.wy-side-scroll';
- class_name = 'ethical-rtd ethical-dark-theme';
- } else if (rtd.is_alabaster_like_theme()) {
- selector = 'div.sphinxsidebar > div.sphinxsidebarwrapper';
- class_name = 'ethical-alabaster';
- }
-
- if (selector) {
- // Determine if this element would be above the fold
- // If this is off screen, instead create an ad in the footer
- // Assumes the ad would be ~200px high
- element = $("").appendTo(selector);
- offset = element.offset();
- if (!offset || (offset.top - window.scrollY + 200) > window.innerHeight) {
- if (rtd.is_rtd_like_theme()) {
- selector = $('').insertAfter('footer hr');
- class_name = 'ethical-rtd';
-
- // Use the stickybox placement 100% of the time,
- // now that we're happy with its performance.
- style_name = 'stickybox';
- ad_type = 'image';
- } else if (rtd.is_alabaster_like_theme()) {
- selector = 'div.bodywrapper .body';
- class_name = 'ethical-alabaster';
- }
- }
- element.remove();
-
- // Add the element where the ad will go
- return $('')
- .attr("id", "rtd-sidebar")
- .attr("data-ea-publisher", "readthedocs")
- .attr("data-ea-type", ad_type)
- .attr("data-ea-manual", "true")
- .attr("data-ea-style", style_name)
- .addClass(class_name)
- .appendTo(selector);
- }
-
- return null;
-}
-
-function detect_adblock() {
- // Status codes are not correctly reported on JSONP requests
- // So we resort to different ways to detect adblockers
- var detected = false;
-
- // Check if our ad element is blocked
- $('')
- .attr('id', 'rtd-detection')
- .attr('class', 'ethical-rtd')
- .html(' ')
- .appendTo('body');
- if ($('#rtd-detection').height() === 0) {
- detected = true;
- }
-
- // Remove the test element regardless
- $('#rtd-detection').remove();
-
- return detected;
-}
-
-function adblock_admonition() {
- console.log('---------------------------------------------------------------------------------------');
- console.log('Read the Docs hosts documentation for tens of thousands of open source projects.');
- console.log('We fund our development (we are open source) and operations through advertising.');
-
- console.log('We promise to:');
- console.log(' - never let advertisers run 3rd party JavaScript');
- console.log(' - never sell user data to advertisers or other 3rd parties');
- console.log(' - only show advertisements of interest to developers');
- console.log('Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/advertising/ethical-advertising.html');
- console.log('%cPlease allow our Ethical Ads or go ad-free:', 'font-size: 2em');
- console.log('https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html');
- console.log('--------------------------------------------------------------------------------------');
-}
-
-function adblock_nag(placement) {
- // Place an ad block nag into the sidebar
- var unblock_url = 'https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html#allowing-ethical-ads';
- var ad_free_url = 'https://readthedocs.org/sustainability/';
- var container = null;
-
- if (placement) {
- container = placement.attr('class', 'keep-us-sustainable');
-
- $('').text('Support Read the Docs!').appendTo(container);
- $('').html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(container);
- $('').text('Thank you! \u2764\ufe0f').appendTo(container);
- }
-}
-
-function init() {
- var placement;
-
- rtd = rtddata.get();
-
- if (!rtd.show_promo()) {
- return;
- }
-
- placement = create_ad_placement();
-
- // Inject ads
- inject_ads_client();
-
- $.ajax({
- url: rtd.api_host + "/api/v2/sustainability/data/",
- crossDomain: true,
- xhrFields: {
- withCredentials: true,
- },
- dataType: "jsonp",
- data: {
- format: "jsonp",
- project: rtd.project,
- },
- success: function (data) {
- if (!placement || data.ad_free) {
- // No valid placement or project/user is ad free
- return;
- }
-
- // Set the keyword, campaign data, and publisher
- if (data.keywords) {
- placement.attr("data-ea-keywords", data.keywords.join("|"));
- }
- if (data.campaign_types) {
- placement.attr("data-ea-campaign-types", data.campaign_types.join("|"));
- }
- if (data.publisher) {
- placement.attr("data-ea-publisher", data.publisher);
- }
-
- if (typeof ethicalads !== "undefined") {
- // Trigger ad request
- ethicalads.load();
- } else if (!rtd.ad_free && detect_adblock()) {
- // Ad client prevented from loading - check ad blockers
- adblock_admonition();
- adblock_nag(placement);
- } else {
- // The ad client hasn't loaded yet which could happen due to a variety of issues
- // Add an event listener for it to load
- document.getElementById("ethicaladsjs").addEventListener("load", function () {
- if (typeof ethicalads !== "undefined") {
- ethicalads.load();
- }
- });
- }
- },
- error: function () {
- console.error('Error loading Read the Docs user and project information');
-
- if (!rtd.ad_free && detect_adblock()) {
- adblock_admonition();
- adblock_nag(placement);
- }
- },
- });
-}
-
-module.exports = {
- init: init,
-};
diff --git a/readthedocs/core/static-src/core/js/readthedocs-doc-embed.js b/readthedocs/core/static-src/core/js/readthedocs-doc-embed.js
index 81e6521b138..8aab0ac9bcb 100644
--- a/readthedocs/core/static-src/core/js/readthedocs-doc-embed.js
+++ b/readthedocs/core/static-src/core/js/readthedocs-doc-embed.js
@@ -1,5 +1,3 @@
-const sponsorship = require('./doc-embed/sponsorship');
-const footer = require('./doc-embed/footer.js');
// grokthedocs = require('./doc-embed/grokthedocs-client'),
// mkdocs = require('./doc-embed/mkdocs'),
const sphinx = require('./doc-embed/sphinx');
@@ -39,10 +37,8 @@ function injectJQuery(init) {
domReady(function () {
// Block on jQuery loading before we run any of our code.
injectJQuery(function () {
- footer.init();
sphinx.init();
search.init();
- sponsorship.init();
});
});
}());
diff --git a/readthedocs/core/static/core/js/readthedocs-doc-embed.js b/readthedocs/core/static/core/js/readthedocs-doc-embed.js
index 5792ef07f0a..02aa05f357f 100644
--- a/readthedocs/core/static/core/js/readthedocs-doc-embed.js
+++ b/readthedocs/core/static/core/js/readthedocs-doc-embed.js
@@ -1 +1 @@
-!function i(o,a,r){function s(t,e){if(!a[t]){if(!o[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(d)return d(t,!0);throw(e=new Error("Cannot find module '"+t+"'")).code="MODULE_NOT_FOUND",e}n=a[t]={exports:{}},o[t][0].call(n.exports,function(e){return s(o[t][1][e]||e)},n,n.exports,i,o,a,r)}return a[t].exports}for(var d="function"==typeof require&&require,e=0;e"),n("table.docutils.footnote").wrap(""),n("table.docutils.citation").wrap(""),n(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=n(this);(expand=n('')).on("click",function(e){return i.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t,n=$(".wy-menu-vertical"),i=n.find('[href="'+e+'"]');0===i.length&&(t=$('.document [id="'+e.substring(1)+'"]').closest("div.section"),0===(i=n.find('[href="#'+t.attr("id")+'"]')).length&&(i=n.find('[href="#"]'))),0this.docHeight||(this.navBar.scrollTop(n),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){e=e.closest("li");e.siblings("li.current").removeClass("current"),e.siblings().find("li.current").removeClass("current"),e.find("> ul li.current").removeClass("current"),e.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav});for(var a=0,o=["ms","moz","webkit","o"],r=0;r{if(e.ok)return e.json();throw new Error}).then(t=>{t.show_version_warning&&a.init(t.version_compare);{var n=o.get();let e=document.querySelector(r);if(null!==e)e.innerHTML=t.html;else if(n.is_sphinx_builder()&&n.is_rtd_like_theme()){let e=document.querySelector("div.rst-other-versions");null!==e&&(e.innerHTML=t.html)}else document.body.insertAdjacentHTML("beforeend",t.html);if(t.version_active)t.version_supported;else for(var i of document.getElementsByClassName("rst-current-version"))i.classList.add("rst-out-of-date");return}}).catch(e=>{console.error("Error loading Read the Docs footer")}),{project:t.project,version:t.version,absolute_uri:window.location.href}),t=t.proxied_api_host+"/api/v2/analytics/?"+new URLSearchParams(e).toString();fetch(t,{method:"GET",cache:"no-store"}).then(e=>{if(!e.ok)throw new Error}).catch(e=>{console.error("Error registering page view")})}}},{"./rtd-data":4,"./version-compare":9}],4:[function(e,t,n){var i=e("./constants"),o={is_rtd_like_theme:function(){return 1===document.querySelectorAll("div.rst-other-versions").length||(this.theme===i.THEME_RTD||this.theme===i.THEME_MKDOCS_RTD)},is_alabaster_like_theme:function(){return-1{t.appendChild(e)})}for(c of t.getElementsByTagName("span"))c.className="highlighted";n.appendChild(t),l{if(e.ok)return e.json();throw new Error}).then(e=>{0{i()})}var t,E=o.project,a=o.version,r=o.language||"en";"undefined"!=typeof Search&&E&&a&&(o.features&&o.features.docsearch_disabled?console.log("Server side search is disabled."):(t=Search.query,Search.query_fallback=t,Search.query=e)),s(function(){"undefined"!=typeof Search&&Search.init()})}t.exports={init:function(){var e=i.get();e.is_sphinx_builder()?a(e):console.log("Server side search is disabled.")}}},{"./rtd-data":4,"./utils":8}],6:[function(i,e,t){const o=i("./rtd-data"),a=i("./utils")["domReady"];e.exports={init:function(){var e,t=o.get(),n=document.querySelector("[data-toggle='rst-current-version']");null!=n&&n.addEventListener("click",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof READTHEDOCS_DATA&&READTHEDOCS_DATA.global_analytics_code&&("undefined"!=typeof gtag?gtag("event","Click",{event_category:"Flyout",event_label:e,send_to:"rtfd"}):"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e]))}),void 0===window.SphinxRtdTheme&&(e=i("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav,a(function(){setTimeout(function(){e.navBar||e.enable()},1e3)}),t.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length&&(console.log("Applying theme sidebar fix..."),n=$("nav.wy-nav-side:first"),t=$("").addClass("wy-side-scroll"),n.children().detach().appendTo(t),t.prependTo(n),e.navBar=t))}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":4,"./utils":8}],7:[function(e,t,n){e("./constants");var s,d=e("./rtd-data"),l="[data-ea-publisher]",c="#ethical-ad-placement";function h(){var e=!1;return $("").attr("id","rtd-detection").attr("class","ethical-rtd").html(" ").appendTo("body"),0===$("#rtd-detection").height()&&(e=!0),$("#rtd-detection").remove(),e}function u(){console.log("---------------------------------------------------------------------------------------"),console.log("Read the Docs hosts documentation for tens of thousands of open source projects."),console.log("We fund our development (we are open source) and operations through advertising."),console.log("We promise to:"),console.log(" - never let advertisers run 3rd party JavaScript"),console.log(" - never sell user data to advertisers or other 3rd parties"),console.log(" - only show advertisements of interest to developers"),console.log("Read more about our approach to advertising here: https://docs.readthedocs.io/en/latest/advertising/ethical-advertising.html"),console.log("%cPlease allow our Ethical Ads or go ad-free:","font-size: 2em"),console.log("https://docs.readthedocs.io/en/latest/advertising/ad-blocking.html"),console.log("--------------------------------------------------------------------------------------")}function p(e){e&&(e=e.attr("class","keep-us-sustainable"),$("").text("Support Read the Docs!").appendTo(e),$("").html('Please help keep us sustainable by allowing our Ethical Ads in your ad blocker or go ad-free by subscribing.').appendTo(e),$("").text("Thank you! ❤️").appendTo(e))}t.exports={init:function(){var t,e,n,i,o,a,r;(s=d.get()).show_promo()&&(o=null,a="readthedocs-sidebar",t=0<$(l).length?($(l).attr("data-ea-publisher","readthedocs"),$(l).attr("data-ea-manual","true"),"image"!==$(l).attr("data-ea-type")&&"text"!==$(l).attr("data-ea-type")&&$(l).attr("data-ea-type","readthedocs-sidebar"),$(l)):(0<$(c).length?(o=c,e=s.is_rtd_like_theme()?"ethical-rtd ethical-dark-theme":"ethical-alabaster"):s.is_mkdocs_builder()&&s.is_rtd_like_theme()?(o="nav.wy-nav-side",e="ethical-rtd ethical-dark-theme"):s.is_rtd_like_theme()?(o="nav.wy-nav-side > div.wy-side-scroll",e="ethical-rtd ethical-dark-theme"):s.is_alabaster_like_theme()&&(o="div.sphinxsidebar > div.sphinxsidebarwrapper",e="ethical-alabaster"),o?((!(r=(i=$("").appendTo(o)).offset())||r.top-window.scrollY+200>window.innerHeight)&&(s.is_rtd_like_theme()?(o=$("").insertAfter("footer hr"),e="ethical-rtd",n="stickybox",a="image"):s.is_alabaster_like_theme()&&(o="div.bodywrapper .body",e="ethical-alabaster")),i.remove(),$("").attr("id","rtd-sidebar").attr("data-ea-publisher","readthedocs").attr("data-ea-type",a).attr("data-ea-manual","true").attr("data-ea-style",n).addClass(e).appendTo(o)):null),(r=document.createElement("script")).src="https://media.ethicalads.io/media/client/beta/ethicalads.min.js",r.type="text/javascript",r.async=!0,r.id="ethicaladsjs",document.getElementsByTagName("head")[0].appendChild(r),$.ajax({url:s.api_host+"/api/v2/sustainability/data/",crossDomain:!0,xhrFields:{withCredentials:!0},dataType:"jsonp",data:{format:"jsonp",project:s.project},success:function(e){t&&!e.ad_free&&(e.keywords&&t.attr("data-ea-keywords",e.keywords.join("|")),e.campaign_types&&t.attr("data-ea-campaign-types",e.campaign_types.join("|")),e.publisher&&t.attr("data-ea-publisher",e.publisher),"undefined"!=typeof ethicalads?ethicalads.load():!s.ad_free&&h()?(u(),p(t)):document.getElementById("ethicaladsjs").addEventListener("load",function(){"undefined"!=typeof ethicalads&ðicalads.load()}))},error:function(){console.error("Error loading Read the Docs user and project information"),!s.ad_free&&h()&&(u(),p(t))}}))}}},{"./constants":2,"./rtd-data":4}],8:[function(e,t,n){t.exports={createDomNode:function(e,t){let n=document.createElement(e);if(t)for(var i of Object.keys(t))n.setAttribute(i,t[i]);return n},domReady:function(e){"complete"===document.readyState||"interactive"===document.readyState?setTimeout(e,1):document.addEventListener("DOMContentLoaded",e)}}},{}],9:[function(e,t,n){const a=e("./rtd-data"),r=e("./utils")["createDomNode"];t.exports={init:function(n){var i,o=a.get();if(!n.is_highest){o=window.location.pathname.replace(o.version,n.slug);let t=r("div",{class:"admonition warning"}),e=r("a",{href:o});e.innerText=n.slug,t.innerHTML='Note
You are not reading the most recent version of this documentation. '+e.outerHTML+" is the latest version available.
";for(i of["[role=main]","main","div.body","div.document"]){let e=document.querySelector(i);if(null!==e){e.prepend(t);break}}}}}},{"./rtd-data":4,"./utils":8}],10:[function(i,e,t){const o=i("./doc-embed/sponsorship"),a=i("./doc-embed/footer.js"),r=i("./doc-embed/sphinx"),s=i("./doc-embed/search"),n=i("./doc-embed/utils")["domReady"],d=i("./doc-embed/rtd-data");n(function(){var t=function(){a.init(),r.init(),s.init(),o.init()};if(window.jQuery)t();else{console.debug("JQuery not found. Injecting.");var n=d.get();let e=document.createElement("script");e.type="text/javascript",e.src=n.proxied_static_path+"vendor/jquery.js",e.onload=function(){window.$=i("jquery"),window.jQuery=window.$,t()},document.head.appendChild(e)}})},{"./doc-embed/footer.js":3,"./doc-embed/rtd-data":4,"./doc-embed/search":5,"./doc-embed/sphinx":6,"./doc-embed/sponsorship":7,"./doc-embed/utils":8,jquery:"jquery"}]},{},[10]);
\ No newline at end of file
+!function i(o,r,a){function s(t,e){if(!r[t]){if(!o[t]){var n="function"==typeof require&&require;if(!e&&n)return n(t,!0);if(c)return c(t,!0);throw(e=new Error("Cannot find module '"+t+"'")).code="MODULE_NOT_FOUND",e}n=r[t]={exports:{}},o[t][0].call(n.exports,function(e){return s(o[t][1][e]||e)},n,n.exports,i,o,r,a)}return r[t].exports}for(var c="function"==typeof require&&require,e=0;e"),n("table.docutils.footnote").wrap(""),n("table.docutils.citation").wrap(""),n(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var t=n(this);(expand=n('')).on("click",function(e){return i.toggleCurrent(t),e.stopPropagation(),!1}),t.prepend(expand)})},reset:function(){var e=encodeURI(window.location.hash)||"#";try{var t,n=$(".wy-menu-vertical"),i=n.find('[href="'+e+'"]');0===i.length&&(t=$('.document [id="'+e.substring(1)+'"]').closest("div.section"),0===(i=n.find('[href="#'+t.attr("id")+'"]')).length&&(i=n.find('[href="#"]'))),0this.docHeight||(this.navBar.scrollTop(n),this.winPosition=e)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(e){e=e.closest("li");e.siblings("li.current").removeClass("current"),e.siblings().find("li.current").removeClass("current"),e.find("> ul li.current").removeClass("current"),e.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:t.exports.ThemeNav,StickyNav:t.exports.ThemeNav});for(var r=0,o=["ms","moz","webkit","o"],a=0;a{t.appendChild(e)})}for(d of t.getElementsByTagName("span"))d.className="highlighted";n.appendChild(t),l{if(e.ok)return e.json();throw new Error}).then(e=>{0{i()})}var t,w=o.project,r=o.version,a=o.language||"en";"undefined"!=typeof Search&&w&&r&&(o.features&&o.features.docsearch_disabled?console.log("Server side search is disabled."):(t=Search.query,Search.query_fallback=t,Search.query=e)),s(function(){"undefined"!=typeof Search&&Search.init()})}t.exports={init:function(){var e=i.get();e.is_sphinx_builder()?r(e):console.log("Server side search is disabled.")}}},{"./rtd-data":3,"./utils":6}],5:[function(i,e,t){const o=i("./rtd-data"),r=i("./utils")["domReady"];e.exports={init:function(){var e,t=o.get(),n=document.querySelector("[data-toggle='rst-current-version']");null!=n&&n.addEventListener("click",function(){var e=$("[data-toggle='rst-versions']").hasClass("shift-up")?"was_open":"was_closed";"undefined"!=typeof READTHEDOCS_DATA&&READTHEDOCS_DATA.global_analytics_code&&("undefined"!=typeof gtag?gtag("event","Click",{event_category:"Flyout",event_label:e,send_to:"rtfd"}):"undefined"!=typeof ga?ga("rtfd.send","event","Flyout","Click",e):"undefined"!=typeof _gaq&&_gaq.push(["rtfd._setAccount","UA-17997319-1"],["rtfd._trackEvent","Flyout","Click",e]))}),void 0===window.SphinxRtdTheme&&(e=i("./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js").ThemeNav,r(function(){setTimeout(function(){e.navBar||e.enable()},1e3)}),t.is_rtd_like_theme()&&!$("div.wy-side-scroll:first").length&&(console.log("Applying theme sidebar fix..."),n=$("nav.wy-nav-side:first"),t=$("").addClass("wy-side-scroll"),n.children().detach().appendTo(t),t.prependTo(n),e.navBar=t))}}},{"./../../../../../../bower_components/sphinx-rtd-theme/js/theme.js":1,"./rtd-data":3,"./utils":6}],6:[function(e,t,n){t.exports={createDomNode:function(e,t){let n=document.createElement(e);if(t)for(var i of Object.keys(t))n.setAttribute(i,t[i]);return n},domReady:function(e){"complete"===document.readyState||"interactive"===document.readyState?setTimeout(e,1):document.addEventListener("DOMContentLoaded",e)}}},{}],7:[function(i,e,t){const o=i("./doc-embed/sphinx"),r=i("./doc-embed/search"),n=i("./doc-embed/utils")["domReady"],a=i("./doc-embed/rtd-data");n(function(){var t=function(){o.init(),r.init()};if(window.jQuery)t();else{console.debug("JQuery not found. Injecting.");var n=a.get();let e=document.createElement("script");e.type="text/javascript",e.src=n.proxied_static_path+"vendor/jquery.js",e.onload=function(){window.$=i("jquery"),window.jQuery=window.$,t()},document.head.appendChild(e)}})},{"./doc-embed/rtd-data":3,"./doc-embed/search":4,"./doc-embed/sphinx":5,"./doc-embed/utils":6,jquery:"jquery"}]},{},[7]);
\ No newline at end of file
diff --git a/readthedocs/proxito/middleware.py b/readthedocs/proxito/middleware.py
index 772ce06a781..cd6f14c9a29 100644
--- a/readthedocs/proxito/middleware.py
+++ b/readthedocs/proxito/middleware.py
@@ -48,7 +48,6 @@ class ProxitoMiddleware(MiddlewareMixin):
# which depends on the proxito middleware.
skip_views = (
"health_check",
- "footer_html",
"search_api",
"embed_api",
)
diff --git a/readthedocs/proxito/tests/test_headers.py b/readthedocs/proxito/tests/test_headers.py
index 8a4c199721b..f8919648503 100644
--- a/readthedocs/proxito/tests/test_headers.py
+++ b/readthedocs/proxito/tests/test_headers.py
@@ -5,10 +5,9 @@
ACCESS_CONTROL_ALLOW_ORIGIN,
)
from django.test import override_settings
-from django.urls import reverse
from django_dynamic_fixture import get
-from readthedocs.builds.constants import EXTERNAL, LATEST
+from readthedocs.builds.constants import EXTERNAL
from readthedocs.builds.models import Version
from readthedocs.organizations.models import Organization
from readthedocs.projects.constants import PRIVATE, PUBLIC
@@ -153,16 +152,6 @@ def test_custom_domain_headers(self):
r["X-RTD-Path"], "/proxito/media/html/project/latest/index.html"
)
- def test_footer_headers(self):
- version = self.project.versions.get(slug=LATEST)
- url = (
- reverse("footer_html")
- + f"?project={self.project.slug}&version={version.slug}"
- )
- r = self.client.get(url, headers={"host": "project.dev.readthedocs.io"})
- self.assertEqual(r.status_code, 200)
- self.assertEqual(r["Cache-Tag"], "project,project:latest,project:rtd-footer")
-
def test_user_domain_headers(self):
hostname = "docs.domain.com"
self.domain = fixture.get(
diff --git a/readthedocs/proxito/tests/test_proxied_api.py b/readthedocs/proxito/tests/test_proxied_api.py
deleted file mode 100644
index 72eca03245d..00000000000
--- a/readthedocs/proxito/tests/test_proxied_api.py
+++ /dev/null
@@ -1,14 +0,0 @@
-from django.test import TestCase, override_settings
-
-from readthedocs.rtd_tests.tests.test_footer import BaseTestFooterHTML
-
-
-@override_settings(PUBLIC_DOMAIN="readthedocs.io")
-class TestProxiedFooterHTML(BaseTestFooterHTML, TestCase):
- def setUp(self):
- super().setUp()
- self.host = "pip.readthedocs.io"
-
- def render(self):
- r = self.client.get(self.url, headers={"host": self.host})
- return r
diff --git a/readthedocs/rtd_tests/tests/test_api_version_compare.py b/readthedocs/rtd_tests/tests/test_api_version_compare.py
deleted file mode 100644
index bec4dc5ef65..00000000000
--- a/readthedocs/rtd_tests/tests/test_api_version_compare.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from django.test import TestCase
-
-from readthedocs.api.v2.views.footer_views import get_version_compare_data
-from readthedocs.builds.constants import LATEST
-from readthedocs.projects.models import Project
-
-
-class VersionCompareTests(TestCase):
- fixtures = ["eric.json", "test_data.json"]
-
- def setUp(self):
- Project.objects.update(show_version_warning=True)
-
- def test_not_highest(self):
- project = Project.objects.get(slug="read-the-docs")
- version = project.versions.get(slug="0.2.1")
-
- data = get_version_compare_data(project, version)
- self.assertEqual(data["is_highest"], False)
-
- def test_latest_version_highest(self):
- project = Project.objects.get(slug="read-the-docs")
-
- data = get_version_compare_data(project)
- self.assertEqual(data["is_highest"], True)
-
- version = project.versions.get(slug=LATEST)
- data = get_version_compare_data(project, version)
- self.assertEqual(data["is_highest"], True)
-
- def test_real_highest(self):
- project = Project.objects.get(slug="read-the-docs")
- version = project.versions.get(slug="0.2.2")
-
- data = get_version_compare_data(project, version)
- self.assertEqual(data["is_highest"], True)
diff --git a/readthedocs/rtd_tests/tests/test_footer.py b/readthedocs/rtd_tests/tests/test_footer.py
deleted file mode 100644
index beb1f5f9bc6..00000000000
--- a/readthedocs/rtd_tests/tests/test_footer.py
+++ /dev/null
@@ -1,530 +0,0 @@
-from unittest import mock
-
-import pytest
-from django.contrib.auth.models import User
-from django.test import TestCase, override_settings
-from django.urls import reverse
-from django_dynamic_fixture import get
-from rest_framework.test import APIRequestFactory
-
-from readthedocs.api.v2.views.footer_views import get_version_compare_data
-from readthedocs.builds.constants import BRANCH, EXTERNAL, LATEST, TAG
-from readthedocs.builds.models import Version
-from readthedocs.organizations.models import Organization
-from readthedocs.projects.constants import GITHUB_BRAND, GITLAB_BRAND, PRIVATE, PUBLIC
-from readthedocs.projects.models import Project
-from readthedocs.subscriptions.constants import TYPE_CNAME
-from readthedocs.subscriptions.products import RTDProductFeature
-
-
-class BaseTestFooterHTML:
- def setUp(self):
- self.pip = get(
- Project,
- slug="pip",
- repo="https://github.com/rtfd/readthedocs.org",
- privacy_level=PUBLIC,
- external_builds_privacy_level=PUBLIC,
- main_language_project=None,
- )
- self.pip.versions.update(privacy_level=PUBLIC, built=True)
-
- self.latest = self.pip.versions.get(slug=LATEST)
- self.url = (
- reverse("footer_html")
- + f"?project={self.pip.slug}&version={self.latest.slug}&page=index&docroot=/"
- )
-
- self.factory = APIRequestFactory()
-
- def render(self):
- r = self.client.get(self.url)
- return r
-
- def test_footer(self):
- pip = Project.objects.get(slug="pip")
- pip.show_version_warning = True
- pip.save()
-
- r = self.render()
- self.assertTrue(r.data["version_active"])
- self.assertTrue(r.data["version_compare"]["is_highest"])
- self.assertTrue(r.data["version_supported"])
- self.assertTrue(r.data["show_version_warning"])
- self.assertEqual(r.context["main_project"], self.pip)
- self.assertEqual(r.status_code, 200)
-
- self.latest.active = False
- self.latest.save()
- r = self.render()
- self.assertFalse(r.data["version_active"])
- self.assertEqual(r.status_code, 200)
-
- def test_footer_dont_show_version_warning(self):
- pip = Project.objects.get(slug="pip")
- pip.show_version_warning = False
- pip.save()
-
- r = self.render()
- self.assertEqual(r.status_code, 200)
- self.assertTrue(r.data["version_active"])
- self.assertFalse(r.data["version_compare"]["is_highest"])
- self.assertTrue(r.data["version_supported"])
- self.assertFalse(r.data["show_version_warning"])
- self.assertEqual(r.context["main_project"], self.pip)
-
- def test_footer_show_explicit_name_for_external_version(self):
- project = Project.objects.get(slug="pip")
- version = project.versions.get(slug=LATEST)
- version.type = EXTERNAL
- version.verbose_name = "4"
- version.save()
- self.url = (
- reverse("footer_html")
- + f"?project={project.slug}&version={version.slug}&page=index&docroot=/"
- )
-
- git_provider_name = "readthedocs.projects.models.Project.git_provider_name"
- with mock.patch(git_provider_name, GITHUB_BRAND):
- r = self.render()
- self.assertIn("#4 (PR)", r.data["html"])
- self.assertNotIn("#4 (MR)", r.data["html"])
- self.assertNotIn("#4 (EV)", r.data["html"])
- with mock.patch(git_provider_name, GITLAB_BRAND):
- r = self.render()
- self.assertIn("#4 (MR)", r.data["html"])
- self.assertNotIn("#4 (PR)", r.data["html"])
- self.assertNotIn("#4 (EV)", r.data["html"])
-
- def test_footer_dont_show_version_warning_for_external_versions(self):
- self.latest.type = EXTERNAL
- self.latest.save()
-
- r = self.render()
- self.assertEqual(r.status_code, 200)
- self.assertFalse(r.data["version_compare"]["is_highest"])
- self.assertFalse(r.data["show_version_warning"])
- self.assertEqual(r.context["main_project"], self.pip)
-
- def test_footer_uses_version_compare(self):
- version_compare = (
- "readthedocs.api.v2.views.footer_views.get_version_compare_data" # noqa
- )
- with mock.patch(version_compare) as get_version_compare_data:
- get_version_compare_data.return_value = {
- "MOCKED": True,
- }
- r = self.render()
- self.assertEqual(r.status_code, 200)
- self.assertEqual(r.data["version_compare"], {"MOCKED": True})
-
- def test_pdf_build_mentioned_in_footer(self):
- self.latest.has_pdf = True
- self.latest.save()
-
- response = self.render()
- self.assertIn("pdf", response.data["html"])
-
- def test_pdf_not_mentioned_in_footer_when_doesnt_exists(self):
- response = self.render()
- self.assertNotIn("pdf", response.data["html"])
-
- def test_epub_build_mentioned_in_footer(self):
- self.latest.has_epub = True
- self.latest.save()
-
- response = self.render()
- self.assertIn("epub", response.data["html"])
-
- def test_epub_not_mentioned_in_footer_when_doesnt_exists(self):
- response = self.render()
- self.assertNotIn("epub", response.data["html"])
-
- def test_show_version_warning(self):
- self.pip.show_version_warning = True
- self.pip.save()
- response = self.render()
- self.assertTrue(response.data["show_version_warning"])
-
- def test_show_edit_on_github(self):
- version = self.pip.versions.get(slug=LATEST)
- version.type = BRANCH
- version.save()
- response = self.render()
- self.assertIn("On GitHub", response.data["html"])
- self.assertIn("View", response.data["html"])
- self.assertIn("Edit", response.data["html"])
-
- def test_not_show_edit_on_github(self):
- version = self.pip.versions.get(slug=LATEST)
- version.type = TAG
- version.save()
- response = self.render()
- self.assertIn("On GitHub", response.data["html"])
- self.assertIn("View", response.data["html"])
- self.assertNotIn("Edit", response.data["html"])
-
- def test_index_pages_sphinx_htmldir(self):
- version = self.pip.versions.get(slug=LATEST)
- version.documentation_type = "sphinx_htmldir"
- version.save()
-
- # A page with slug 'index' should render like /en/latest/
- self.url = (
- reverse("footer_html")
- + f"?project={self.pip.slug}&version={self.latest.slug}&page=index&docroot=/"
- )
- response = self.render()
- self.assertIn("/en/latest/", response.data["html"])
- self.assertNotIn("/en/latest/index.html", response.data["html"])
-
- # A page with slug 'foo/index' should render like /en/latest/foo/
- self.url = (
- reverse("footer_html")
- + f"?project={self.pip.slug}&version={self.latest.slug}&page=foo/index&docroot=/"
- )
- response = self.render()
- self.assertIn("/en/latest/foo/", response.data["html"])
- self.assertNotIn("/en/latest/foo.html", response.data["html"])
- self.assertNotIn("/en/latest/foo/index.html", response.data["html"])
-
- # A page with slug 'foo/bar' should render like /en/latest/foo/bar/
- self.url = (
- reverse("footer_html")
- + f"?project={self.pip.slug}&version={self.latest.slug}&page=foo/bar&docroot=/"
- )
- response = self.render()
- self.assertIn("/en/latest/foo/bar/", response.data["html"])
- self.assertNotIn("/en/latest/foo/bar.html", response.data["html"])
- self.assertNotIn("/en/latest/foo/bar/index.html", response.data["html"])
-
- # A page with slug 'foo/bar/index' should render like /en/latest/foo/bar/
- self.url = (
- reverse("footer_html")
- + f"?project={self.pip.slug}&version={self.latest.slug}&page=foo/bar/index&docroot=/"
- )
- response = self.render()
- self.assertIn("/en/latest/foo/bar/", response.data["html"])
- self.assertNotIn("/en/latest/foo/bar.html", response.data["html"])
- self.assertNotIn("/en/latest/foo/bar/index.html", response.data["html"])
-
- # A page with slug 'foo/index/bar' should render like /en/latest/foo/index/bar/
- self.url = (
- reverse("footer_html")
- + f"?project={self.pip.slug}&version={self.latest.slug}&page=foo/index/bar&docroot=/"
- )
- response = self.render()
- self.assertIn("/en/latest/foo/index/bar/", response.data["html"])
- self.assertNotIn("/en/latest/foo/index/bar.html", response.data["html"])
- self.assertNotIn("/en/latest/foo/index/bar/index.html", response.data["html"])
-
- def test_hidden_versions(self):
- hidden_version = get(
- Version,
- slug="2.0",
- hidden=True,
- privacy_level=PUBLIC,
- project=self.pip,
- )
-
- # The hidden version doesn't appear on the footer
- self.url = (
- reverse("footer_html")
- + f"?project={self.pip.slug}&version={self.latest.slug}&page=index&docroot=/"
- )
- response = self.render()
- self.assertIn("/en/latest/", response.data["html"])
- self.assertNotIn("/en/2.0/", response.data["html"])
-
- # We can access the hidden version, but it doesn't appear on the footer
- self.url = (
- reverse("footer_html")
- + f"?project={self.pip.slug}&version={hidden_version.slug}&page=index&docroot=/"
- )
- response = self.render()
- self.assertIn("/en/latest/", response.data["html"])
- self.assertNotIn("/en/2.0/", response.data["html"])
-
- def test_built_versions(self):
- built_version = get(
- Version,
- slug="2.0",
- active=True,
- built=True,
- privacy_level=PUBLIC,
- project=self.pip,
- )
-
- # The built versions appears on the footer
- self.url = (
- reverse("footer_html")
- + f"?project={self.pip.slug}&version={self.latest.slug}&page=index&docroot=/"
- )
- response = self.render()
- self.assertIn("/en/latest/", response.data["html"])
- self.assertIn("/en/2.0/", response.data["html"])
-
- # We can access the built version, and it appears on the footer
- self.url = (
- reverse("footer_html")
- + f"?project={self.pip.slug}&version={built_version.slug}&page=index&docroot=/"
- )
- response = self.render()
- self.assertIn("/en/latest/", response.data["html"])
- self.assertIn("/en/2.0/", response.data["html"])
-
- def test_not_built_versions(self):
- not_built_version = get(
- Version,
- slug="2.0",
- active=True,
- built=False,
- privacy_level=PUBLIC,
- project=self.pip,
- )
-
- # The un-built version doesn't appear on the footer
- self.url = (
- reverse("footer_html")
- + f"?project={self.pip.slug}&version={self.latest.slug}&page=index&docroot=/"
- )
- response = self.render()
- self.assertIn("/en/latest/", response.data["html"])
- self.assertNotIn("/en/2.0/", response.data["html"])
-
- # We can access the unbuilt version, but it doesn't appear on the footer
- self.url = (
- reverse("footer_html")
- + f"?project={self.pip.slug}&version={not_built_version.slug}&page=index&docroot=/"
- )
- response = self.render()
- self.assertIn("/en/latest/", response.data["html"])
- self.assertNotIn("/en/2.0/", response.data["html"])
-
- def test_invalid_footer_url(self):
- # The built versions appears on the footer
- self.url = reverse("footer_html") + "/invalid/url"
- response = self.render()
- self.assertEqual(response.status_code, 404)
-
-
-class TestFooterHTML(BaseTestFooterHTML, TestCase):
- pass
-
-
-@override_settings(
- PUBLIC_DOMAIN="readthedocs.io",
- PUBLIC_DOMAIN_USES_HTTPS=True,
-)
-class TestVersionCompareFooter(TestCase):
- fixtures = ["test_data", "eric"]
-
- def setUp(self):
- self.pip = Project.objects.get(slug="pip")
- self.pip.versions.update(built=True)
- self.pip.show_version_warning = True
- self.pip.privacy_level = PUBLIC
- self.pip.save()
- self.pip.versions.update(privacy_level=PUBLIC)
-
- self.user = User.objects.get(username="eric")
-
- def test_highest_version_from_stable(self):
- base_version = self.pip.get_stable_version()
- valid_data = {
- "project": "0.8.1",
- "url": "https://pip.readthedocs.io/en/0.8.1/",
- "slug": "0.8.1",
- "version": "0.8.1",
- "is_highest": True,
- }
- returned_data = get_version_compare_data(self.pip, base_version)
- self.assertDictEqual(valid_data, returned_data)
-
- def test_highest_version_from_lower(self):
- base_version = self.pip.versions.get(slug="0.8")
- valid_data = {
- "project": "0.8.1",
- "url": "https://pip.readthedocs.io/en/0.8.1/",
- "slug": "0.8.1",
- "version": "0.8.1",
- "is_highest": False,
- }
- returned_data = get_version_compare_data(self.pip, base_version)
- self.assertDictEqual(valid_data, returned_data)
-
- def test_highest_version_from_latest(self):
- self.pip.versions.filter(slug=LATEST).update(built=True)
- base_version = self.pip.versions.get(slug=LATEST)
- valid_data = {
- "project": "0.8.1",
- "url": "https://pip.readthedocs.io/en/0.8.1/",
- "slug": "0.8.1",
- "version": "0.8.1",
- "is_highest": True,
- }
- returned_data = get_version_compare_data(self.pip, base_version)
- self.assertDictEqual(valid_data, returned_data)
-
- def test_highest_version_over_branches(self):
- Version.objects.create(
- project=self.pip,
- verbose_name="2.0.0",
- identifier="2.0.0",
- type=BRANCH,
- active=True,
- )
-
- version = Version.objects.create(
- project=self.pip,
- verbose_name="1.0.0",
- identifier="1.0.0",
- type=TAG,
- active=True,
- built=True,
- )
-
- base_version = self.pip.versions.get(slug="0.8.1")
- valid_data = {
- "project": "1.0.0",
- "url": "https://pip.readthedocs.io/en/1.0.0/",
- "slug": "1.0.0",
- "version": "1.0.0",
- "is_highest": False,
- }
- returned_data = get_version_compare_data(self.pip, base_version)
- self.assertDictEqual(valid_data, returned_data)
-
- def test_highest_version_without_tags(self):
- self.pip.versions.filter(type=TAG).update(type=BRANCH)
-
- base_version = self.pip.versions.get(slug="0.8.1")
- valid_data = {
- "project": "0.8.1",
- "url": "https://pip.readthedocs.io/en/0.8.1/",
- "slug": "0.8.1",
- "version": "0.8.1",
- "is_highest": True,
- }
- returned_data = get_version_compare_data(self.pip, base_version)
- self.assertDictEqual(valid_data, returned_data)
-
- base_version = self.pip.versions.get(slug="0.8")
- valid_data = {
- "project": "0.8.1",
- "url": "https://pip.readthedocs.io/en/0.8.1/",
- "slug": "0.8.1",
- "version": "0.8.1",
- "is_highest": False,
- }
- returned_data = get_version_compare_data(self.pip, base_version)
- self.assertDictEqual(valid_data, returned_data)
-
- version = Version.objects.create(
- project=self.pip,
- verbose_name="2.0.0",
- identifier="2.0.0",
- type=BRANCH,
- active=True,
- built=True,
- )
- valid_data = {
- "project": "2.0.0",
- "url": "https://pip.readthedocs.io/en/2.0.0/",
- "slug": "2.0.0",
- "version": "2.0.0",
- "is_highest": False,
- }
- returned_data = get_version_compare_data(self.pip, base_version)
- self.assertDictEqual(valid_data, returned_data)
-
- @override_settings(
- RTD_ALLOW_ORGANIZATIONS=True,
- )
- def test_private_highest_version(self):
- get(Organization, projects=[self.pip], owners=[self.user])
- self.pip.versions.update(privacy_level=PRIVATE)
- base_version = self.pip.versions.get(slug="0.8")
- returned_data = get_version_compare_data(self.pip, base_version)
- self.assertTrue(returned_data["is_highest"])
-
- returned_data = get_version_compare_data(self.pip, base_version, user=self.user)
- valid_data = {
- "project": "0.8.1",
- "url": "https://pip.readthedocs.io/en/0.8.1/",
- "slug": "0.8.1",
- "version": "0.8.1",
- "is_highest": False,
- }
- self.assertDictEqual(valid_data, returned_data)
-
-
-@pytest.mark.proxito
-@override_settings(
- PUBLIC_DOMAIN="readthedocs.io",
- RTD_DEFAULT_FEATURES=dict([RTDProductFeature(type=TYPE_CNAME, value=2).to_item()]),
-)
-class TestFooterPerformance(TestCase):
- # The expected number of queries for generating the footer
- # This shouldn't increase unless we modify the footer API
- EXPECTED_QUERIES = 11
-
- def setUp(self):
- self.pip = get(
- Project,
- slug="pip",
- repo="https://github.com/rtfd/readthedocs.org",
- privacy_level=PUBLIC,
- show_version_warning=True,
- main_language_project=None,
- )
- self.pip.versions.create(
- verbose_name="0.8.1",
- identifier="0.8.1",
- type=TAG,
- )
- self.pip.versions.update(privacy_level=PUBLIC, built=True, active=True)
- self.latest = self.pip.versions.get(slug=LATEST)
-
- self.url = (
- reverse("footer_html")
- + f"?project={self.pip.slug}&version={self.latest.slug}&page=index&docroot=/docs/"
- )
- self.host = "pip.readthedocs.io"
-
- def test_version_queries(self):
- with self.assertNumQueries(self.EXPECTED_QUERIES):
- response = self.client.get(self.url, headers={"host": self.host})
- self.assertContains(response, "0.8.1")
-
- # Second time we don't create a new page view,
- # this shouldn't impact the number of queries.
- with self.assertNumQueries(self.EXPECTED_QUERIES):
- response = self.client.get(self.url, headers={"host": self.host})
- self.assertContains(response, "0.8.1")
-
- # The number of Versions shouldn't impact the number of queries
- for patch in range(3):
- identifier = "0.99.{}".format(patch)
- self.pip.versions.create(
- verbose_name=identifier,
- identifier=identifier,
- type=TAG,
- active=True,
- built=True,
- )
-
- with self.assertNumQueries(self.EXPECTED_QUERIES):
- response = self.client.get(self.url, headers={"host": self.host})
- self.assertContains(response, "0.99.0")
-
- def test_domain_queries(self):
- domain = "docs.foobar.com"
- self.pip.domains.create(
- domain=f"http://{domain}",
- canonical=True,
- )
-
- with self.assertNumQueries(self.EXPECTED_QUERIES):
- response = self.client.get(self.url, headers={"host": domain})
- self.assertContains(response, domain)
diff --git a/readthedocs/rtd_tests/tests/test_privacy_urls.py b/readthedocs/rtd_tests/tests/test_privacy_urls.py
index ace93325952..54319deb9c8 100644
--- a/readthedocs/rtd_tests/tests/test_privacy_urls.py
+++ b/readthedocs/rtd_tests/tests/test_privacy_urls.py
@@ -439,9 +439,6 @@ def setUp(self):
"buildcommandresult-detail": {"pk": self.build_command_result.pk},
"version-detail": {"pk": self.pip.versions.all()[0].pk},
"domain-detail": {"pk": self.domain.pk},
- "footer_html": {
- "data": {"project": "pip", "version": "latest", "page": "index"}
- },
"remoteorganization-detail": {"pk": self.remote_org.pk},
"remoterepository-detail": {"pk": self.remote_repo.pk},
"remoteaccount-detail": {"pk": self.social_account.pk},
diff --git a/readthedocs/rtd_tests/tests/test_resolver.py b/readthedocs/rtd_tests/tests/test_resolver.py
index 87e9cb97cce..fa4d78de13a 100644
--- a/readthedocs/rtd_tests/tests/test_resolver.py
+++ b/readthedocs/rtd_tests/tests/test_resolver.py
@@ -606,9 +606,6 @@ def test_resolve_project_object(self):
url = resolver.resolve_project(self.pip, filename="index.html")
self.assertEqual(url, "http://pip.readthedocs.org/index.html")
- url = resolver.resolve_project(self.pip, filename="/_/api/v2/footer_html")
- self.assertEqual(url, "http://pip.readthedocs.org/_/api/v2/footer_html")
-
def test_resolve_subproject_object(self):
url = resolver.resolve_project(self.subproject)
self.assertEqual(url, "http://pip.readthedocs.org/")
@@ -616,11 +613,6 @@ def test_resolve_subproject_object(self):
url = resolver.resolve_project(self.subproject, filename="index.html")
self.assertEqual(url, "http://pip.readthedocs.org/index.html")
- url = resolver.resolve_project(
- self.subproject, filename="/_/api/v2/footer_html"
- )
- self.assertEqual(url, "http://pip.readthedocs.org/_/api/v2/footer_html")
-
def test_resolve_translation_object(self):
url = resolver.resolve_project(self.translation)
self.assertEqual(url, "http://pip.readthedocs.org/")
@@ -628,11 +620,6 @@ def test_resolve_translation_object(self):
url = resolver.resolve_project(self.translation, filename="index.html")
self.assertEqual(url, "http://pip.readthedocs.org/index.html")
- url = resolver.resolve_project(
- self.translation, filename="/_/api/v2/footer_html"
- )
- self.assertEqual(url, "http://pip.readthedocs.org/_/api/v2/footer_html")
-
def test_resolve_version_object(self):
url = resolver.resolve_version(self.pip)
self.assertEqual(url, "http://pip.readthedocs.org/en/latest/")
diff --git a/readthedocs/settings/base.py b/readthedocs/settings/base.py
index 58626c017dd..cc119dc6644 100644
--- a/readthedocs/settings/base.py
+++ b/readthedocs/settings/base.py
@@ -756,8 +756,7 @@ def SOCIALACCOUNT_PROVIDERS(self):
CORS_URLS_REGEX = re.compile(
r"""
^(
- /api/v2/footer_html
- |/api/v2/search
+ /api/v2/search
|/api/v2/docsearch
|/api/v2/embed
|/api/v3/embed