Skip to content

feat: add readthedocs javascript search#158

Open
ReenigneArcher wants to merge 8 commits into
jothepro:mainfrom
ReenigneArcher:feat-add-readthedocs-javascript-search
Open

feat: add readthedocs javascript search#158
ReenigneArcher wants to merge 8 commits into
jothepro:mainfrom
ReenigneArcher:feat-add-readthedocs-javascript-search

Conversation

@ReenigneArcher

@ReenigneArcher ReenigneArcher commented Aug 7, 2024

Copy link
Copy Markdown

This PR adds a custom readthedocs search extension using javascript. I found the default doxygen search is quite terrible, and doesn't seem to actually search any markdown files (or barely searches them)... which is not great when you have user documentation.

I have added this for my own projects (here: LizardByte/doxyconfig#4), and figured I could share it back here for others to benefit from. A live preview is available here: https://docs.lizardbyte.dev/projects/doxyconfig/latest/search.html?query=doxygen

This is what it looks like.
image

image

Old version

image

image

The styling is somewhat based on Furo, this is how that looks in one of my projects.
image

TODO:

  • improve the appearance/layout of the anchor urls
  • possibly add live searching (This is above my capability for now, maybe it could be part of a later PR).

@ReenigneArcher ReenigneArcher force-pushed the feat-add-readthedocs-javascript-search branch from 6989243 to b2a87fc Compare August 7, 2024 18:46
@ReenigneArcher ReenigneArcher marked this pull request as ready for review August 7, 2024 18:49
@ReenigneArcher

This comment was marked as resolved.

Comment thread doxygen-awesome-readthedocs-search.js Outdated

@jothepro jothepro left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! The readthedocs search seems to work a lot better indeed! I think adding this as an extension to the theme would be really valuable!

When starting the search with the readthedocs addon widget at the bottom right, a really nice popover with live search is opened. IMO that's a really nice user experience! Do you think it would be possible to use the searchbar in the upper right just as a link that opens this popover?

Comment thread package.json Outdated
@ReenigneArcher

Copy link
Copy Markdown
Author

When starting the search with the readthedocs addon widget at the bottom right, a really nice popover with live search is opened. IMO that's a really nice user experience! Do you think it would be possible to use the searchbar in the upper right just as a link that opens this popover?

I'm not sure I fully understand the ask, but if you're just asking if the live search will work (search as you type)... it's possible, I just don't know how to implement it.

Introduce a live search dropdown and various robustness improvements for ReadTheDocs search integration. Changes:
- Add CSS for live search dropdown (#RTDLiveResults) styling and item/snippet formatting.
- Use globalThis.location.hostname and expose searchFor on globalThis to avoid scope issues.
- Wrap global SearchBox to preserve behavior while preventing CloseResultsWindow from blurring an actively focused search field.
- Add MutationObservers to re-attach listeners and re-focus the search input when the DOM is mutated (fixes mobile/OSK behavior where input is recreated).
- Implement debounced live search (_attachLiveSearch, _runLiveSearch), AJAX-based live result rendering (_showLiveResults), positioning, keyboard navigation, and hide logic.
- Refactor paginated search fetch into fetchResults with a ctx object and appendResultItem helper for consistent DOM updates.
- Make getReadTheDocsDefaultVersion return a Promise and resolve to 'latest' on error (handles PR numeric versions).

These changes improve UX for live searching, keyboard support, and resilience when menu code recreates the search field.
Migrate away from jQuery for DOM access and AJAX: use document.getElementById / querySelector and textContent/appendChild instead of jQuery selectors and methods; replace $.ajax calls with fetch + response.ok checks and promise handlers; replace $.each with Array.forEach; update search field assignment to use .value. Remove jquery from package.json devDependencies. This modernizes the code and removes an unnecessary runtime dependency.
@ReenigneArcher

Copy link
Copy Markdown
Author

Decided to revisit this PR with assistance from Claude.

  • Fixed issue where on screen keyboard would disappear when searching on a mobile device
  • Add live search
  • Fixed several sonar issues
  • Replaced jquery/ajax with native fetch

@ReenigneArcher ReenigneArcher requested a review from jothepro March 21, 2026 17:26
@ReenigneArcher

Copy link
Copy Markdown
Author

@jothepro anything else needed to get this going? It's working pretty well for me. You can see an example of it with my docs for Sunshine at https://docs.lizardbyte.dev/projects/sunshine/latest/

An example to search for could be "vulkan" to show the live and standard search results.

Repository owner deleted a comment from dianacarolinasanchez30-netizen May 31, 2026

@jothepro jothepro left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks very promising already, thanks for the good work!

Comment thread package.json
Comment thread doxygen-awesome-readthedocs-search.css
Comment thread doxygen-awesome-readthedocs-search.css
Comment on lines +265 to +268
dropdown.style.top = `${rect.bottom + scrollY}px`;
dropdown.style.left = '';
dropdown.style.right = `${viewportWidth - rect.right}px`;
dropdown.style.minWidth = `${Math.max(rect.width, 260)}px`;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume that this will not work with the sidebar only variant of the theme, because the element is always aligned to the right edge of the search box. The sidebar theme would require a left-align though, otherwise the element will not be fully visible.

I've crafted some screenshots on how this would likely look like with the current alignment, and how the layout should be IMO:

Right Aligned

Image

Left Aligned

Image

I'm guessing an easy fix would be to add an init parameter that allows to configure the alignment?

DoxygenAwesomeReadtheDocsSearch.init('leftAlign')

Pls correct me if my assumptions are not correct.

Comment thread doxygen-awesome-readthedocs-search.css
Comment thread doxygen-awesome-readthedocs-search.css
const rect = anchor.getBoundingClientRect();
const scrollY = window.scrollY;
const viewportWidth = document.documentElement.clientWidth;
dropdown.style.top = `${rect.bottom + scrollY}px`;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very minor bug that I'd consider tolerable because I'd consider the input a rase edge case:

When resizing the viewport, the position of the dropdown is not recalculated. This occurs when switching from desktop to mobile layout and when the navigation-items move under the logo:

Bildschirmaufnahme.2026-05-31.um.15.25.00.mov

Comment thread doxygen-awesome-readthedocs-search.js Outdated
Comment on lines +158 to +173
field.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
DoxygenAwesomeReadtheDocsSearch._hideLiveResults();
} else if (e.key === 'ArrowDown') {
e.preventDefault();
DoxygenAwesomeReadtheDocsSearch._moveLiveResultFocus(1);
} else if (e.key === 'ArrowUp') {
e.preventDefault();
DoxygenAwesomeReadtheDocsSearch._moveLiveResultFocus(-1);
} else if (e.key === 'Enter') {
const focused = document.querySelector('#RTDLiveResults .rtd-live-item:focus');
if (focused) {
e.preventDefault();
focused.click();
}
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why but the keyboard navigation is broken for me:

It is possible to focus the first item in the list pressing on the keyboard. But the focus is stuck then and cannot be moved to other items using either or . It is also not possible to exit out of the search by pressing Esc.

I've tried to visualize the problem in this video (Keyboard inputs are displayed in the lower left)

Bildschirmaufnahme.2026-05-31.um.14.34.30.mov

ReenigneArcher and others added 3 commits May 31, 2026 10:40
Co-Authored-By: jothepro <21294002+jothepro@users.noreply.github.com>
Support left-aligned live search variant and improve live-results behavior. Docs: add example showing initialization with leftAlign for the sidebar-only theme. JS: add alignment state, allow init('leftAlign'), prevent duplicate live-search attachment, move keydown handling to a shared _handleLiveSearchKeydown, add dropdown keydown listener, restore focus on Escape, update positioning logic for left/right alignment and mobile, use requestAnimationFrame to schedule position updates, and listen for window resize to recompute placement. Overall fixes keyboard, focus and positioning edge cases and reduces redundant event attachment.
@ReenigneArcher

ReenigneArcher commented May 31, 2026

Copy link
Copy Markdown
Author

Thanks for the review! I applied your suggestions to the styling, and pushed some changes that I think will fix the 3 functional issues you mentioned. I have not tested the changes though... would it be possible for you to setup this project in readthedocs and enforce building pull requests? Then it will be super easy to view and test pull request modifications.

I can add all the required readthedocs configuration in this PR, it just needs to be setup there first and receive webhooks from GitHub.

Edit: I added the rtd config already. If you setup this project on readthedocs, I will force push to trigger a build there. And one more note, when setting up the project it will ask for the location of the .readthedocs.yaml, you can just say that it already exists and it will still work for this PR. Once this one is merged it will run for all PRs.

@ReenigneArcher ReenigneArcher requested a review from jothepro June 23, 2026 17:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants