es2xml

convert AST generated by acorn to XML and flatten AST to matrix

Usage no npm install needed!

<script type="module">
  import es2xml from 'https://cdn.skypack.dev/es2xml';
</script>

README

es2xml

convert AST generated by acorn to XML and flatten AST to matrix

Install

npm install es2xml

Usage


cmdline

1. select nodes

    #global install
        npm install es2xml -g
    #command <input_js_file>, for example:
        function_declaration angular.min.js
    #will generate a js file begin with <input_js_file>__
        E2XLAB# ls -l | egrep angular.min.js__
        -rw-r--r-- 1 root root  264043 Jun  1 08:03 angular.min.js__undefined_undefined_undefined_undefined_undefined_undefined
        E2XLAB#
        E2XLAB# cat angular.min.js__undefined_undefined_undefined_undefined_undefined_undefined | egrep "^function"
        function N(a) {
        function ta(a) {
        function q(a, b, d) {
        function tc(a, b, d) {
        function uc(a) {
        function Yd() {
        function Pb(a, b, d) {
        ......
        
        E2XLAB#vim angular.min.js__undefined_undefined_undefined_undefined_undefined_undefined | egrep "^function"
        
        function N(a) {
            return function () {
                var b = arguments[0], d;
                d = '[' + (a ? a + ':' : '') + b + '] http://errors.angularjs.org/1.5.8/' + (a ? a + '/' : '') + b;
                for (b = 1; b < arguments.length; b++) {
                    d = d + (1 == b ? '?' : '&') + 'p' + (b - 1) + '=';
                    var c = encodeURIComponent, e;
                    e = arguments[b];
                    e = 'function' == typeof e ? e.toString().replace(/ \{[\s\S]*$/, '') : 'undefined' == typeof e ? 'undefined' : 'string' != typeof e ? JSON.stringify(e) : e;
                    d += c(e);
                }
                return Error(d);
            };
        }
        ================================
        function ta(a) {
            if (null == a || Va(a))
                return !1;
            if (L(a) || G(a) || F && a instanceof F)
                return !0;
            var b = 'length' in Object(a) && a.length;
            return T(b) && (0 <= b && (b - 1 in a || a instanceof Array) || 'function' == typeof a.item);
        }
        ================================
        ......
      
    # supported commands     
    function_expression
    function_declaration
    arrow_function_expression
    member_expression
    expression_statement
    if_statement
    switch_statement
    switch_case
    with_statement
    block_statement
    break_statement
    continue_statement
    label_statement
    empty_statement
    debugger_statement
    return_statement
    throw_statement
    try_statement
    do_while_statement
    while_statement
    for_statement
    for_of_statement
    for_in_statement
    this_expression
    array_expression
    array_pattern
    object_expression
    object_pattern
    property
    unary_expression
    update_expression
    binary_expression
    assignment_expression
    logical_expression
    conditional_expression
    call_expression
    new_expression
    sequence_expression
    yield_expression
    await_expression
    variable_declaration
    variable_declarator
    catch_clause
    identifier
    literal
    regex_literal
    super
    spread_element
    template_literal
    template_element
    tagged_template_expression
    assignment_pattern
    rest_element
    class_declaration
    class_expression
    class_body
    method_definition
    meta_property
    import_declaration
    import_specifier
    import_default_specifier
    import_namespace_specifier
    export_specifier
    export_default_specifier
    export_name_declaration
    export_all_declaration

    
    # ls -l | egrep axios.min.js
    -rw-r--r-- 1 root root  12941 Feb 19  2018 axios.min.js

    e2x axios.min.js axios.min.xml "es-"

    # ls -l
    -rw-r--r-- 1 root root  12941 Feb 19  2018 axios.min.js
    -rw-r--r-- 1 root root 693231 Apr 30 23:56 axios.min.xml

    vim axios.min.xml
    
    <es-root>
      <es-body>
        <es-0 type="ExpressionStatement">
          <es-expression type="UnaryExpression" operator="%21" prefix="true">
            <es-argument type="CallExpression">
              <es-callee type="FunctionExpression" expression="false" generator="false" async="false">
                <es-params>
                  <es-0 type="Identifier" name="e">
                  </es-0>
                  <es-1 type="Identifier" name="t">
                  </es-1>
                </es-params>
                ......

2. beautify

   #npm install es2xml -g
   #esbeau mozilla.tst.1.js
   # head beauty.mozilla.tst.1.js
   (function (global, factory) {
       if (typeof module === 'object' && typeof module.exports === 'object') {
           module.exports = global.document ? factory(global, true) : function (w) {
               if (!w.document) {
                   throw new Error('jQuery requires a window with a document');
               }
               return factory(w);
           };
       } else {
            factory(global);

code

    var e2x = require("es2xml")
    var acorn = require("acorn")
    var code = `function isNewLine(code, ecma2019String) {
      return code === 10 || code === 13 || !ecma2019String && (code === 0x2028 || code === 0x2029);
    }`
    var ast = acorn.parse(code)

1. e2x.xml(ast)

    #tag-prefix = ""
    console.log(e2x.xml(ast,"")) 

2. search the AST using css selector

    var cheerio =require('cheerio')
    var code = e2x.xml(ast)
    var $ = cheerio.load(code,{xmlMode:true})
    $("[type=Identifier]").length
    $("[type=Identifier]")[0].attribs
    $("[type=Identifier]")[1].attribs
    $("[type=Identifier]")[2].attribs
    $("[type=BinaryExpression]")[0].attribs.operator
    //according to estree spec , some special-chars-not-allowed-in-html exist, so need escape/unescape
    unescape($("[type=BinaryExpression]")[0].attribs.operator)

3. flatten and traverse the AST

    //acorn-walk use sax-like-way to traverse the AST
    //and too many recursive functions in it, its hard to read
    //sometimes, its not convient for me to copy and resue the code
    //so i use a matrix to store it,make everything F-L-A-T and C-L-E-A-R
    //dfs is depth-first-search-path-record
    //wfs is width-first-search-path-record
    var mat = e2x.esmat(ast)
    var pldfs = e2x.pldfs(mat)
    var attrdfs = e2x.attrdfs(mat)
    var locdfs = e2x.locdfs(mat)
    var plwfs = e2x.plwfs(mat)
    var locwfs = e2x.locwfs(mat)

Doc


In Progressing...


STANDARDS

(The ESTree Spec)


The ESTree Spec


PACKAGE DEPENDANY


elist


CODE REFERENCE

(thanks to)


1. acorn-walk



USEAGE SCREENSHOOTS


    var e2x = require("es2xml")
    var acorn = require("acorn")
    var code = `function isNewLine(code, ecma2019String) {
      return code === 10 || code === 13 || !ecma2019String && (code === 0x2028 || code === 0x2029);
    }`
    var ast = acorn.parse(code)

    var cheerio =require('cheerio')
    var code = e2x.xml(ast)
    var $ = cheerio.load(code,{xmlMode:true})
    $("[type=Identifier]").length
    $("[type=Identifier]")[0].attribs
    $("[type=Identifier]")[1].attribs
    $("[type=Identifier]")[2].attribs
    $("[type=BinaryExpression]")[0].attribs.operator
    unescape($("[type=BinaryExpression]")[0].attribs.operator)

    var mat = e2x.esmat(ast)
    var pldfs = e2x.pldfs(mat)

    var attrdfs = e2x.attrdfs(mat)

    var locdfs = e2x.locdfs(mat)

    var plwfs = e2x.plwfs(mat)

    var locwfs = e2x.locwfs(mat)        


TODO


1.xml2es
2.doc