Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support type-dependent search result highlighting via CSS #12474

Merged
merged 8 commits into from
Aug 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ Features added

* #11328: Mention evaluation of templated content during production of static
output files.
* #12474: Support type-dependent search result highlighting via CSS.
Patch by Tim Hoffmann.

Bugs fixed
----------
Expand Down
23 changes: 22 additions & 1 deletion doc/_themes/sphinx13/static/sphinx13.css
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,28 @@ div.sphinx-feature > p.admonition-title::before {
justify-content: center;
gap: 10px;
}

.sphinx-users-logos .headerlink {
display: none;
}

/* -- search results -------------------------------------------------------- */

ul.search {
padding-left: 30px;
}
ul.search li {
padding: 5px 0 5px 10px;
list-style-type: "\25A1"; /* Unicode: White Square */
}
ul.search li.context-index {
list-style-type: "\1F4D1"; /* Unicode: Bookmark Tabs */
}
ul.search li.context-object {
list-style-type: "\1F4E6"; /* Unicode: Package */
}
ul.search li.context-title {
list-style-type: "\1F4C4"; /* Unicode: Page Facing Up */
}
ul.search li.context-text {
list-style-type: "\1F4C4"; /* Unicode: Page Facing Up */
}
58 changes: 58 additions & 0 deletions doc/development/html_themes/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,64 @@ If your theme package contains two or more themes, please call
``sphinx.html_themes`` entry_points feature.


Styling with CSS
----------------

The :confval:`!stylesheets` setting can be used to add custom CSS files to a theme.

.. caution::

The structure of the HTML elements and their classes are currently not a
well-defined public API. Please infer them from inspecting the built HTML
pages. While we cannot guarantee full stability, they tend to be fairly
stable.

Styling search result entries by category
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

.. versionadded:: 8.0

The search result items have classes indicating the context in which the
search term was found. You can use the CSS selectors:

- ``ul.search li.context-index``:
For results in an index, such as the glossary
- ``ul.search li.context-object``:
For results in source code, like Python function definitions
- ``ul.search li.context-title``:
For results found in section headings
- ``ul.search li.context-text``:
For results found anywhere else in the documentation text

As a base for inheritance by other themes, the ``basic`` theme is
intentionally minimal and does not define CSS rules using these.
Derived themes are encouraged to use these selectors as they see fit.
For example, the following stylesheet adds contextual icons to the
search result list:

.. code-block:: css
ul.search {
padding-left: 30px;
}
ul.search li {
padding: 5px 0 5px 10px;
list-style-type: "\25A1"; /* Unicode: White Square */
}
ul.search li.context-index {
list-style-type: "\1F4D1"; /* Unicode: Bookmark Tabs */
}
ul.search li.context-object {
list-style-type: "\1F4E6"; /* Unicode: Package */
}
ul.search li.context-title {
list-style-type: "\1F4C4"; /* Unicode: Page Facing Up */
}
ul.search li.context-text {
list-style-type: "\1F4C4"; /* Unicode: Page Facing Up */
}
Templating
----------

Expand Down
8 changes: 2 additions & 6 deletions sphinx/themes/basic/static/basic.css.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,11 @@ img {
/* -- search page ----------------------------------------------------------- */

ul.search {
margin: 10px 0 0 20px;
padding: 0;
margin-top: 10px;
}

ul.search li {
padding: 5px 0 5px 20px;
background-image: url(file.png);
background-repeat: no-repeat;
background-position: 0 7px;
padding: 5px 0;
}

ul.search li a {
Expand Down
25 changes: 21 additions & 4 deletions sphinx/themes/basic/static/searchtools.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ if (typeof Scorer === "undefined") {
// and returns the new score.
/*
score: result => {
const [docname, title, anchor, descr, score, filename] = result
const [docname, title, anchor, descr, score, filename, context] = result
return score
},
*/
Expand All @@ -47,6 +47,14 @@ if (typeof Scorer === "undefined") {
};
}

// Global search result kind enum, used by themes to style search results.
class SearchResultContext {
AA-Turner marked this conversation as resolved.
Show resolved Hide resolved
static get index() { return "index"; }
static get object() { return "object"; }
static get text() { return "text"; }
static get title() { return "title"; }
}

const _removeChildren = (element) => {
while (element && element.lastChild) element.removeChild(element.lastChild);
};
Expand All @@ -64,9 +72,13 @@ const _displayItem = (item, searchTerms, highlightTerms) => {
const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY;
const contentRoot = document.documentElement.dataset.content_root;

const [docName, title, anchor, descr, score, _filename] = item;
const [docName, title, anchor, descr, score, _filename, context] = item;

let listItem = document.createElement("li");
// Add a class representing the item's type:
// can be used by a theme's CSS selector for styling
// See SearchResultContext for the class names.
listItem.classList.add(`context-${context}`);
let requestUrl;
let linkUrl;
if (docBuilder === "dirhtml") {
Expand Down Expand Up @@ -138,7 +150,7 @@ const _displayNextItem = (
else _finishSearch(resultCount);
};
// Helper function used by query() to order search results.
// Each input is an array of [docname, title, anchor, descr, score, filename].
// Each input is an array of [docname, title, anchor, descr, score, filename, context].
// Order the results by score (in opposite order of appearance, since the
// `_displayNextItem` function uses pop() to retrieve items) and then alphabetically.
const _orderResultsByScoreThenName = (a, b) => {
Expand Down Expand Up @@ -248,6 +260,7 @@ const Search = {
searchSummary.classList.add("search-summary");
searchSummary.innerText = "";
const searchList = document.createElement("ul");
searchList.setAttribute("role", "list");
searchList.classList.add("search");

const out = document.getElementById("search-results");
Expand Down Expand Up @@ -318,7 +331,7 @@ const Search = {
const indexEntries = Search._index.indexentries;

// Collect multiple result groups to be sorted separately and then ordered.
// Each is an array of [docname, title, anchor, descr, score, filename].
// Each is an array of [docname, title, anchor, descr, score, filename, context].
const normalResults = [];
const nonMainIndexResults = [];

Expand All @@ -337,6 +350,7 @@ const Search = {
null,
score + boost,
filenames[file],
SearchResultContext.title,
]);
}
}
Expand All @@ -354,6 +368,7 @@ const Search = {
null,
score,
filenames[file],
SearchResultContext.index,
];
if (isMain) {
normalResults.push(result);
Expand Down Expand Up @@ -475,6 +490,7 @@ const Search = {
descr,
score,
filenames[match[0]],
SearchResultContext.object,
]);
};
Object.keys(objects).forEach((prefix) =>
Expand Down Expand Up @@ -585,6 +601,7 @@ const Search = {
null,
score,
filenames[file],
SearchResultContext.text,
]);
}
return results;
Expand Down
16 changes: 11 additions & 5 deletions tests/js/searchtools.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ describe('Basic html theme search', function() {
"",
null,
5,
"index.rst"
"index.rst",
"text"
]];
expect(Search.performTermsSearch(searchterms, excluded)).toEqual(hits);
});
Expand All @@ -53,7 +54,9 @@ describe('Basic html theme search', function() {
'',
null,
15,
'index.rst']];
'index.rst',
'text'
]];
expect(Search.performTermsSearch(searchterms, excluded)).toEqual(hits);
});

Expand All @@ -68,7 +71,8 @@ describe('Basic html theme search', function() {
"",
null,
7,
"index.rst"
"index.rst",
"text"
]];
expect(Search.performTermsSearch(searchterms, excluded)).toEqual(hits);
});
Expand All @@ -86,7 +90,8 @@ describe('Basic html theme search', function() {
"",
null,
2,
"index.rst"
"index.rst",
"text"
]];
expect(Search.performTermsSearch(searchterms, excluded, terms, titleterms)).toEqual(hits);
});
Expand All @@ -107,7 +112,8 @@ describe('Basic html theme search', function() {
'',
null,
16,
'index.rst'
'index.rst',
'title'
]
];
expect(Search._performSearch(...searchParameters)).toEqual(hits);
Expand Down
Loading