Have ideas to improve npm?Join in the discussion! »

    ceval
    TypeScript icon, indicating that this package has built-in type declarations

    1.2.5 • Public • Published

    Ceval

    CI Node.js CI

    online demo;

    中文文档 零依赖,适合表达式运算;

    No dependence, suitable for calculating expressions;

    ┌───────────────────────────────┐
    │                               │
    │   Destinationlib/index.js   │
    │   Bundle Size:  21.92 KB      │
    │   Minified Size:  21.89 KB    │
    │   Gzipped Size:  6.76 KB      │
    │                               │
    └───────────────────────────────┘

    usage

    npm i ceval -S

    introduce

    alt=流程图

    Options

    const Parser = require('ceval')
    const analysis = new Parser({
       /**
       * @desc Allow operators
       * @type {boolean} 
       */
      endableOperators?: boolean = true;
     
      /**
       * @desc number enable multi bit base
       * @type {boolean} 
       */
      endableBitNumber?: boolean = true;
     
      /**
       * @desc Allow access to members
       * @type {boolean} 
       */
      allowMemberAccess?: boolean = true;
     
      /**
       * @desc Zoom in calculation allowed by default
       * @see To process the results of arithmetic e.g 0.1+0.2 !== 0.3  || 1.0-0.9 !== 0.1
       * Beyond the boundary(ta > Number.MAX_SAFE_INTEGER || ta < Number.MIN_SAFE_INTEGER)will not do processing, restore arithmetic
       * @requires false 
       * @type {boolean} 
       */
      allowHandleNumberPrecision?: boolean = true;
     
      /**
       * @desc Operators are not allowed to be overridden by presetvalue by default
       * @see In some cases, developers want to make more accurate calculations, such as BigInt, presetValue={'+':Function}
       * @requires false
       * @type {boolean} 
       * @memberof CevalOptions
       */
      allowOperatorsCovered?: boolean;
     
      /**
       * @desc Trigger default return value when there is no return value or undefined
       * @type {any} 
       */
      defaultReturnValues?: any = '' // done
    })

    API

    Parser Instance API

    api desc type
    operatorMap Operators mapping table, which can be used in preset values overlay operation Record<string, Function>
    getSupportOperationMap The name of the operator method supported by the query can be overridden (ops: string) => null
    parseString Parsing strings, exposing methods to the outside world (expression: string, values?: Record<string, any>) => any;
    getCurrentValues Get current datapool preset + external + internal declaration () => Record<string, any>
    updatePresetValues Update PresetValues (values: Record<string, any>) => void
    updateOptions Update Option (Options: Partial) => void
    getOptions get Options () => Readonly

    about Options example test case;

    use test262 test case;

    rule

    There are two rules:

    Semicolon at the end

    e.g.

    parse('0b01 + 0b01;') // 2 

    Although it is not necessary in a simple expression operation, but it's a good habit.The parser can know exactly where the end is, Although it doesn't have too many restrictions.

    e.g.

    parse(`
      function abs(a,b,c) { 
        let b = 1 /* ⚠️ error, must has semicolon */
        c = 2;
        return(a+b+c);
      };
      abs(3,4,8);
    `)

    statement

    "var" statement does not affect "scope", it's inserted into values "let" and "const" assigned to the current scope, warn if the current scope exists

    var Parser = require('ceval');
     
    var instance = new Parser({/*...*/});
    var parse = instance.parseString;
     
    parse(`
      var obj = { foo:'foo', bar: 'bar'};
     
      function abs(a,b,c) {
        var d = 'global';
        return (a+b+c);
      }
      abs(1,2,3)
    `)
     
    console.log(instance.getCurrentValues().obj); // { foo:'foo', bar: 'bar'}
    console.log(instance.getCurrentValues().d); // 'global'
     
    parse(`
      let foo = 'foo';
      const bar = 'bar';
      function abs(a,b,c) {
        let d = 'scope';
        const e = 'scope';
        return (a+b+c);
      }
      abs(1,2,3)
    `)
    console.log(instance.getCurrentValues().foo); // undefined
    console.log(instance.getCurrentValues().bar); // undefined
    console.log(instance.getCurrentValues().d); // undefined
    console.log(instance.getCurrentValues().e); // undefined

    basic

    const { parse: parse } = analysis

    Number

    parse('0b01') // 1
    parse('0b11') // 3
    parse('0b010101') // 21
     
    parse('01') // 1
    parse('077') // 63
    parse('01111') // 585
     
    parse('.1') // 1
    parse('33') // 33
    parse('100.00') // 100
     
    parse('0x01') // 1
    parse('0xaf') // 175
    parse('0x9fac') // 40876
     
    parse(`1e+308*2 === Infinity`) // true
     
    parse(`
        var x = NaN;
        var y = NaN;
        return (x !== y);
      `) // true
     
    parse(`
      var x = NaN;
      return(typeof(x) === 'number');
      `) // true
     
    parse(`
      var x = NaN;
      var x_geq_0=(x >= 0.0);
      return(x_geq_0)
      `) // false
     
    parse(`
      var x=+Infinity;
      return(typeof(x) === 'number')
      `) // true

    More testcase here

    calculation

    const obj = `{ a: 1, b: 2, c: 3, d: { e: 4, f: 5}}`
    parse(`1+1`);                       // 2
    parse(`-1-2-3`);                    // -6
    parse(`1*2*3`);                     // 6
    parse(`1/2/4`);                     // 0.125
    parse(`undefined || 2`);            // 2
    parse(`~-1 || -2 || 3`);            // -2
    parse(`-0 == +0`);                  // true
    parse(`~1 > 1`);                    // false
    parse(`false > false > 1`);         // false
    parse(`5 >= 0`);                    // true
    parse(`1 in [1, 2, 3]`);            // true
    parse(`undefined in [1, 2, true]`); // false
    parse(`'a' in ${obj}`);             // true
    parse(`\'\'a\'\' in ${obj}`);       // true ('"a"'  === 'a') is Palindrome
    parse(`1 === true`);                // false
    parse(`3%2`);                       // 1

    Function

    parse(`
      function abs(a,b,c) { 
        var a = 5; /* => inject to presetValues */
        let b = 1; /* => inject to current scope */
        c = 2;
        const d = 4; /* If the current scope contains the variable D, It will trigger warning, but the operation will still be completed, is overlay */
        return(a+b+c);
      };
      abs(3,4,8);
    `)

    Object & Array

    parse(`[1*2, false, true, undefined, null]`); // Array[]
    parse(`var a = { b: { c: ['a','b','c','d']} };'e' in a.b.c`); // false
    parse(`{ a: 1, b: 2, c: { d: undefined, e: { f: false, g: { h: null }}}}`); // object
     
    parse(`var a = { b: 2 };a.b`) //2;
    parse(`var a = { b: 2 };a["b"]`) //2;
    parse(`var a = { b: 2, c:3 };var b='c';a[b]`) //3;
     
    // data reference
    parse(`
      var a = { b: 2, c:[1,2,3]};
      var b='c';
      a[b][0] = '0';
      return a[b];
    `) // ['0',2,3]
     
    parse(`
      var arr = [1,2,3];
      arr[0] = 0;
      return arr;
    `) // [0,2,3]

    Variable

    parse(`
    var a = { foo: 1 };
    var b = { bar: 2 };
    let a = { state: 1 } // ⚠️, Raise warning, current scope exists key
    const b = { state: 1 } // ⚠️, Raise warning, current scope exists key
     
    let c = { coo: 1} // success;
    const d = { coo: 1} // success;
    `)
     
    parse(`
    var a = { a: [false, true, undefined, null, ''] };
    var b = { b: true, c: undefined, d:{ e: a, f: '1', g: {}}};
    `) // Can be obtained from the instance. api: getCurrentValues

    this

    Operator

    Through instance.operatorMap Get all operators;

    return

    return interrupt this operation cycle; but it doesn't affect the outside world.

    parse(`
    return 1;
    return 2;
    `) // 1
     
    parse(`
      var foo = 'foo'
      function abs(a,b,c) {
        return a;
        return b;
      }
      var bar = abs(1,2,3)
      return (bar + foo);
    `) // foo1

    Other

    Please move to test case for more examples

    TODO: Test39 Some test cases,

    speed of progress

    2020-06-24 done: number, null, boolean

    In more function extension, welcome to participate or propose feature.

    development

    develop

    npm start

    build

    # webapck build umd module, No compression 
    npm run build:umd
     
    # rollup build umd module, Compressed version 
    npm run build:rollup
     
    # webpack build docs 
    npm run build:docs

    publish

    npm publish

    Install

    npm i ceval

    DownloadsWeekly Downloads

    17

    Version

    1.2.5

    License

    MIT

    Unpacked Size

    170 kB

    Total Files

    18

    Last publish

    Collaborators

    • avatar