diff --git a/CHANGES.rst b/CHANGES.rst index 561517dc196..6141dc9af43 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -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 ---------- diff --git a/doc/_themes/sphinx13/static/sphinx13.css b/doc/_themes/sphinx13/static/sphinx13.css index e008e2fa36b..b0501d34394 100644 --- a/doc/_themes/sphinx13/static/sphinx13.css +++ b/doc/_themes/sphinx13/static/sphinx13.css @@ -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 */ +} diff --git a/doc/development/html_themes/index.rst b/doc/development/html_themes/index.rst index 35a3b363a36..18a345d3f71 100644 --- a/doc/development/html_themes/index.rst +++ b/doc/development/html_themes/index.rst @@ -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 ---------- diff --git a/sphinx/themes/basic/static/basic.css.jinja b/sphinx/themes/basic/static/basic.css.jinja index 297b9bfaeff..53fbadb0b6a 100644 --- a/sphinx/themes/basic/static/basic.css.jinja +++ b/sphinx/themes/basic/static/basic.css.jinja @@ -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 { diff --git a/sphinx/themes/basic/static/searchtools.js b/sphinx/themes/basic/static/searchtools.js index 3efa5165933..2b058e13bec 100644 --- a/sphinx/themes/basic/static/searchtools.js +++ b/sphinx/themes/basic/static/searchtools.js @@ -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 }, */ @@ -47,6 +47,14 @@ if (typeof Scorer === "undefined") { }; } +// Global search result kind enum, used by themes to style search results. +class SearchResultContext { + 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); }; @@ -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") { @@ -140,7 +152,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) => { @@ -250,6 +262,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"); @@ -320,7 +333,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 = []; @@ -339,6 +352,7 @@ const Search = { null, score + boost, filenames[file], + SearchResultContext.title, ]); } } @@ -356,6 +370,7 @@ const Search = { null, score, filenames[file], + SearchResultContext.index, ]; if (isMain) { normalResults.push(result); @@ -477,6 +492,7 @@ const Search = { descr, score, filenames[match[0]], + SearchResultContext.object, ]); }; Object.keys(objects).forEach((prefix) => @@ -587,6 +603,7 @@ const Search = { null, score, filenames[file], + SearchResultContext.text, ]); } return results; diff --git a/tests/js/searchtools.spec.js b/tests/js/searchtools.spec.js index 1ff789a4a56..cfe5fdcf7ed 100644 --- a/tests/js/searchtools.spec.js +++ b/tests/js/searchtools.spec.js @@ -38,7 +38,8 @@ describe('Basic html theme search', function() { "", null, 5, - "index.rst" + "index.rst", + "text" ]]; expect(Search.performTermsSearch(searchterms, excluded)).toEqual(hits); }); @@ -53,7 +54,9 @@ describe('Basic html theme search', function() { '', null, 15, - 'index.rst']]; + 'index.rst', + 'text' + ]]; expect(Search.performTermsSearch(searchterms, excluded)).toEqual(hits); }); @@ -68,7 +71,8 @@ describe('Basic html theme search', function() { "", null, 7, - "index.rst" + "index.rst", + "text" ]]; expect(Search.performTermsSearch(searchterms, excluded)).toEqual(hits); }); @@ -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); }); @@ -107,7 +112,8 @@ describe('Basic html theme search', function() { '', null, 16, - 'index.rst' + 'index.rst', + 'title' ] ]; expect(Search._performSearch(...searchParameters)).toEqual(hits);