这是indexloc提供的服务,不要输入任何密码
Skip to content

Conversation

@inetol
Copy link
Member

@inetol inetol commented Nov 1, 2025

This PR defines a new interface for client side "plugins" that coexist with server side plugin system. Each plugin (e.g., InfiniteScroll) extends the base Plugin. Client side plugins are independent and lazy‑loaded via router.ts when their load() 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  -->  Plugin 
Loading

Since these are client side plugins, we can only invoke them once DOM is fully loaded. E.g. Calculator will not render a new answer block until fully loaded and executed.

For some plugins, we might want to handle its availability in settings.yml and toggle in UI, like we do for server side plugins. In that case, we extend py Plugin instancing only the information and then checking client side if settings.plugins array has the plugin id.

Due to those changes, Vite bundling also needed some rework to properly lazy-load.


I expected to refactor search.ts as 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 answers div from scratch on client side.

Maybe we can add a condition in the answers.html template to add the style display:none if no answer blocks are appended server side?

@return42

This comment was marked as outdated.

@inetol

This comment was marked as outdated.

@inetol inetol force-pushed the mod-client-plugins branch 5 times, most recently from e1f4cac to b3a35a5 Compare November 2, 2025 19:01
@inetol

This comment was marked as outdated.

@inetol inetol force-pushed the mod-client-plugins branch from b3a35a5 to 977c105 Compare November 2, 2025 21:13
@return42

This comment was marked as outdated.

@inetol inetol force-pushed the mod-client-plugins branch from 977c105 to 83507ca Compare November 3, 2025 09:21
@inetol
Copy link
Member Author

inetol commented Nov 3, 2025

Thanks for the guide, a lot cleaner than my hackish implementation. I thought py Plugin did more stuff behind the scenes, I should have checked it out earlier.

To summarize: we have PluginStorage.client_plugins from where we get a list of PluginCfg.

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 metadata info:

https://github.com/inetol/searxng/blob/83507ca671ce3c204ae105b222c77bb3fadc6d49/searx/plugins/calculator.py

For the client, its sufficient to know if the plugin id is inside the array:

https://github.com/inetol/searxng/blob/83507ca671ce3c204ae105b222c77bb3fadc6d49/client/simple/src/js/router.ts#L10-L23

...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.

I could implement that for you, but I currently have other, more urgent tasks (Google engine, etc.) that I want to work on first. Either you wait until I implement the above, or you try it yourself .. if you think it's taking too long with me :-)

Got it :)

@inetol inetol force-pushed the mod-client-plugins branch 3 times, most recently from 99c6366 to 1ad832b Compare November 5, 2025 20:56
@inetol inetol changed the title [rfc] client/simple: client plugins [mod] client/simple: client plugins Nov 5, 2025
@inetol inetol force-pushed the mod-client-plugins branch 2 times, most recently from ac565c3 to f140c92 Compare November 11, 2025 10:43
@inetol inetol force-pushed the mod-client-plugins branch from f140c92 to c2377e4 Compare November 11, 2025 10:58
@inetol inetol marked this pull request as ready for review November 11, 2025 11:00
@inetol inetol requested a review from Copilot November 11, 2025 11:00
Copy link

Copilot AI left a 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 Plugin class for client-side plugins with lifecycle methods (run() and post())
  • 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):
Copy link

Copilot AI Nov 11, 2025

Choose a reason for hiding this comment

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

The class 'SXNGPlugin' does not override 'eq', but adds the new attribute info.

Copilot uses AI. Check for mistakes.
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