-
Notifications
You must be signed in to change notification settings - Fork 2.3k
[mod] client/simple: client plugins #5406
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
base: master
Are you sure you want to change the base?
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
e1f4cac to
b3a35a5
Compare
This comment was marked as outdated.
This comment was marked as outdated.
b3a35a5 to
977c105
Compare
This comment was marked as outdated.
This comment was marked as outdated.
977c105 to
83507ca
Compare
|
Thanks for the guide, a lot cleaner than my hackish implementation. I thought
We really need to differentiate between client or server plugin that much? Both types are plugins, but client ones doesn't implement any server side logic, only instances For the client, its sufficient to know if the plugin id is inside the array: ...returned by the list of enabled plugins: https://github.com/inetol/searxng/blob/83507ca671ce3c204ae105b222c77bb3fadc6d49/searx/webapp.py#L371 I can implement a new storage method if you're not convinced, but I think it's not necessary.
Got it :) |
99c6366 to
1ad832b
Compare
ac565c3 to
f140c92
Compare
f140c92 to
c2377e4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces a client-side plugin architecture that complements the existing server-side plugin system. The changes refactor the calculator plugin and infinite scroll feature to be client-side plugins that are lazy-loaded based on configuration and routing conditions. The bundling system has been reworked using Vite to support this new architecture with proper code splitting.
Key changes:
- Introduced a base
Pluginclass for client-side plugins with lifecycle methods (run()andpost()) - Moved calculator functionality from server-side to client-side implementation
- Converted infinite scroll from a user preference to a plugin-based feature
- Refactored build output structure with renamed files (sxng-* prefix) and chunk-based loading
Reviewed Changes
Copilot reviewed 47 out of 91 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/unit/test_plugin_calculator.py | Removed server-side calculator tests (functionality moved to client) |
| tests/unit/settings/user_settings.yml | Added infinite_scroll plugin configuration |
| searx/webapp.py | Changed to send enabled plugins array instead of individual preferences |
| searx/templates/simple/rss.xsl | Updated CSS filename reference |
| searx/templates/simple/preferences/infinite_scroll.html | Removed infinite scroll preference UI (now plugin-controlled) |
| searx/templates/simple/preferences.html | Removed infinite scroll preference inclusion |
| searx/templates/simple/base.html | Updated JS and CSS filename references |
| searx/static/themes/simple/*.css | Renamed CSS bundles with sxng- prefix |
| searx/static/themes/simple/sxng-core.min.js* | New core bundle with plugin loader |
| searx/static/themes/simple/manifest.json | Updated build manifest with new chunk structure |
| searx/static/themes/simple/js/* | Removed old JS bundles (replaced by chunk-based structure) |
| searx/static/themes/simple/chunk/* | New chunk-based JS modules for lazy loading |
Files not reviewed (1)
- client/simple/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
|
|
||
| @t.final | ||
| class SXNGPlugin(Plugin): |
Copilot
AI
Nov 11, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR defines a new interface for client side "plugins" that coexist with server side plugin system. Each plugin (e.g.,
InfiniteScroll) extends the basePlugin. Client side plugins are independent and lazy‑loaded viarouter.tswhen theirload()conditions are met. On each navigation request, all applicable plugins are instanced.classDiagram direction BT class Calculator { constructor() MathJsInstance math run() Promise~string | undefined~ post(result: string) Promise~void~ } class InfiniteScroll { constructor() run() Promise~void~ post() Promise~void~ } class MapView { constructor(map: HTMLElement) HTMLElement map run() Promise~void~ post() Promise~void~ } class Plugin { constructor(id: string) string id invoke() Promise~void~ run() Promise~unknown~ post(result: NonNullable~Awaited~ReturnType~this["run"]~~~) Promise~void~ } Calculator --> Plugin InfiniteScroll --> Plugin MapView --> PluginSince these are client side plugins, we can only invoke them once DOM is fully loaded. E.g.
Calculatorwill not render a newanswerblock until fully loaded and executed.For some plugins, we might want to handle its availability in
settings.ymland toggle in UI, like we do for server side plugins. In that case, we extendpy Plugininstancing only the information and then checking client side ifsettings.pluginsarray has the plugin id.Due to those changes, Vite bundling also needed some rework to properly lazy-load.
I expected to refactor
search.tsas a plugin too, but the PR is already somewhat large, so I left it halfway done. No logic changes were made.I am not entirely convinced about having to recreate the
answersdiv from scratch on client side.Maybe we can add a condition in the answers.html template to add the style
display:noneif noanswerblocks are appended server side?