Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/sphinx-doc/sphinx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Turner <9087854+AA-Turner@users.noreply.github.com>2022-09-21 00:08:03 +0300
committerGitHub <noreply@github.com>2022-09-21 00:08:03 +0300
commit8ae81839be3b197007f9916406a7e44b97aa6171 (patch)
tree2b25d0da3a54755662d3cd7f3b7390b8b432ce26
parent56fd7fb8ae1e11937285f6607c43552b9e729ba6 (diff)
Support searching for index entries (#10819)
-rw-r--r--CHANGES2
-rw-r--r--sphinx/search/__init__.py41
-rw-r--r--sphinx/themes/basic/static/searchtools.js18
-rw-r--r--tests/test_search.py6
4 files changed, 64 insertions, 3 deletions
diff --git a/CHANGES b/CHANGES
index 27d82fd59..9c9596fcc 100644
--- a/CHANGES
+++ b/CHANGES
@@ -27,6 +27,8 @@ Features added
* #10718: HTML Search: Save search result score to the HTML element for debugging
* #10673: Make toctree accept 'genindex', 'modindex' and 'search' docnames
* #6316, #10804: Add domain objects to the table of contents. Patch by Adam Turner
+* #6692: HTML Search: Include explicit :rst:dir:`index` directive index entries
+ in the search index and search results. Patch by Adam Turner
Bugs fixed
----------
diff --git a/sphinx/search/__init__.py b/sphinx/search/__init__.py
index eea262d82..0cff8fd25 100644
--- a/sphinx/search/__init__.py
+++ b/sphinx/search/__init__.py
@@ -14,6 +14,7 @@ from docutils.nodes import Element, Node
from sphinx import addnodes, package_dir
from sphinx.deprecation import RemovedInSphinx70Warning
from sphinx.environment import BuildEnvironment
+from sphinx.util import split_into
class SearchLanguage:
@@ -242,6 +243,7 @@ class IndexBuilder:
# stemmed words in titles -> set(docname)
self._title_mapping: Dict[str, Set[str]] = {}
self._all_titles: Dict[str, List[Tuple[str, str]]] = {} # docname -> all titles
+ self._index_entries: Dict[str, List[Tuple[str, str, str]]] = {} # docname -> index entry
self._stem_cache: Dict[str, str] = {} # word -> stemmed word
self._objtypes: Dict[Tuple[str, str], int] = {} # objtype -> index
# objtype index -> (domain, type, objname (localized))
@@ -380,10 +382,15 @@ class IndexBuilder:
for title, titleid in titlelist:
alltitles.setdefault(title, []).append((fn2index[docname], titleid))
+ index_entries: Dict[str, List[Tuple[int, str]]] = {}
+ for docname, entries in self._index_entries.items():
+ for entry, entry_id, main_entry in entries:
+ index_entries.setdefault(entry.lower(), []).append((fn2index[docname], entry_id))
+
return dict(docnames=docnames, filenames=filenames, titles=titles, terms=terms,
objects=objects, objtypes=objtypes, objnames=objnames,
titleterms=title_terms, envversion=self.env.version,
- alltitles=alltitles)
+ alltitles=alltitles, indexentries=index_entries)
def label(self) -> str:
return "%s (code: %s)" % (self.lang.language_name, self.lang.lang)
@@ -441,6 +448,38 @@ class IndexBuilder:
if _filter(stemmed_word) and not already_indexed:
self._mapping.setdefault(stemmed_word, set()).add(docname)
+ # find explicit entries within index directives
+ _index_entries: Set[Tuple[str, str, str]] = set()
+ for node in doctree.findall(addnodes.index):
+ for entry_type, value, tid, main, *index_key in node['entries']:
+ tid = tid or ''
+ try:
+ if entry_type == 'single':
+ try:
+ entry, subentry = split_into(2, 'single', value)
+ except ValueError:
+ entry, = split_into(1, 'single', value)
+ subentry = ''
+ _index_entries.add((entry, tid, main))
+ if subentry:
+ _index_entries.add((subentry, tid, main))
+ elif entry_type == 'pair':
+ first, second = split_into(2, 'pair', value)
+ _index_entries.add((first, tid, main))
+ _index_entries.add((second, tid, main))
+ elif entry_type == 'triple':
+ first, second, third = split_into(3, 'triple', value)
+ _index_entries.add((first, tid, main))
+ _index_entries.add((second, tid, main))
+ _index_entries.add((third, tid, main))
+ elif entry_type in {'see', 'seealso'}:
+ first, second = split_into(2, 'see', value)
+ _index_entries.add((first, tid, main))
+ except ValueError:
+ pass
+
+ self._index_entries[docname] = sorted(_index_entries)
+
def context_for_searchtool(self) -> Dict[str, Any]:
if self.lang.js_splitter_code:
js_splitter_code = self.lang.js_splitter_code
diff --git a/sphinx/themes/basic/static/searchtools.js b/sphinx/themes/basic/static/searchtools.js
index 4c0b8cf7e..d7ada9b46 100644
--- a/sphinx/themes/basic/static/searchtools.js
+++ b/sphinx/themes/basic/static/searchtools.js
@@ -242,6 +242,7 @@ const Search = {
const docNames = Search._index.docnames;
const titles = Search._index.titles;
const allTitles = Search._index.alltitles;
+ const indexEntries = Search._index.indexentries;
// stem the search terms and add them to the correct list
const stemmer = new Stemmer();
@@ -295,6 +296,23 @@ const Search = {
}
}
+ // search for explicit entries in index directives
+ for (const [entry, foundEntries] of Object.entries(indexEntries)) {
+ if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) {
+ for (const [file, id] of foundEntries) {
+ let score = Math.round(100 * queryLower.length / entry.length)
+ results.push([
+ docNames[file],
+ titles[file],
+ id ? "#" + id : "",
+ null,
+ score,
+ filenames[file],
+ ]);
+ }
+ }
+ }
+
// lookup as object
objectTerms.forEach((term) =>
results.push(...Search.performObjectSearch(term, objectTerms))
diff --git a/tests/test_search.py b/tests/test_search.py
index cbe1be54f..c47c6c695 100644
--- a/tests/test_search.py
+++ b/tests/test_search.py
@@ -178,7 +178,8 @@ def test_IndexBuilder():
'test': [0, 1, 2, 3]},
'titles': ('title1_1', 'title1_2', 'title2_1', 'title2_2'),
'titleterms': {'section_titl': [0, 1, 2, 3]},
- 'alltitles': {'section_title': [(0, 'section-title'), (1, 'section-title'), (2, 'section-title'), (3, 'section-title')]}
+ 'alltitles': {'section_title': [(0, 'section-title'), (1, 'section-title'), (2, 'section-title'), (3, 'section-title')]},
+ 'indexentries': {},
}
assert index._objtypes == {('dummy1', 'objtype1'): 0, ('dummy2', 'objtype1'): 1}
assert index._objnames == {0: ('dummy1', 'objtype1', 'objtype1'),
@@ -236,7 +237,8 @@ def test_IndexBuilder():
'test': [0, 1]},
'titles': ('title1_2', 'title2_2'),
'titleterms': {'section_titl': [0, 1]},
- 'alltitles': {'section_title': [(0, 'section-title'), (1, 'section-title')]}
+ 'alltitles': {'section_title': [(0, 'section-title'), (1, 'section-title')]},
+ 'indexentries': {},
}
assert index._objtypes == {('dummy1', 'objtype1'): 0, ('dummy2', 'objtype1'): 1}
assert index._objnames == {0: ('dummy1', 'objtype1', 'objtype1'),