exprify 1.0.4 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/HISTORY.md +49 -0
- package/README.md +109 -182
- package/SECURITY.md +18 -0
- package/bin/cli.mjs +234 -0
- package/dist/exprify.cjs.cjs +3558 -1220
- package/dist/exprify.cjs.cjs.map +1 -1
- package/dist/exprify.esm.js +3558 -1220
- package/dist/exprify.esm.js.map +1 -1
- package/dist/exprify.js +3560 -1222
- package/dist/exprify.js.map +1 -1
- package/dist/exprify.min.js +2 -2
- package/dist/exprify.min.js.map +1 -1
- package/package.json +44 -17
- package/src/core/context.js +35 -27
- package/src/core/exprify.js +880 -0
- package/src/function/executor.js +29 -20
- package/src/function/internal.js +1150 -153
- package/src/function/registry.js +23 -16
- package/src/index.js +1 -1
- package/src/math/bignumber.js +31 -0
- package/src/math/fraction.js +112 -0
- package/src/math/operations.js +38 -24
- package/src/parser/astBuild.js +276 -214
- package/src/parser/evaluator.js +431 -171
- package/src/parser/tokenizer.js +179 -146
- package/src/utils/decimal.js +264 -0
- package/src/utils/globalUnits.js +43 -35
- package/src/utils/matrix.js +14 -14
- package/src/utils/store.js +69 -47
- package/src/variables/store.js +18 -15
- package/src/core/Exprify.js +0 -369
package/HISTORY.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on Keep a Changelog, and this project follows semantic versioning.
|
|
6
|
+
|
|
7
|
+
## [1.0.5] - 2026-06-12
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- ESLint (v10 flat config) with strict rules, Prettier formatting, and TypeScript JSDoc type checking
|
|
12
|
+
- Husky pre-commit hook with lint-staged for automatic linting and formatting on commit
|
|
13
|
+
- Dependabot config for weekly automated dependency pull requests
|
|
14
|
+
- CodeQL security analysis workflow on push/PR/schedule
|
|
15
|
+
- Bundle size monitoring via size-limit (min.js: 30 KB, esm.js: 60 KB)
|
|
16
|
+
- Jest coverage reporting (`npm run test:coverage`) with CI artifact upload
|
|
17
|
+
- Node.js 24 to CI test matrix (previously 20 and 22 only)
|
|
18
|
+
- `.editorconfig` for cross-editor consistency
|
|
19
|
+
- `// @ts-check` annotations to all 14 source files
|
|
20
|
+
- `engines` field requiring Node >=18
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- Upgraded Rollup from v2 to v4 with updated plugin versions
|
|
25
|
+
- Replaced rimraf with built-in `fs.rmSync` for the clean script
|
|
26
|
+
- Replaced nodemon with Node.js built-in `--watch` flag for the dev script
|
|
27
|
+
- CI workflow now runs lint, typecheck, size check, and coverage in addition to tests
|
|
28
|
+
- Switched CI workflows to Node 24 for publish and audit jobs
|
|
29
|
+
- Added `--no-warnings` flag to test scripts to suppress ExperimentalWarning
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- All ESLint errors (no-unused-vars, no-undef, eqeqeq, prefer-const, camelcase, etc.)
|
|
34
|
+
- All TypeScript type errors (err unknown type, null checks, variable store reference)
|
|
35
|
+
- lint-staged Windows ENOENT error by switching from package.json config to `lint-staged.config.js` with direct `node` invocation
|
|
36
|
+
|
|
37
|
+
### Removed
|
|
38
|
+
|
|
39
|
+
- Unused Babel dependencies (@babel/cli, @babel/core, @babel/preset-env)
|
|
40
|
+
- Unused rollup-plugin-strip-banner, glob, and rimraf dev dependencies
|
|
41
|
+
- `overrides` section (test-exclude, glob pins) — no longer needed with Jest 30
|
|
42
|
+
- `nodemon` devDependency (replaced by `node --watch`)
|
|
43
|
+
|
|
44
|
+
## [1.0.1] - 2026-04-05
|
|
45
|
+
|
|
46
|
+
### Fixed
|
|
47
|
+
|
|
48
|
+
- Corrected the import path in `src/index.js` to match the actual filename casing of `src/core/Exprify.js`.
|
|
49
|
+
- Resolved a cross-platform build issue where Rollup failed on Linux-based CI environments because of case-sensitive path resolution.
|
package/README.md
CHANGED
|
@@ -1,8 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
[](https://github.com/code-hemu/Exprify)
|
|
2
2
|
|
|
3
|
-
[](https://github.com/code-hemu/Exprify)
|
|
4
3
|
|
|
5
|
-
Exprify is a JavaScript expression parser and evaluator for math
|
|
4
|
+
**Exprify** (Math **Expr**ession + Simp**lify**) is a fast, lightweight JavaScript expression parser and evaluator. It is designed for math applications, scientific computing, data visualization tools, calculators, and other complex workflows that run in the browser and in Node.js. It supports basic arithmetic, variables, user-defined functions, and built-in operators for comparison, logic, and string manipulation.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/exprify)
|
|
8
|
+
[](https://www.npmjs.com/package/exprify)
|
|
9
|
+
[](https://github.com/code-hemu/exprify/blob/master/LICENSE)
|
|
10
|
+
[](https://www.jsdelivr.com/package/npm/exprify)
|
|
11
|
+
[](https://unpkg.com/exprify)
|
|
12
|
+
[](https://github.com/code-hemu/exprify/issues)
|
|
13
|
+
[](https://github.com/code-hemu/exprify/graphs/contributors)
|
|
14
|
+
[](https://github.com/sponsors/code-hemu)
|
|
15
|
+
[](https://github.com/code-hemu/exprify)
|
|
16
|
+
|
|
17
|
+
## Features
|
|
18
|
+
|
|
19
|
+
- **Arithmetic & Variables** - `expr.evaluate("5 + 7 * 2")` · [docs](docs/datatypes/numbers.md)
|
|
20
|
+
- **Unit conversion** - `expr.evaluate("2 inch to cm")` · [docs](docs/datatypes/units.md)
|
|
21
|
+
- **Matrix operations** - `expr.evaluate("det([-1,2;3,1])")` · [docs](docs/datatypes/matrices.md)
|
|
22
|
+
- **Complex numbers** - `expr.evaluate("9/3 + 2i")` · [docs](docs/datatypes/complex_numbers.md)
|
|
23
|
+
- **Symbolic math** - `expr.evaluate('expand("(x+1)^2")')` · [docs](docs/expressions/algebra.md)
|
|
24
|
+
- **Arbitrary precision** - `expr.evaluate('bignumber("0.1") + bignumber("0.2")')` · [docs](docs/datatypes/bignumbers.md)
|
|
25
|
+
- **Exact fractions** - `expr.evaluate("fraction(1,3) + fraction(1,6)")` · [docs](docs/datatypes/fractions.md)
|
|
26
|
+
- **Calculus & statistics** - `expr.evaluate('integral("x^2", 0, 1)')` · [docs](docs/reference/functions.md)
|
|
27
|
+
- **Lambda expressions** - `expr.evaluate('map([1,2,3], x -> x^2)')` · [docs](docs/expressions/customization.md)
|
|
28
|
+
- **Expression chaining** - `c.evaluate("sqrt(x)").evaluate("ans * 2").done()` · [docs](docs/core/chaining.md)
|
|
29
|
+
- **State serialization** - `expr.exportState()` / `expr.importState(state)` · [docs](docs/core/serialization.md)
|
|
30
|
+
- **Degree-mode trig** - `expr.evaluate("sind(90)")` · [docs](docs/reference/functions.md)
|
|
6
31
|
|
|
7
32
|
## Installation
|
|
8
33
|
|
|
@@ -12,270 +37,178 @@ npm install exprify
|
|
|
12
37
|
|
|
13
38
|
## Quick Start
|
|
14
39
|
|
|
15
|
-
**ESM** (Node.js
|
|
40
|
+
**ESM** (Node.js / bundlers):
|
|
16
41
|
|
|
17
42
|
```js
|
|
18
43
|
import Exprify from "exprify";
|
|
19
44
|
|
|
20
45
|
const expr = new Exprify();
|
|
21
46
|
|
|
22
|
-
|
|
23
|
-
// 19
|
|
47
|
+
expr.evaluate("5 + 7 * 2"); // 19
|
|
24
48
|
|
|
25
49
|
expr.setVariable("x", 10);
|
|
26
|
-
|
|
27
|
-
// 15
|
|
50
|
+
expr.evaluate("x + 5"); // 15
|
|
28
51
|
```
|
|
29
52
|
|
|
30
|
-
**CommonJS
|
|
53
|
+
**CommonJS:**
|
|
31
54
|
|
|
32
55
|
```js
|
|
33
56
|
const Exprify = require("exprify");
|
|
34
57
|
|
|
35
58
|
const expr = new Exprify();
|
|
36
|
-
|
|
37
|
-
// 19
|
|
59
|
+
expr.evaluate("5 + 7 * 2"); // 19
|
|
38
60
|
```
|
|
39
61
|
|
|
40
|
-
|
|
62
|
+
**Browser (CDN):**
|
|
41
63
|
|
|
42
64
|
```html
|
|
43
65
|
<script src="https://unpkg.com/exprify"></script>
|
|
44
66
|
<script>
|
|
45
67
|
const expr = new Exprify();
|
|
46
|
-
|
|
68
|
+
expr.evaluate("(10 + 5) * 2"); // 30
|
|
47
69
|
</script>
|
|
48
70
|
```
|
|
49
71
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
## Module Formats
|
|
53
|
-
|
|
54
|
-
The package ships a separate build for each consumer, and `package.json`'s `exports` field routes each import style to the right file:
|
|
55
|
-
|
|
56
|
-
| Consumer | Resolved file | Notes |
|
|
57
|
-
| --- | --- | --- |
|
|
58
|
-
| `import Exprify from "exprify"` (ESM) | `dist/exprify.esm.js` | Default export is the `Exprify` class. |
|
|
59
|
-
| `const Exprify = require("exprify")` (CJS) | `dist/exprify.cjs.cjs` | `module.exports` is the `Exprify` class. |
|
|
60
|
-
| `<script src="https://unpkg.com/exprify">` | `dist/exprify.min.js` | UMD build; exposes `Exprify` as a global. |
|
|
61
|
-
| `import "exprify/dist/exprify.js"` (UMD) | `dist/exprify.js` | Unminified UMD for bundlers that prefer it. |
|
|
62
|
-
|
|
63
|
-
The `.cjs` extension on the CommonJS bundle keeps it loadable as CJS even though the package is `"type": "module"`, so `require()` and `import` both work without configuration.
|
|
64
|
-
|
|
65
|
-
## API
|
|
72
|
+
## API Reference
|
|
66
73
|
|
|
67
74
|
### `new Exprify()`
|
|
68
75
|
|
|
69
|
-
Creates a new evaluator instance with isolated state
|
|
76
|
+
Creates a new evaluator instance with fully isolated state. Each instance maintains its own independent registry of variables, custom functions, unit definitions, and a compiled-expression cache - so multiple instances never interfere with each other.
|
|
70
77
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
- compiled-expression cache
|
|
78
|
+
```js
|
|
79
|
+
const expr = new Exprify();
|
|
80
|
+
```
|
|
75
81
|
|
|
76
|
-
### `expr.evaluate(expression)`
|
|
82
|
+
### `expr.evaluate(expression, scope?)`
|
|
77
83
|
|
|
78
|
-
Parses and evaluates an expression string.
|
|
84
|
+
Parses and evaluates an expression string, returning the computed result. An optional `scope` object lets you pass temporary variable values that apply only to that single call - they do not modify the instance's stored state.
|
|
79
85
|
|
|
80
86
|
```js
|
|
81
|
-
expr.evaluate("10 + 5 * 2");
|
|
82
|
-
|
|
87
|
+
expr.evaluate("10 + 5 * 2"); // 20
|
|
88
|
+
|
|
89
|
+
expr.setVariable("x", 100);
|
|
90
|
+
expr.evaluate("x + 1", { x: 5 }); // 6 (x = 100 is unchanged)
|
|
83
91
|
```
|
|
84
92
|
|
|
85
93
|
### `expr.parse(expression)`
|
|
86
94
|
|
|
87
|
-
Returns `{ tokens, ast }
|
|
95
|
+
Parses an expression without evaluating it. Returns a `{ tokens, ast }` object containing the raw token list and the abstract syntax tree - useful for debugging, introspection, or building custom tooling on top of the parser.
|
|
88
96
|
|
|
89
97
|
```js
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
console.log(parsed.ast);
|
|
98
|
+
const { tokens, ast } = expr.parse("2 inch to cm");
|
|
99
|
+
// tokens: [...], ast: { type: "UnitConversion", ... }
|
|
93
100
|
```
|
|
94
101
|
|
|
95
102
|
### `expr.compile(expression)`
|
|
96
103
|
|
|
97
|
-
Compiles an expression once and returns a reusable function.
|
|
104
|
+
Compiles an expression once and returns a reusable callable function. The compiled form skips parsing on every subsequent invocation, making this the right choice for hot paths or any expression evaluated repeatedly with different inputs.
|
|
98
105
|
|
|
99
106
|
```js
|
|
100
107
|
const area = expr.compile("width * height");
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
// 24
|
|
108
|
+
area({ width: 6, height: 4 }); // 24
|
|
109
|
+
area({ width: 3, height: 9 }); // 27
|
|
104
110
|
```
|
|
105
111
|
|
|
106
112
|
### `expr.setVariable(name, value)` / `expr.getVariable(name)`
|
|
107
113
|
|
|
108
|
-
Stores
|
|
114
|
+
Stores a named value that persists across all future evaluations on this instance. `getVariable` retrieves a previously stored value by name.
|
|
109
115
|
|
|
110
116
|
```js
|
|
111
117
|
expr.setVariable("x", 10);
|
|
112
118
|
expr.setVariable("y", 5);
|
|
119
|
+
expr.evaluate("x + y * 2"); // 20
|
|
113
120
|
|
|
114
|
-
|
|
115
|
-
// 20
|
|
121
|
+
expr.getVariable("x"); // 10
|
|
116
122
|
```
|
|
117
123
|
|
|
118
124
|
### `expr.addFunction(name, fn)`
|
|
119
125
|
|
|
120
|
-
Registers a
|
|
126
|
+
Registers a plain JavaScript function under a given name, making it available to call inside any expression evaluated on this instance. The function receives its arguments as individual parameters, exactly as written in the expression.
|
|
121
127
|
|
|
122
128
|
```js
|
|
123
129
|
expr.addFunction("double", (n) => n * 2);
|
|
130
|
+
expr.evaluate("double(5) + 3"); // 13
|
|
124
131
|
|
|
125
|
-
|
|
126
|
-
//
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### Inline Function Definitions
|
|
130
|
-
|
|
131
|
-
You can define functions inside expressions.
|
|
132
|
-
|
|
133
|
-
```js
|
|
134
|
-
expr.evaluate("hyp(a, b) = sqrt(a ^ 2 + b ^ 2)");
|
|
135
|
-
|
|
136
|
-
console.log(expr.evaluate("hyp(3, 4)"));
|
|
137
|
-
// 5
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
## Features
|
|
141
|
-
|
|
142
|
-
### Arithmetic
|
|
143
|
-
|
|
144
|
-
```js
|
|
145
|
-
expr.evaluate("2 + 3 * 4");
|
|
146
|
-
// 14
|
|
147
|
-
|
|
148
|
-
expr.evaluate("(2 + 3) * 4");
|
|
149
|
-
// 20
|
|
150
|
-
|
|
151
|
-
expr.evaluate("11n ^ 2n");
|
|
152
|
-
// 121n
|
|
132
|
+
expr.addFunction("clamp", (val, lo, hi) => Math.min(Math.max(val, lo), hi));
|
|
133
|
+
expr.evaluate("clamp(150, 0, 100)"); // 100
|
|
153
134
|
```
|
|
154
135
|
|
|
155
|
-
###
|
|
156
|
-
|
|
157
|
-
```js
|
|
158
|
-
expr.evaluate('"Hello " + "World"');
|
|
159
|
-
// "Hello World"
|
|
160
|
-
|
|
161
|
-
expr.evaluate("true && false");
|
|
162
|
-
// false
|
|
163
|
-
|
|
164
|
-
expr.evaluate("9 / 3 + 2i");
|
|
165
|
-
// "3 + 2i"
|
|
166
|
-
```
|
|
136
|
+
### `expr.chain()`
|
|
167
137
|
|
|
168
|
-
|
|
138
|
+
Returns a fluent `Chain` object for building multi-step calculations. Each call to `.evaluate()` on the chain stores its result in the special variable `ans`, which the next expression can reference directly. Call `.done()` at the end to extract the final value.
|
|
169
139
|
|
|
170
140
|
```js
|
|
171
|
-
expr.
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
//
|
|
176
|
-
|
|
177
|
-
expr.evaluate("5cm + 0.2 m in inch");
|
|
178
|
-
// "9.84251968503937 inch"
|
|
179
|
-
|
|
180
|
-
expr.evaluate("a = 5.08 cm + 2 inch");
|
|
181
|
-
expr.evaluate("a to inch");
|
|
182
|
-
// "4 inch"
|
|
141
|
+
const c = expr.chain();
|
|
142
|
+
c.setVariable("x", 25);
|
|
143
|
+
c.evaluate("sqrt(x) + 3"); // computes 8, stored as ans
|
|
144
|
+
c.evaluate("ans * 2"); // computes 16, stored as ans
|
|
145
|
+
c.done(); // 16
|
|
183
146
|
```
|
|
184
147
|
|
|
185
|
-
###
|
|
186
|
-
|
|
187
|
-
Exprify supports matrix literals with `;` as row separators.
|
|
188
|
-
|
|
189
|
-
```js
|
|
190
|
-
expr.evaluate("a = [1, 2, 3; 4, 5, 6]");
|
|
191
|
-
// {"exprify":"DenseMatrix","data":[[1,2,3],[4,5,6]],"size":[2,3]}
|
|
192
|
-
|
|
193
|
-
expr.evaluate("a[2, 3]");
|
|
194
|
-
// 6
|
|
195
|
-
|
|
196
|
-
expr.evaluate("a[1:2, 2]");
|
|
197
|
-
// "2\n5"
|
|
198
|
-
|
|
199
|
-
expr.evaluate("a[3, 1:3] = [7, 8, 9]");
|
|
200
|
-
// "7\t8\t9"
|
|
148
|
+
### `expr.exportState()` / `expr.importState(state)`
|
|
201
149
|
|
|
202
|
-
|
|
203
|
-
// -7
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
### Linear Algebra Helpers
|
|
150
|
+
Serializes the complete engine state - all variables, registered functions, and unit definitions - into a plain object that can be stored, transmitted, or restored later. `importState` loads a previously exported snapshot into a fresh instance, fully reconstructing that environment.
|
|
207
151
|
|
|
208
152
|
```js
|
|
209
|
-
expr.
|
|
210
|
-
// {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
// {
|
|
214
|
-
|
|
215
|
-
expr.evaluate("qr([[1, -1, 4], [1, 4, -2], [1, 4, 2], [1, -1, 0]])");
|
|
216
|
-
// {"Q":{"exprify":"DenseMatrix",...},"R":{"exprify":"DenseMatrix",...}}
|
|
153
|
+
const state = expr.exportState();
|
|
154
|
+
// {
|
|
155
|
+
// variables: { x: 10, y: 5 },
|
|
156
|
+
// functions: ["double", "clamp"],
|
|
157
|
+
// units: {...}
|
|
158
|
+
// }
|
|
217
159
|
|
|
218
|
-
|
|
219
|
-
|
|
160
|
+
const expr2 = new Exprify();
|
|
161
|
+
expr2.importState(state);
|
|
162
|
+
expr2.evaluate("x + y"); // 15
|
|
220
163
|
```
|
|
221
164
|
|
|
222
|
-
|
|
165
|
+
### Inline Function Definitions
|
|
223
166
|
|
|
224
|
-
|
|
167
|
+
Functions can be defined directly inside an expression using the `name(params) = body` syntax. Once defined, they behave exactly like functions registered via `addFunction` and remain available for the lifetime of the instance.
|
|
225
168
|
|
|
226
169
|
```js
|
|
227
|
-
expr.evaluate(
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
expr.evaluate('derivative("2x^2 + 3x + 4", "x")');
|
|
231
|
-
// "4 * x + 3"
|
|
232
|
-
|
|
233
|
-
expr.evaluate('rationalize("2x/y - y/(x+1)", true)');
|
|
234
|
-
// {"numerator":"2 * x ^ 2 + 2 * x - y ^ 2","denominator":"x * y + y","coefficients":[],"variables":["x","y"],"expression":"(2 * x ^ 2 + 2 * x - y ^ 2) / (x * y + y)"}
|
|
170
|
+
expr.evaluate("hyp(a, b) = sqrt(a^2 + b^2)");
|
|
171
|
+
expr.evaluate("hyp(3, 4)"); // 5
|
|
172
|
+
expr.evaluate("hyp(5, 12)"); // 13
|
|
235
173
|
```
|
|
236
174
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
```js
|
|
240
|
-
expr.evaluate('leafCount("e^(i*pi)-1")');
|
|
241
|
-
// 4
|
|
242
|
-
|
|
243
|
-
expr.evaluate('leafCount(parse("{a: 22/7, b: 10^(1/2)}"))');
|
|
244
|
-
// 5
|
|
245
|
-
```
|
|
175
|
+
This is particularly convenient for one-off helpers that do not warrant a full `addFunction` call, or for expressions that define and immediately use a function in a single evaluation step.
|
|
246
176
|
|
|
247
|
-
|
|
177
|
+
## Built-in Functions (Selected)
|
|
248
178
|
|
|
249
|
-
|
|
179
|
+
| Function | Description | Example | Result |
|
|
180
|
+
|---|---|---|---|
|
|
181
|
+
| `abs` | Absolute value | `abs(-5)` | `5` |
|
|
182
|
+
| `round` | Round to nearest integer | `round(3.7)` | `4` |
|
|
183
|
+
| `floor` | Round down | `floor(3.7)` | `3` |
|
|
184
|
+
| `ceil` | Round up | `ceil(3.2)` | `4` |
|
|
250
185
|
|
|
251
|
-
|
|
252
|
-
- `sin`, `cos`, `tan`, `asin`, `acos`, `atan`
|
|
253
|
-
- `log`, `log10`, `exp`, `random`
|
|
254
|
-
- `clamp`, `if`, `length`, `typeof`
|
|
255
|
-
- `det`, `lsolve`, `lup`, `lyap`, `qr`, `polynomialRoot`
|
|
256
|
-
- `simplify`, `derivative`, `rationalize`, `leafCount`, `parse`
|
|
186
|
+
> See the [full searchable function reference](docs/reference/functions.md) for all ~130 built-in functions.
|
|
257
187
|
|
|
258
188
|
## Return Types
|
|
259
189
|
|
|
260
|
-
|
|
190
|
+
| Type | Example expression | Result |
|
|
191
|
+
|---|---|---|
|
|
192
|
+
| Number / BigInt / Boolean | `2 + 2`, `true && false` | `4`, `false` |
|
|
193
|
+
| String | `"hello" + " world"` | `"hello world"` |
|
|
194
|
+
| Unit string | `2 inch to cm` | `"5.08 cm"` |
|
|
195
|
+
| Complex string | `3 + 2i` | `"3 + 2i"` |
|
|
196
|
+
| Matrix JSON | `[1,2;3,4]` | `{"exprify":"DenseMatrix",...}` |
|
|
197
|
+
| Structured JSON | `lup(...)`, `rationalize(..., true)` | JSON object string |
|
|
198
|
+
| Function | `x -> x^2` | Native JS function |
|
|
199
|
+
| Array | `1:5` | `[1,2,3,4,5]` |
|
|
261
200
|
|
|
262
|
-
- numbers / bigint / booleans
|
|
263
|
-
- strings
|
|
264
|
-
- formatted unit strings like `"5.08 cm"`
|
|
265
|
-
- formatted complex strings like `"3 + 2i"`
|
|
266
|
-
- matrix wrapper JSON strings such as `{"exprify":"DenseMatrix",...}`
|
|
267
|
-
- JSON strings for structured helper outputs like `lup()` or `rationalize(..., true)`
|
|
268
201
|
|
|
269
202
|
## Manual Build
|
|
270
203
|
|
|
271
204
|
```bash
|
|
272
|
-
git clone https://github.com/code-hemu/
|
|
205
|
+
git clone https://github.com/code-hemu/exprify.git
|
|
273
206
|
cd Exprify
|
|
274
207
|
npm install
|
|
275
208
|
npm run build
|
|
276
209
|
```
|
|
277
210
|
|
|
278
|
-
|
|
211
|
+
Output is written to `dist/`.
|
|
279
212
|
|
|
280
213
|
## Testing
|
|
281
214
|
|
|
@@ -283,21 +216,15 @@ Build output is written to `dist/`.
|
|
|
283
216
|
npm test
|
|
284
217
|
```
|
|
285
218
|
|
|
286
|
-
Tested in CI across Node 20 and 22
|
|
287
|
-
|
|
288
|
-
## Publishing
|
|
289
|
-
|
|
290
|
-
The package is published to the public npm registry via `npm publish`. The `npm-publish.yml` workflow runs on GitHub release events. See `.github/workflows/npm-publish.yml` for details.
|
|
291
|
-
|
|
292
|
-
`package-lock.json` is committed but is not shipped in the published tarball (see `.npmignore`); consumers generate their own lockfile when installing.
|
|
293
|
-
|
|
294
|
-
## License
|
|
295
|
-
|
|
296
|
-
Exprify is licensed under GPL-3.0. Copyright (c) [Nirmal Paul](https://github.com/nirmalpaul383/).
|
|
219
|
+
Tested in CI across Node 20 and 22. See `.github/workflows/ci.yml` for details.
|
|
297
220
|
|
|
298
221
|
## Contributing
|
|
299
222
|
|
|
300
223
|
1. Fork the repository.
|
|
301
224
|
2. Create a branch: `git checkout -b feature/your-feature`
|
|
302
225
|
3. Commit your changes: `git commit -m "Add your feature"`
|
|
303
|
-
4. Push
|
|
226
|
+
4. Push and open a pull request.
|
|
227
|
+
|
|
228
|
+
## License
|
|
229
|
+
|
|
230
|
+
Exprify is licensed under **GPL-3.0**. Copyright © [Nirmal Paul](https://github.com/nirmalpaul383/).
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
| Version | Supported |
|
|
6
|
+
| ------- | --------- |
|
|
7
|
+
| 1.0.5 | ❌ |
|
|
8
|
+
| 1.0.6 | ✅ |
|
|
9
|
+
|
|
10
|
+
## Reporting a Vulnerability
|
|
11
|
+
|
|
12
|
+
If you discover a security vulnerability in Exprify, please report it privately by opening a security advisory at:
|
|
13
|
+
|
|
14
|
+
https://github.com/code-hemu/exprify/security/advisories/new
|
|
15
|
+
|
|
16
|
+
You can expect an acknowledgment within 48 hours and a detailed response within 5 business days. If the vulnerability is accepted, a fix will be coordinated through a private release and published as a patch version. If declined, you will receive an explanation of why the issue does not constitute a security risk.
|
|
17
|
+
|
|
18
|
+
Please do **not** report security vulnerabilities through public GitHub issues, discussions, or pull requests.
|