Skip to content

Commit

Permalink
Use API V3 (#132)
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
stsewd authored Mar 27, 2023
1 parent c8cb912 commit ca36a15
Show file tree
Hide file tree
Showing 14 changed files with 282 additions and 64 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: 2.1

orbs:
browser-tools: circleci/browser-tools@1.1.1
browser-tools: circleci/browser-tools@1.4.1

commands:
run-tox:
Expand Down
8 changes: 2 additions & 6 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
version: 2

build:
os: "ubuntu-20.04"
os: "ubuntu-22.04"
tools:
# sphinx-js isn't compatible with python 3.10.
# https://github.com/mozilla/sphinx-js/issues/186
python: "3.9"
python: "3"
nodejs: "16"

python:
Expand All @@ -16,5 +14,3 @@ python:

sphinx:
configuration: docs/conf.py

formats: []
7 changes: 5 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import os
from pathlib import Path
import sys
sys.path.insert(0, os.path.abspath('..'))
sys.path.append(os.path.abspath("./_ext"))
sys.path.insert(0, str(Path(__file__).parent.parent))
sys.path.insert(0, str(Path(__file__).parent / "_ext"))

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

Expand Down Expand Up @@ -100,6 +101,8 @@

if not ON_RTD:
html_js_files = ['rtd_dummy_data.js']
os.environ['READTHEDOCS_PROJECT'] = 'readthedocs-sphinx-search'
os.environ['READTHEDOCS_VERSION'] = 'latest'

# Custom sidebar templates, must be a dictionary that maps document names
# to template names.
Expand Down
44 changes: 44 additions & 0 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,47 @@ You can customize these configuration options in your ``conf.py`` file:
Default: ``'minified'``

Type: ``string``

.. confval:: rtd_sphinx_search_default_filter

Description: Default filter to be used when the user hasn't selected any other filters.
The filter will simply be appended to the current search query.

Default: ``project:<project>/<version>``

Type: ``string``

Example:

.. code-block:: python
# https://docs.readthedocs.io/page/reference/environment-variables.html
project = os.environ["READTHEDOCS_PROJECT"]
version = os.environ["READTHEDOCS_VERSION"]
# Include results from subprojects by default.
rtd_sphinx_search_default_filter = f"subprojects:{project}/{version}"
.. confval:: rtd_sphinx_search_filters

Description: Map of filters to show in the search bar.
The key is the name of the filter to show to the user,
and the value is the filter itself.
The filter will simply be appended to the current search query.

Default: ``{}``

Type: ``dict``

Example:

.. code-block:: python
# https://docs.readthedocs.io/page/reference/environment-variables.html
project = os.environ["READTHEDOCS_PROJECT"]
version = os.environ["READTHEDOCS_VERSION"]
rtd_sphinx_search_filters = {
"Search this project": f"project:{project}/{version}",
"Search subprojects": f"subprojects:{project}/{version}",
}
2 changes: 1 addition & 1 deletion docs/development.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Go to http://127.0.0.1:8000 and start searching!

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

Releasing
---------
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 49 additions & 7 deletions sphinx_search/extension.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import os

from sphinx_search import __version__
from sphinx.errors import ExtensionError
from pathlib import Path
from sphinx.util.fileutil import copy_asset

ASSETS_FILES = {
'minified': [
os.path.join('js', 'rtd_sphinx_search.min.js'),
os.path.join('css', 'rtd_sphinx_search.min.css'),
Path("js/rtd_search_config.js_t"),
Path("js/rtd_sphinx_search.min.js"),
Path("css/rtd_sphinx_search.min.css"),
],
'un-minified': [
os.path.join('js', 'rtd_sphinx_search.js'),
os.path.join('css', 'rtd_sphinx_search.css'),
Path("js/rtd_search_config.js_t"),
Path("js/rtd_sphinx_search.js"),
Path("css/rtd_sphinx_search.css"),
]
}

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


def get_context(config):
"""
Get context for templates.
This mainly returns the settings from the extension
that are needed in our JS code.
"""
default_filter = config.rtd_sphinx_search_default_filter
filters = config.rtd_sphinx_search_filters
# When converting to JSON, the order of the keys is not guaranteed.
# So we pass a list of tuples to preserve the order.
filters = [(name, filter) for name, filter in filters.items()]
return {
"rtd_search_config": {
"filters": filters,
"default_filter": default_filter,
}
}


def copy_asset_files(app, exception):
"""
Copy assets files to the output directory.
If the name of the file ends with ``_t``, it will be interpreted as a template.
"""
if exception is None: # build succeeded
root = Path(__file__).parent
for file in _get_static_files(app.config):
path = os.path.join(os.path.dirname(__file__), 'static', file)
copy_asset(path, os.path.join(app.outdir, '_static', file.split('.')[-1]))
source = root / 'static' / file
destination = Path(app.outdir) / '_static' / file.parent
context = None
# If the file ends with _t, it is a template file,
# so we provide a context to treat it as a template.
if file.name.endswith('_t'):
context = get_context(app.config)
copy_asset(str(source), str(destination), context=context)


def inject_static_files(app):
"""Inject correct CSS and JS files based on the value of ``rtd_sphinx_search_file_type``."""
for file in _get_static_files(app.config):
file = str(file)
# Templates end with `_t`, Sphinx removes the _t when copying the file.
if file.endswith('_t'):
file = file[:-2]
if file.endswith('.js'):
app.add_js_file(file)
elif file.endswith('.css'):
app.add_css_file(file)


def setup(app):
project = os.environ.get('READTHEDOCS_PROJECT', '')
version = os.environ.get('READTHEDOCS_VERSION', '')

app.add_config_value('rtd_sphinx_search_file_type', 'minified', 'html')
app.add_config_value('rtd_sphinx_search_default_filter', f'project:{project}/{version}', 'html')
app.add_config_value('rtd_sphinx_search_filters', {}, 'html')

app.connect('builder-inited', inject_static_files)
app.connect('build-finished', copy_asset_files)
Expand Down
33 changes: 32 additions & 1 deletion sphinx_search/static/css/rtd_sphinx_search.css
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,12 @@

/* Search result */

.search__result__box {
padding: 0px 10px;
}

.search__result__single {
margin-top: 10px;
padding: 0px 10px;
border-bottom: 1px solid #e6e6e6;
}

Expand Down Expand Up @@ -282,6 +285,34 @@
letter-spacing: 1px;
}

.search__filters {
padding: 0px 10px;
}

.search__filters ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
}

.search__filters li {
display: flex;
align-items: center;
margin-right: 15px;
}

.search__filters label {
color: black;
font-size: 15px;
margin: auto;
}

.search__filters .search__filters__title {
color: black;
font-size: 15px;
}

@media (max-width: 670px) {
.rtd__search__credits {
height: 50px;
Expand Down
2 changes: 1 addition & 1 deletion sphinx_search/static/css/rtd_sphinx_search.min.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions sphinx_search/static/js/rtd_search_config.js_t
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{# Set the extension options as a JSON object, so it can be used from our JS code. #}
var RTD_SEARCH_CONFIG = {{ rtd_search_config | tojson }};
Loading

0 comments on commit ca36a15

Please sign in to comment.