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


    1.3.1 • Public • Published

    esdom Build Status Code Climate


    Build up DOM from AST or AST from DOM. Just because DOM is something more familiar to web-developers than AST, though there are tools like esquery or ast-types. ESDOM is forward-compatible with esquery, so everything is done via esdom can be painlessly refactored to use esquery.

    Works both in browsers and node.

    $ npm install esdom

    var esdom = require('esdom');
    var esprima = require('esprima');
    var escodegen = require('escodegen');
    var ast = esprima.parse(code);
    var el = esdom.toDOM(ast);
    el.querySelector('Identifier').setAttribute('name', 'x');
    ast = esdom.toAST(el);

    Mapping nodes

    Mapping is done to be compatible with ESQuery selectors as much as possible.

    Let’s take an examplary source:

    var a = 1;

    AST for the source will be:

        "type": "Program",
        "body": [
                "type": "VariableDeclaration",
                "declarations": [
                        "type": "VariableDeclarator",
                        "id": {
                            "type": "Identifier",
                            "name": "a"
                        "init": {
                            "type": "Literal",
                            "value": 1,
                            "raw": "1"
                "kind": "var"

    And resulting HTML:

    <program class="Program Node Printable" type="Program" body="[]">
        <variabledeclaration class="VariableDeclaration Declaration Statement Node Printable" type="VariableDeclaration" declarations="[]" kind="var" prop="body">
            <variabledeclarator class="VariableDeclarator Node Printable" type="VariableDeclarator" id="Identifier" init="Literal" prop="declarations">
                <identifier class="Identifier Expression Pattern Node Printable" type="Identifier" name="a" prop="id"></identifier>
                <literal class="Literal Expression Pattern Node Printable" type="Literal" value="1" raw="1" prop="init"></literal>

    So all esquery css selectors work just fine with that html, with some exceptions:

    • :first-child and :last-child selectors always return non-empty result, where esquery may return nothing. For example, selector VariableDeclarator > Identifier:first-child returns <Identifier>, where esquery returns null.
    • Nested attribute selector should be replaced with subject indicator (or :has): [attr.subAttr=xyz]![attr] > [subAttr=xyz]
    • To select custom esquery pseudos like :statement, it is recommended to use esdom/query, otherwise it should be replaced with natural DOM class .Statement.
    • Regular expression and conditional selectors should be replaced with according css selectors.

    In all other regards it works just the same.


    • esquery is inable to select list of nodes, like all function params, or all function body statements. With esdom you can do .Function > [prop="params"].
    • esdom might be somewhat slow in browsers due to using browser API. In node, DOM is emulated via dom-lite, so it’s times faster.
    • esdom work only with ES5.


    ESDOM also provides helpful scope/variable analysis, marking nodes with additional data- attributes. To analyze DOM, call esdom.analyze(dom), and it will set attributes:

    Attribute Description
    data-scope=<id> Scope indicator
    data-scope-global Global scope flag
    data-scope-parent=<scope-id> Parent scope id
    data-variable=<id> Variable indicator with unique id
    data-variable-declaration Variable declaration flag
    data-variable-scope=<scope-id> Variable holding scope


    Method Description
    .toDOM(ast) Convert AST to DOM element.
    .toAST(element) Build AST from DOM element.
    .analyze(element) Mark up AST nodes



    npm i esdom

    DownloadsWeekly Downloads






    Last publish


    • avatar