Add existing to tracked

This commit is contained in:
Jay
2026-08-11 09:53:42 -04:00
parent afe07f3055
commit ffd6e3d73c
8531 changed files with 4396230 additions and 0 deletions
Generated Vendored
+20
View File
@@ -0,0 +1,20 @@
Copyright (c) 2013 Stephen Oney, https://ericsmekens.github.io/jsep/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+208
View File
@@ -0,0 +1,208 @@
## jsep: A Tiny JavaScript Expression Parser
[jsep](https://ericsmekens.github.io/jsep/) is a simple expression parser written in JavaScript. It can parse JavaScript expressions but not operations. The difference between expressions and operations is akin to the difference between a cell in an Excel spreadsheet vs. a proper JavaScript program.
### Why jsep?
I wanted a lightweight, tiny parser to be included in one of my other libraries. [esprima](http://esprima.org/) and other parsers are great, but had more power than I need and were *way* too large to be included in a library that I wanted to keep relatively small.
jsep's output is almost identical to [esprima's](http://esprima.org/doc/index.html#ast), which is in turn based on [SpiderMonkey's](https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API).
### Custom Build
While in the jsep project directory, run:
```bash
npm install
npm run default
```
The jsep built files will be in the build/ directory.
### Usage
#### Client-side
```html
<script type="module">
import jsep from '/PATH/TO/jsep.min.js';
const parsed = jsep('1 + 1');
</script>
<script src="/PATH/TO/jsep.iife.min.js"></script>
...
let parse_tree = jsep("1 + 1");
```
#### Node.JS
First, run `npm install jsep`. Then, in your source file:
```javascript
// ESM:
import jsep from 'jsep';
const parse_tree = jsep('1 + 1');
// or:
import { Jsep } from 'jsep';
const parse_tree = Jsep.parse('1 + 1');
// CJS:
const jsep = require('jsep').default;
const parsed = jsep('1 + 1');
// or:
const { Jsep } = require('jsep');
const parse_tree = Jsep.parse('1 + 1');
```
#### Custom Operators
```javascript
// Add a custom ^ binary operator with precedence 10
// (Note that higher number = higher precedence)
jsep.addBinaryOp("^", 10);
// Add exponentiation operator (right-to-left)
jsep.addBinaryOp('**', 11, true); // now included by default
// Add a custom @ unary operator
jsep.addUnaryOp('@');
// Remove a binary operator
jsep.removeBinaryOp(">>>");
// Remove a unary operator
jsep.removeUnaryOp("~");
```
#### Custom Identifiers
You can add or remove additional valid identifier chars. ('_' and '$' are already treated like this.)
```javascript
// Add a custom @ identifier
jsep.addIdentifierChar("@");
// Removes a custom @ identifier
jsep.removeIdentifierChar('@');
```
#### Custom Literals
You can add or remove additional valid literals. By default, only `true`, `false`, and `null` are defined
```javascript
// Add standard JS literals:
jsep.addLiteral('undefined', undefined);
jsep.addLiteral('Infinity', Infinity);
jsep.addLiteral('NaN', NaN);
// Remove "null" literal from default definition
jsep.removeLiteral('null');
```
### Plugins
JSEP supports defining custom hooks for extending or modifying the expression parsing.
Plugins are registered by calling `jsep.plugins.register()` with the plugin(s) as the argument(s).
#### JSEP-provided plugins:
| | |
|-----------------------------------|-------------------------------------------------------------------------------------------|
| [ternary](packages/ternary) | Built-in by default, adds support for ternary `a ? b : c` expressions |
| [arrow](packages/arrow) | Adds arrow-function support: `v => !!v` |
| [assignment](packages/assignment) | Adds assignment and update expression support: `a = 2`, `a++` |
| [comment](packages/comment) | Adds support for ignoring comments: `a /* ignore this */ > 1 // ignore this too` |
| [new](packages/new) | Adds 'new' keyword support: `new Date()` |
| [numbers](packages/numbers) | Adds hex, octal, and binary number support, ignore _ char |
| [object](packages/object) | Adds object expression support: `{ a: 1, b: { c }}` |
| [regex](packages/regex) | Adds support for regular expression literals: `/[a-z]{2}/ig` |
| [spread](packages/spread) | Adds support for the spread operator, `fn(...[1, ...a])`. Works with `object` plugin, too |
| [template](packages/template) | Adds template literal support: `` `hi ${name}` `` |
| | |
#### How to add plugins:
Plugins have a `name` property so that they can only be registered once.
Any subsequent registrations will have no effect. Add a plugin by registering it with JSEP:
```javascript
import jsep from 'jsep';
import ternary from '@jsep-plugin/ternary';
import object from '@jsep-plugin/object';
jsep.plugins.register(object);
jsep.plugins.register(ternary, object);
```
#### List plugins:
Plugins are stored in an object, keyed by their name.
They can be retrieved through `jsep.plugins.registered`.
#### Writing Your Own Plugin:
Plugins are objects with two properties: `name` and `init`.
Here's a simple plugin example:
```javascript
const plugin = {
name: 'the plugin',
init(jsep) {
jsep.addIdentifierChar('@');
jsep.hooks.add('gobble-expression', function myPlugin(env) {
if (this.char === '@') {
this.index += 1;
env.node = {
type: 'MyCustom@Detector',
};
}
});
},
};
```
This example would treat the `@` character as a custom expression, returning
a node of type `MyCustom@Detector`.
##### Hooks
Most plugins will make use of hooks to modify the parsing behavior of jsep.
All hooks are bound to the jsep instance, are called with a single argument, and return void.
The `this` context provides access to the internal parsing methods of jsep
to allow reuse as needed. Some hook types will pass an object that allows reading/writing
the `node` property as needed.
##### Hook Types
* `before-all`: called just before starting all expression parsing.
* `after-all`: called after parsing all. Read/Write `arg.node` as required.
* `gobble-expression`: called just before attempting to parse an expression. Set `arg.node` as required.
* `after-expression`: called just after parsing an expression. Read/Write `arg.node` as required.
* `gobble-token`: called just before attempting to parse a token. Set `arg.node` as required.
* `after-token`: called just after parsing a token. Read/Write `arg.node` as required.
* `gobble-spaces`: called when gobbling whitespace.
##### The `this` context of Hooks
```typescript
export interface HookScope {
index: number;
readonly expr: string;
readonly char: string; // current character of the expression
readonly code: number; // current character code of the expression
gobbleSpaces: () => void;
gobbleExpressions: (untilICode?: number) => Expression[];
gobbleExpression: () => Expression;
gobbleBinaryOp: () => PossibleExpression;
gobbleBinaryExpression: () => PossibleExpression;
gobbleToken: () => PossibleExpression;
gobbleTokenProperty: (node: Expression) => Expression;
gobbleNumericLiteral: () => PossibleExpression;
gobbleStringLiteral: () => PossibleExpression;
gobbleIdentifier: () => PossibleExpression;
gobbleArguments: (untilICode: number) => PossibleExpression;
gobbleGroup: () => Expression;
gobbleArray: () => PossibleExpression;
throwError: (msg: string) => never;
}
```
### License
jsep is under the MIT license. See LICENSE file.
### Thanks
Some parts of the latest version of jsep were adapted from the esprima parser.
+1129
View File
File diff suppressed because it is too large Load Diff
+1
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+3
View File
@@ -0,0 +1,3 @@
{
"type": "commonjs"
}
+1132
View File
File diff suppressed because it is too large Load Diff
+1
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1126
View File
File diff suppressed because it is too large Load Diff
+2
View File
File diff suppressed because one or more lines are too long
+1
View File
File diff suppressed because one or more lines are too long
+153
View File
@@ -0,0 +1,153 @@
{
"name": "jsep",
"version": "1.4.0",
"description": "a tiny JavaScript expression parser",
"author": "Stephen Oney <swloney@gmail.com> (http://from.so/)",
"maintainers": [
"Eric Smekens (https://github.com/EricSmekens)",
"Lea Verou (https://github.com/LeaVerou)"
],
"homepage": "https://ericsmekens.github.io/jsep/",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/EricSmekens/jsep.git"
},
"type": "module",
"main": "./dist/cjs/jsep.cjs.js",
"module": "./dist/jsep.js",
"exports": {
".": {
"types": "./typings/tsd.d.ts",
"require": "./dist/cjs/jsep.cjs.js",
"default": "./dist/jsep.js"
}
},
"typings": "typings/tsd.d.ts",
"private": false,
"devDependencies": {
"@commitlint/cli": "^13.1.0",
"@commitlint/config-angular": "^13.1.0",
"@rollup/plugin-replace": "^2.4.2",
"@semantic-release/changelog": "^5.0.1",
"@semantic-release/exec": "^6.0.3",
"@semantic-release/git": "^9.0.0",
"benchmark": "^2.1.4",
"docco": "^0.9.1",
"eslint": "^7.23.0",
"http-server": "^14.1.1",
"husky": "^7.0.0",
"node-qunit-puppeteer": "^2.1.2",
"puppeteer": "^19.9.0",
"rollup": "^2.44.0",
"rollup-plugin-delete": "^2.0.0",
"rollup-plugin-terser": "^7.0.2",
"semantic-release-monorepo": "^7.0.5",
"semantic-release-plus": "^18.4.1"
},
"engines": {
"node": ">= 10.16.0"
},
"directories": {
"test": "test"
},
"release": {
"commitPaths": [
"src/",
"packages/ternary/src/",
"types",
"typings/",
".npmignore",
"package*.json",
"rollup*.js"
],
"branches": [
"master",
{
"name": "alpha",
"prerelease": true
},
{
"name": "beta",
"prerelease": true
}
],
"plugins": [
[
"@semantic-release/commit-analyzer",
{
"preset": "angular",
"parserOpts": {
"noteKeywords": [
"BREAKING CHANGE",
"BREAKING CHANGES",
"BREAKING"
]
}
}
],
[
"@semantic-release/release-notes-generator",
{
"preset": "angular",
"parserOpts": {
"noteKeywords": [
"BREAKING CHANGE",
"BREAKING CHANGES",
"BREAKING"
]
},
"writerOpts": {
"commitsSort": [
"scope",
"subject"
]
}
}
],
"@semantic-release/changelog",
[
"@semantic-release/exec",
{
"prepareCmd": "NEXT_VERSION=${nextRelease.version} pnpm run build"
}
],
[
"@semantic-release/npm",
{
"tarballDir": "./"
}
],
[
"@semantic-release/git",
{
"message": "build: ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
],
[
"@semantic-release/github",
{
"assets": [
{
"path": "./*.tgz",
"label": "build"
}
]
}
]
]
},
"scripts": {
"default": "npm run lint && npm run build:all && npm run test:all && npm run docco",
"build": "npx rollup -c && cp package-cjs.json dist/cjs/package.json",
"build:watch": "npx rollup -c --watch",
"build:all": "pnpm run build -r",
"test": "npx http-server -p 49649 --silent & npx node-qunit-puppeteer http://localhost:49649/test/unit_tests.html",
"test:all": "npx http-server -p 49649 --silent & pnpm run test -r --workspace-concurrency=1",
"test:performance": "node test/performance.test.js",
"docco": "npx docco src/jsep.js --css=src/docco.css --output=annotated_source/",
"lint": "npx eslint src/**/*.js test/*.js test/packages/**/*.js packages/**/*.js",
"prepare": "husky install",
"release": "./release.sh"
}
}
+180
View File
@@ -0,0 +1,180 @@
declare module 'jsep' {
namespace jsep {
export type baseTypes = string | number | boolean | RegExp | null | undefined | object;
export interface Expression {
type: string;
[key: string]: baseTypes | Expression | Array<baseTypes | Expression>;
}
export interface ArrayExpression extends Expression {
type: 'ArrayExpression';
/** The expression can be null in the case of array holes ([ , , ]) */
elements: Array<null | Expression>;
}
export interface BinaryExpression extends Expression {
type: 'BinaryExpression';
operator: string;
left: Expression;
right: Expression;
}
export interface CallExpression extends Expression {
type: 'CallExpression';
arguments: Expression[];
callee: Expression;
}
export interface Compound extends Expression {
type: 'Compound';
body: Expression[];
}
export interface SequenceExpression extends Expression {
type: 'SequenceExpression';
expressions: Expression[];
}
export interface ConditionalExpression extends Expression {
type: 'ConditionalExpression';
test: Expression;
consequent: Expression;
alternate: Expression;
}
export interface Identifier extends Expression {
type: 'Identifier';
name: string;
}
export interface Literal extends Expression {
type: 'Literal';
value: boolean | number | string | RegExp | null;
raw: string;
}
export interface MemberExpression extends Expression {
type: 'MemberExpression';
computed: boolean;
object: Expression;
property: Expression;
optional?: boolean;
}
export interface ThisExpression extends Expression {
type: 'ThisExpression';
}
export interface UnaryExpression extends Expression {
type: 'UnaryExpression';
operator: string;
argument: Expression;
prefix: boolean;
}
export type ExpressionType =
'Compound'
| 'SequenceExpression'
| 'Identifier'
| 'MemberExpression'
| 'Literal'
| 'ThisExpression'
| 'CallExpression'
| 'UnaryExpression'
| 'BinaryExpression'
| 'ConditionalExpression'
| 'ArrayExpression';
export type CoreExpression =
ArrayExpression
| BinaryExpression
| CallExpression
| Compound
| SequenceExpression
| ConditionalExpression
| Identifier
| Literal
| MemberExpression
| ThisExpression
| UnaryExpression;
export type PossibleExpression = Expression | undefined;
export interface HookScope {
index: number;
readonly expr: string;
readonly char: string; // current character of the expression
readonly code: number; // current character code of the expression
gobbleSpaces: () => void;
gobbleExpressions: (untilICode?: number) => Expression[];
gobbleExpression: () => Expression;
gobbleBinaryOp: () => PossibleExpression;
gobbleBinaryExpression: () => PossibleExpression;
gobbleToken: () => PossibleExpression;
gobbleTokenProperty: (node: Expression) => Expression
gobbleNumericLiteral: () => PossibleExpression;
gobbleStringLiteral: () => PossibleExpression;
gobbleIdentifier: () => PossibleExpression;
gobbleArguments: (untilICode: number) => PossibleExpression;
gobbleGroup: () => Expression;
gobbleArray: () => PossibleExpression;
throwError: (msg: string) => never;
}
export type HookType = 'gobble-expression' | 'after-expression' | 'gobble-token' | 'after-token' | 'gobble-spaces';
export type HookCallback = (this: HookScope, env: { node?: Expression }) => void;
type HookTypeObj = Partial<{ [key in HookType]: HookCallback}>
export interface IHooks extends HookTypeObj {
add(name: HookType, cb: HookCallback, first?: boolean): void;
add(obj: { [name in HookType]: HookCallback }, first?: boolean): void;
run(name: string, env: { context?: typeof jsep, node?: Expression }): void;
}
let hooks: IHooks;
export interface IPlugin {
name: string;
init: (this: typeof jsep) => void;
}
export interface IPlugins {
registered: { [name: string]: IPlugin };
register: (...plugins: IPlugin[]) => void;
}
let plugins: IPlugins;
let unary_ops: { [op: string]: any };
let binary_ops: { [op: string]: number };
let right_associative: Set<string>;
let additional_identifier_chars: Set<string>;
let literals: { [literal: string]: any };
let this_str: string;
function addBinaryOp(operatorName: string, precedence: number, rightToLeft?: boolean): void;
function addUnaryOp(operatorName: string): void;
function addLiteral(literalName: string, literalValue: any): void;
function addIdentifierChar(identifierName: string): void;
function removeBinaryOp(operatorName: string): void;
function removeUnaryOp(operatorName: string): void;
function removeLiteral(literalName: string): void;
function removeIdentifierChar(identifierName: string): void;
function removeAllBinaryOps(): void;
function removeAllUnaryOps(): void;
function removeAllLiterals(): void;
const version: string;
}
function jsep(val: string | jsep.Expression): jsep.Expression;
export = jsep;
}