Files
searxng/client/simple/src/js/plugin/Calculator.ts
Ivan Gabaldon fb089ae297 [mod] client/simple: client plugins (#5406)
* [mod] client/simple: client plugins

Defines a new interface for client side *"plugins"* that coexist with server
side plugin system. Each plugin (e.g., `InfiniteScroll`) extends the base
`ts 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.

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`](1ad832b1dc/client/simple/src/js/toolkit.ts (L134))
array has the plugin id.

* [mod] client/simple: rebuild static
2025-12-02 10:18:00 +00:00

94 lines
2.1 KiB
TypeScript

// SPDX-License-Identifier: AGPL-3.0-or-later
import {
absDependencies,
addDependencies,
create,
divideDependencies,
eDependencies,
evaluateDependencies,
expDependencies,
factorialDependencies,
gcdDependencies,
lcmDependencies,
log1pDependencies,
log2Dependencies,
log10Dependencies,
logDependencies,
modDependencies,
multiplyDependencies,
nthRootDependencies,
piDependencies,
powDependencies,
roundDependencies,
signDependencies,
sqrtDependencies,
subtractDependencies
} from "mathjs/number";
import { Plugin } from "../Plugin.ts";
import { appendAnswerElement } from "../util/appendAnswerElement.ts";
import { getElement } from "../util/getElement.ts";
/**
* Parses and solves mathematical expressions. Can do basic arithmetic and
* evaluate some functions.
*
* @example
* "(3 + 5) / 2" = "4"
* "e ^ 2 + pi" = "10.530648752520442"
* "gcd(48, 18) + lcm(4, 5)" = "26"
*
* @remarks
* Depends on `mathjs` library.
*/
export default class Calculator extends Plugin {
public constructor() {
super("calculator");
}
/**
* @remarks
* Compare bundle size after adding or removing features.
*/
private static readonly math = create({
...absDependencies,
...addDependencies,
...divideDependencies,
...eDependencies,
...evaluateDependencies,
...expDependencies,
...factorialDependencies,
...gcdDependencies,
...lcmDependencies,
...log10Dependencies,
...log1pDependencies,
...log2Dependencies,
...logDependencies,
...modDependencies,
...multiplyDependencies,
...nthRootDependencies,
...piDependencies,
...powDependencies,
...roundDependencies,
...signDependencies,
...sqrtDependencies,
...subtractDependencies
});
protected async run(): Promise<string | undefined> {
const searchInput = getElement<HTMLInputElement>("q");
const node = Calculator.math.parse(searchInput.value);
try {
return `${node.toString()} = ${node.evaluate()}`;
} catch {
// not a compatible math expression
return;
}
}
protected async post(result: string): Promise<void> {
appendAnswerElement(result);
}
}