Skip to content

Commit 5130e1e

Browse files
Revathyvenugopal162pyansys-ci-botjorgepiloto
authored
fix: add more components to the search indexing (#541)
Co-authored-by: pyansys-ci-bot <[email protected]> Co-authored-by: Jorge Martínez <[email protected]>
1 parent 724d0ef commit 5130e1e

File tree

6 files changed

+125
-14
lines changed

6 files changed

+125
-14
lines changed

doc/changelog.d/541.documentation.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fix: add more components to the search indexing

doc/source/conf.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
from sphinx.builders.latex import LaTeXBuilder
1212

1313
from ansys_sphinx_theme import (
14+
ALL_NODES,
15+
PARAGRAPHS,
16+
TITLES,
1417
__version__,
1518
ansys_favicon,
1619
ansys_logo_white,
@@ -65,6 +68,11 @@
6568
},
6669
}
6770

71+
index_patterns = {
72+
"examples/api/": ALL_NODES,
73+
"examples/sphinx_examples/": TITLES + PARAGRAPHS,
74+
}
75+
6876

6977
# Sphinx extensions
7078
extensions = [

doc/source/user-guide/options.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,23 @@ the ``delay`` key in the ``static_search`` dictionary with a value specifying
124124
the amount of milliseconds to wait before executing the search. A value of
125125
``0`` disables the debounce function.
126126

127+
To customise the indexing of your documentation, you can use the ``index_patterns`` dictionary in the ``conf.py`` file.
128+
This dictionary contains the paths to the directories you want to index and the type of nodes to index.
129+
The type of nodes can be ``ALL_NODES``, ``TITLES`` or ``PARAGRAPHS``.
130+
The default value is ``TITLES + PARAGRAPHS``.
131+
132+
Here is an example of how to add the ``index_patterns`` dictionary to the `conf.py`` file:
133+
134+
.. code-block:: python
135+
136+
index_patterns = {
137+
"api/": ALL_NODES,
138+
"examples/": TITLES + PARAGRAPHS,
139+
}
140+
141+
The above example indexes all nodes in the ``api/`` directory and only titles and paragraphs in the ``examples/`` directory.
142+
143+
127144
.. note::
128145

129146
All other options are available in the `Fuse.js documentation <https://fusejs.io/api/options.html>`_.

src/ansys_sphinx_theme/__init__.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,19 @@
2828
import subprocess
2929
from typing import Any, Dict
3030

31-
from docutils.nodes import document
31+
from docutils import nodes
3232
from sphinx import addnodes
3333
from sphinx.application import Sphinx
3434

3535
from ansys_sphinx_theme.extension.linkcode import DOMAIN_KEYS, sphinx_linkcode_resolve
36-
from ansys_sphinx_theme.latex import generate_404 # noqa: F401
37-
from ansys_sphinx_theme.search import create_search_index, update_search_config
36+
from ansys_sphinx_theme.latex import generate_404
37+
from ansys_sphinx_theme.search import (
38+
ALL_NODES,
39+
PARAGRAPHS,
40+
TITLES,
41+
create_search_index,
42+
update_search_config,
43+
)
3844

3945
try:
4046
import importlib.metadata as importlib_metadata
@@ -170,7 +176,7 @@ def setup_default_html_theme_options(app):
170176

171177

172178
def fix_edit_html_page_context(
173-
app: Sphinx, pagename: str, templatename: str, context: dict, doctree: document
179+
app: Sphinx, pagename: str, templatename: str, context: dict, doctree: nodes.document
174180
) -> None:
175181
"""Add a function that Jinja can access for returning an "edit this page" link .
176182
@@ -271,7 +277,7 @@ def fix_edit_link_page(link: str) -> str:
271277

272278

273279
def update_footer_theme(
274-
app: Sphinx, pagename: str, templatename: str, context: Dict[str, Any], doctree: document
280+
app: Sphinx, pagename: str, templatename: str, context: Dict[str, Any], doctree: nodes.document
275281
) -> None:
276282
"""Update the version number of the Ansys Sphinx theme in the footer.
277283
@@ -401,7 +407,7 @@ def convert_pdf_to_png(pdf_path: pathlib.Path, output_dir: pathlib.Path, output_
401407

402408

403409
def add_cheat_sheet(
404-
app: Sphinx, pagename: str, templatename: str, context: Dict[str, Any], doctree: document
410+
app: Sphinx, pagename: str, templatename: str, context: Dict[str, Any], doctree: nodes.document
405411
) -> None:
406412
"""Add a cheat sheet to the left navigation sidebar.
407413
@@ -578,3 +584,6 @@ def setup(app: Sphinx) -> Dict:
578584
"parallel_read_safe": True,
579585
"parallel_write_safe": True,
580586
}
587+
588+
589+
__all__ = ["__version__", "generate_404", "get_version_match", "TITLEs", "PARAGRAPHS", "ALL_NODES"]

src/ansys_sphinx_theme/search/__init__.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,13 @@
2323

2424
from sphinx.application import Sphinx
2525

26-
from ansys_sphinx_theme.search.fuse_search import create_search_index
26+
from ansys_sphinx_theme.search.fuse_search import (
27+
ALL_NODES,
28+
LITERAL,
29+
PARAGRAPHS,
30+
TITLES,
31+
create_search_index,
32+
)
2733

2834

2935
def update_search_config(app: Sphinx) -> None:
@@ -38,7 +44,15 @@ def update_search_config(app: Sphinx) -> None:
3844
theme_static_options["keys"] = ["title", "text"]
3945
theme_static_options["threshold"] = theme_static_options.get("threshold", 0.2)
4046
theme_static_options["limit"] = theme_static_options.get("limit", 10)
47+
app.add_config_value("index_patterns", {}, "html")
4148
app.config.html_theme_options["static_search"] = theme_static_options
4249

4350

44-
__all__ = ["create_search_index", "update_search_config"]
51+
__all__ = [
52+
"create_search_index",
53+
"update_search_config",
54+
"LITERAL",
55+
"PARAGRAPHS",
56+
"TITLES",
57+
"ALL_NODES",
58+
]

src/ansys_sphinx_theme/search/fuse_search.py

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,19 @@
2727
import re
2828

2929
from docutils import nodes
30+
from docutils.nodes import Element
31+
32+
PARAGRAPHS = [nodes.paragraph]
33+
TITLES = [nodes.title]
34+
LITERAL = [nodes.literal]
35+
ALL_NODES = [nodes.Text]
36+
DEFAULT_PATTERN = PARAGRAPHS + TITLES + LITERAL
3037

3138

3239
class SearchIndex:
3340
"""Generate a search index for a Sphinx document."""
3441

35-
def __init__(self, doc_name, app):
42+
def __init__(self, doc_name, app, pattern=None):
3643
"""
3744
Initialize the search index object.
3845
@@ -46,19 +53,31 @@ def __init__(self, doc_name, app):
4653
self.doc_name = doc_name
4754
self.doc_path = f"{self.doc_name}.html"
4855
self.env = app.env
56+
self.theme_options = app.config.html_theme_options.get("static_search", {})
4957
self.doc_title = self.env.titles[self.doc_name].astext()
5058
self.doc_tree = self.env.get_doctree(self.doc_name)
5159
self.sections = []
60+
self.pattern = pattern
5261

5362
def build_sections(self):
54-
"""Build sections from the document tree."""
63+
"""Build sections from the document tree, handling subsections and descriptions."""
5564
for node in self.doc_tree.traverse(nodes.section):
65+
subsections = list(node.traverse(nodes.section))
66+
67+
if len(subsections) > 1:
68+
# get only the first section
69+
main_section = subsections[0]
70+
# remove subsections from the main section
71+
for subsection in main_section.traverse(nodes.section):
72+
subsection.parent.remove(subsection)
73+
node = main_section
74+
5675
section_title = node[0].astext()
76+
5777
section_text = "\n".join(
58-
n.astext()
59-
for node_type in [nodes.paragraph, nodes.literal_block]
60-
for n in node.traverse(node_type)
78+
n.astext() for node_type in self.pattern for n in node.traverse(node_type)
6179
)
80+
6281
section_anchor_id = _title_to_anchor(section_title)
6382
self.sections.append(
6483
{
@@ -68,6 +87,31 @@ def build_sections(self):
6887
}
6988
)
7089

90+
self._process_desc_element(node, section_title)
91+
92+
def _process_desc_element(self, node, title):
93+
"""Process `desc` element within a section."""
94+
for element in node.traverse(Element):
95+
if element.tagname != "desc":
96+
continue
97+
98+
# id is the id tag of the desc element
99+
section_anchor_id = element.attributes["ids"]
100+
if element.children:
101+
for element_child in element.children:
102+
if element_child.tagname != "desc_signature":
103+
continue
104+
section_anchor_id = element_child.attributes["ids"][0]
105+
section_text = element.astext()
106+
section_title = _desc_anchor_to_title(title, section_anchor_id)
107+
self.sections.append(
108+
{
109+
"title": section_title,
110+
"text": section_text,
111+
"anchor_id": section_anchor_id,
112+
}
113+
)
114+
71115
def generate_breadcrumbs(self, section_title: str) -> str:
72116
"""
73117
Generate title breadcrumbs from the document structure.
@@ -122,11 +166,28 @@ def indices(self):
122166
}
123167

124168

169+
def _desc_anchor_to_title(title, anchor):
170+
"""Convert a desc anchor to a title."""
171+
anchor_title = anchor.split(".")[-1]
172+
return f"{title} > {anchor_title}"
173+
174+
125175
def _title_to_anchor(title: str) -> str:
126176
"""Convert a title to a URL-friendly anchor identifier."""
127177
return re.sub(r"[^\w\s-]", "", title.lower().strip().replace(" ", "-"))
128178

129179

180+
def get_pattern_for_each_page(app, doc_name):
181+
"""Get the pattern for each page in the search index."""
182+
patterns = app.env.config.index_patterns or {}
183+
184+
for filename, pattern in patterns.items():
185+
if doc_name.startswith(filename):
186+
return pattern
187+
188+
return DEFAULT_PATTERN
189+
190+
130191
def create_search_index(app, exception):
131192
"""
132193
Generate search index at the end of the Sphinx build process.
@@ -144,7 +205,8 @@ def create_search_index(app, exception):
144205
search_index_list = []
145206

146207
for document in app.env.found_docs:
147-
search_index = SearchIndex(document, app)
208+
pattern = get_pattern_for_each_page(app, document)
209+
search_index = SearchIndex(document, app, pattern)
148210
search_index.build_sections()
149211
search_index_list.extend(search_index.indices)
150212

0 commit comments

Comments
 (0)