Skip to content
This repository was archived by the owner on Apr 8, 2025. It is now read-only.

Commit ca36a15

Browse files
authored
Use API V3 (#132)
- Added 2 new options: rtd_sphinx_search_default_filter and rtd_sphinx_search_filters. - The options are passed as a JSON object to be read by our JS code. - The default filter defaults to the current project and version (extracted from the RTD env vars) - Filters are implemented as check boxes, we only support one filter at a time (when a filter is selected, we uncheck all others) How to test locally: - Run your local version of RTD - To allow cross site requests, add `|/api/v3/search` at https://github.com/readthedocs/readthedocs.org/blob/b574f4b0dad34ccba8595cee72246d3473f8a2e5/readthedocs/settings/base.py#L769-L781 - Change the `rtd_dummy_data.json` file - `'proxied_api_host': 'http://devthedocs.org'` - Set the project and version to a project that you have locally - Change the value of `rtd_sphinx_search_default_filter = "project:superproject/latest"` to the slug of a project you have locally - Build the docs: ``` cd docs make clean html ``` - Open the _build/index.html file. ### showcase [showcase.webm](https://user-images.githubusercontent.com/4975310/225148123-7811d477-3a91-4eea-b9fb-b8cb1cbf0d6a.webm) Closes #129 Closes #130 Closes #131
1 parent c8cb912 commit ca36a15

14 files changed

+282
-64
lines changed

.circleci/config.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
version: 2.1
22

33
orbs:
4-
browser-tools: circleci/browser-tools@1.1.1
4+
browser-tools: circleci/browser-tools@1.4.1
55

66
commands:
77
run-tox:

.readthedocs.yaml

+2-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
version: 2
22

33
build:
4-
os: "ubuntu-20.04"
4+
os: "ubuntu-22.04"
55
tools:
6-
# sphinx-js isn't compatible with python 3.10.
7-
# https://github.com/mozilla/sphinx-js/issues/186
8-
python: "3.9"
6+
python: "3"
97
nodejs: "16"
108

119
python:
@@ -16,5 +14,3 @@ python:
1614

1715
sphinx:
1816
configuration: docs/conf.py
19-
20-
formats: []

docs/conf.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
# documentation root, use os.path.abspath to make it absolute, like shown here.
1212
#
1313
import os
14+
from pathlib import Path
1415
import sys
15-
sys.path.insert(0, os.path.abspath('..'))
16-
sys.path.append(os.path.abspath("./_ext"))
16+
sys.path.insert(0, str(Path(__file__).parent.parent))
17+
sys.path.insert(0, str(Path(__file__).parent / "_ext"))
1718

1819
ON_RTD = os.environ.get('READTHEDOCS', False)
1920

@@ -100,6 +101,8 @@
100101

101102
if not ON_RTD:
102103
html_js_files = ['rtd_dummy_data.js']
104+
os.environ['READTHEDOCS_PROJECT'] = 'readthedocs-sphinx-search'
105+
os.environ['READTHEDOCS_VERSION'] = 'latest'
103106

104107
# Custom sidebar templates, must be a dictionary that maps document names
105108
# to template names.

docs/configuration.rst

+44
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,47 @@ You can customize these configuration options in your ``conf.py`` file:
1616
Default: ``'minified'``
1717

1818
Type: ``string``
19+
20+
.. confval:: rtd_sphinx_search_default_filter
21+
22+
Description: Default filter to be used when the user hasn't selected any other filters.
23+
The filter will simply be appended to the current search query.
24+
25+
Default: ``project:<project>/<version>``
26+
27+
Type: ``string``
28+
29+
Example:
30+
31+
.. code-block:: python
32+
33+
# https://docs.readthedocs.io/page/reference/environment-variables.html
34+
project = os.environ["READTHEDOCS_PROJECT"]
35+
version = os.environ["READTHEDOCS_VERSION"]
36+
37+
# Include results from subprojects by default.
38+
rtd_sphinx_search_default_filter = f"subprojects:{project}/{version}"
39+
40+
.. confval:: rtd_sphinx_search_filters
41+
42+
Description: Map of filters to show in the search bar.
43+
The key is the name of the filter to show to the user,
44+
and the value is the filter itself.
45+
The filter will simply be appended to the current search query.
46+
47+
Default: ``{}``
48+
49+
Type: ``dict``
50+
51+
Example:
52+
53+
.. code-block:: python
54+
55+
# https://docs.readthedocs.io/page/reference/environment-variables.html
56+
project = os.environ["READTHEDOCS_PROJECT"]
57+
version = os.environ["READTHEDOCS_VERSION"]
58+
59+
rtd_sphinx_search_filters = {
60+
"Search this project": f"project:{project}/{version}",
61+
"Search subprojects": f"subprojects:{project}/{version}",
62+
}

docs/development.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Go to http://127.0.0.1:8000 and start searching!
4141

4242
The extension works when is hosted on Read the Docs,
4343
but to make it work locally a custom ``READTHEDOCS_DATA`` js variable is injected automatically
44-
to send the search requests to https://readthedocs.org/api/v2/search/.
44+
to send the search requests to https://readthedocs.org/api/v3/search/.
4545

4646
Releasing
4747
---------

package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sphinx_search/extension.py

+49-7
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
import os
2-
32
from sphinx_search import __version__
43
from sphinx.errors import ExtensionError
4+
from pathlib import Path
55
from sphinx.util.fileutil import copy_asset
66

77
ASSETS_FILES = {
88
'minified': [
9-
os.path.join('js', 'rtd_sphinx_search.min.js'),
10-
os.path.join('css', 'rtd_sphinx_search.min.css'),
9+
Path("js/rtd_search_config.js_t"),
10+
Path("js/rtd_sphinx_search.min.js"),
11+
Path("css/rtd_sphinx_search.min.css"),
1112
],
1213
'un-minified': [
13-
os.path.join('js', 'rtd_sphinx_search.js'),
14-
os.path.join('css', 'rtd_sphinx_search.css'),
14+
Path("js/rtd_search_config.js_t"),
15+
Path("js/rtd_sphinx_search.js"),
16+
Path("css/rtd_sphinx_search.css"),
1517
]
1618
}
1719

@@ -24,25 +26,65 @@ def _get_static_files(config):
2426
return ASSETS_FILES[file_type]
2527

2628

29+
def get_context(config):
30+
"""
31+
Get context for templates.
32+
33+
This mainly returns the settings from the extension
34+
that are needed in our JS code.
35+
"""
36+
default_filter = config.rtd_sphinx_search_default_filter
37+
filters = config.rtd_sphinx_search_filters
38+
# When converting to JSON, the order of the keys is not guaranteed.
39+
# So we pass a list of tuples to preserve the order.
40+
filters = [(name, filter) for name, filter in filters.items()]
41+
return {
42+
"rtd_search_config": {
43+
"filters": filters,
44+
"default_filter": default_filter,
45+
}
46+
}
47+
48+
2749
def copy_asset_files(app, exception):
50+
"""
51+
Copy assets files to the output directory.
52+
53+
If the name of the file ends with ``_t``, it will be interpreted as a template.
54+
"""
2855
if exception is None: # build succeeded
56+
root = Path(__file__).parent
2957
for file in _get_static_files(app.config):
30-
path = os.path.join(os.path.dirname(__file__), 'static', file)
31-
copy_asset(path, os.path.join(app.outdir, '_static', file.split('.')[-1]))
58+
source = root / 'static' / file
59+
destination = Path(app.outdir) / '_static' / file.parent
60+
context = None
61+
# If the file ends with _t, it is a template file,
62+
# so we provide a context to treat it as a template.
63+
if file.name.endswith('_t'):
64+
context = get_context(app.config)
65+
copy_asset(str(source), str(destination), context=context)
3266

3367

3468
def inject_static_files(app):
3569
"""Inject correct CSS and JS files based on the value of ``rtd_sphinx_search_file_type``."""
3670
for file in _get_static_files(app.config):
71+
file = str(file)
72+
# Templates end with `_t`, Sphinx removes the _t when copying the file.
73+
if file.endswith('_t'):
74+
file = file[:-2]
3775
if file.endswith('.js'):
3876
app.add_js_file(file)
3977
elif file.endswith('.css'):
4078
app.add_css_file(file)
4179

4280

4381
def setup(app):
82+
project = os.environ.get('READTHEDOCS_PROJECT', '')
83+
version = os.environ.get('READTHEDOCS_VERSION', '')
4484

4585
app.add_config_value('rtd_sphinx_search_file_type', 'minified', 'html')
86+
app.add_config_value('rtd_sphinx_search_default_filter', f'project:{project}/{version}', 'html')
87+
app.add_config_value('rtd_sphinx_search_filters', {}, 'html')
4688

4789
app.connect('builder-inited', inject_static_files)
4890
app.connect('build-finished', copy_asset_files)

sphinx_search/static/css/rtd_sphinx_search.css

+32-1
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,12 @@
149149

150150
/* Search result */
151151

152+
.search__result__box {
153+
padding: 0px 10px;
154+
}
155+
152156
.search__result__single {
153157
margin-top: 10px;
154-
padding: 0px 10px;
155158
border-bottom: 1px solid #e6e6e6;
156159
}
157160

@@ -282,6 +285,34 @@
282285
letter-spacing: 1px;
283286
}
284287

288+
.search__filters {
289+
padding: 0px 10px;
290+
}
291+
292+
.search__filters ul {
293+
list-style: none;
294+
padding: 0;
295+
margin: 0;
296+
display: flex;
297+
}
298+
299+
.search__filters li {
300+
display: flex;
301+
align-items: center;
302+
margin-right: 15px;
303+
}
304+
305+
.search__filters label {
306+
color: black;
307+
font-size: 15px;
308+
margin: auto;
309+
}
310+
311+
.search__filters .search__filters__title {
312+
color: black;
313+
font-size: 15px;
314+
}
315+
285316
@media (max-width: 670px) {
286317
.rtd__search__credits {
287318
height: 50px;

sphinx_search/static/css/rtd_sphinx_search.min.css

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{# Set the extension options as a JSON object, so it can be used from our JS code. #}
2+
var RTD_SEARCH_CONFIG = {{ rtd_search_config | tojson }};

0 commit comments

Comments
 (0)