{"id":16125675,"url":"https://github.com/dy/esdom","last_synced_at":"2025-09-12T21:33:10.244Z","repository":{"id":25812314,"uuid":"29251348","full_name":"dy/esdom","owner":"dy","description":"Build DOM from AST, change it and convert back to AST.","archived":false,"fork":false,"pushed_at":"2016-08-13T02:39:15.000Z","size":183,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-12-29T00:12:21.236Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://dy.github.io/esdom","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-01-14T15:41:29.000Z","updated_at":"2024-08-22T08:09:15.000Z","dependencies_parsed_at":"2022-07-25T14:52:20.708Z","dependency_job_id":null,"html_url":"https://github.com/dy/esdom","commit_stats":null,"previous_names":["dfcreative/esdom"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dy%2Fesdom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dy%2Fesdom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dy%2Fesdom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dy%2Fesdom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dy","download_url":"https://codeload.github.com/dy/esdom/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":232792150,"owners_count":18577262,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-09T21:30:36.314Z","updated_at":"2025-01-06T21:53:57.012Z","avatar_url":"https://github.com/dy.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# esdom [![Build Status](https://travis-ci.org/dfcreative/esdom.svg?branch=master)](https://travis-ci.org/dfcreative/esdom) [![Code Climate](https://codeclimate.com/github/dfcreative/esdom/badges/gpa.svg)](https://codeclimate.com/github/dfcreative/esdom) \u003ca href=\"UNLICENSE\"\u003e\u003cimg src=\"http://upload.wikimedia.org/wikipedia/commons/6/62/PD-icon.svg\" width=\"20\"/\u003e\u003c/a\u003e\n\n#### [DEMO](http://dfcreative.github.io/esdom/)\n\nBuild 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](https://github.com/estools/esquery) or [ast-types](https://github.com/benjamn/ast-types).\nESDOM is forward-compatible with esquery, so everything is done via esdom can be painlessly refactored to use esquery.\n\nWorks both in browsers and node.\n\n\n`$ npm install esdom`\n\n\n```js\nvar esdom = require('esdom');\nvar esprima = require('esprima');\nvar escodegen = require('escodegen');\n\nvar ast = esprima.parse(code);\n\nvar el = esdom.toDOM(ast);\nel.querySelector('Identifier').setAttribute('name', 'x');\nast = esdom.toAST(el);\n\nescodegen.print(ast);\n```\n\n\n# Mapping nodes\n\nMapping is done to be compatible with [ESQuery selectors](https://github.com/estools/esquery) as much as possible.\n\nLet’s take an examplary source:\n\n```js\nvar a = 1;\n```\n\nAST for the source will be:\n\n```json\n{\n\t\"type\": \"Program\",\n\t\"body\": [\n\t\t{\n\t\t\t\"type\": \"VariableDeclaration\",\n\t\t\t\"declarations\": [\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"VariableDeclarator\",\n\t\t\t\t\t\"id\": {\n\t\t\t\t\t\t\"type\": \"Identifier\",\n\t\t\t\t\t\t\"name\": \"a\"\n\t\t\t\t\t},\n\t\t\t\t\t\"init\": {\n\t\t\t\t\t\t\"type\": \"Literal\",\n\t\t\t\t\t\t\"value\": 1,\n\t\t\t\t\t\t\"raw\": \"1\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"kind\": \"var\"\n\t\t}\n\t]\n}\n```\n\nAnd resulting HTML:\n\n```html\n\u003cprogram class=\"Program Node Printable\" type=\"Program\" body=\"[]\"\u003e\n\t\u003cvariabledeclaration class=\"VariableDeclaration Declaration Statement Node Printable\" type=\"VariableDeclaration\" declarations=\"[]\" kind=\"var\" prop=\"body\"\u003e\n\t\t\u003cvariabledeclarator class=\"VariableDeclarator Node Printable\" type=\"VariableDeclarator\" id=\"Identifier\" init=\"Literal\" prop=\"declarations\"\u003e\n\t\t\t\u003cidentifier class=\"Identifier Expression Pattern Node Printable\" type=\"Identifier\" name=\"a\" prop=\"id\"\u003e\u003c/identifier\u003e\n\t\t\t\u003cliteral class=\"Literal Expression Pattern Node Printable\" type=\"Literal\" value=\"1\" raw=\"1\" prop=\"init\"\u003e\u003c/literal\u003e\n\t\t\u003c/variabledeclarator\u003e\n\t\u003c/variabledeclaration\u003e\n\u003c/program\u003e\n```\n\nSo all esquery css selectors work just fine with that html, with some exceptions:\n\n* `:first-child` and `:last-child` selectors always return non-empty result, where esquery may return nothing. For example, selector `VariableDeclarator \u003e Identifier:first-child` returns `\u003cIdentifier\u003e`, where esquery returns `null`.\n* Nested attribute selector should be replaced with subject indicator (or :has): `[attr.subAttr=xyz]` → `![attr] \u003e [subAttr=xyz]`\n* To select custom esquery pseudos like `:statement`, it is recommended to use [`esdom/query`](query.js), otherwise it should be replaced with natural DOM class `.Statement`.\n* Regular expression and conditional selectors should be replaced with according css selectors.\n\n\nIn all other regards it works just the same.\n\n\n# Notes\n\n* esquery is inable to select list of nodes, like all function params, or all function body statements. With esdom you can do `.Function \u003e [prop=\"params\"]`.\n* esdom might be somewhat slow in browsers due to using browser API. In node, DOM is emulated via [dom-lite](https://www.npmjs.com/package/dom-lite), so it’s times faster.\n* esdom work only with ES5.\n\n\n# Analysis\n\nESDOM also provides helpful scope/variable analysis, marking nodes with additional `data-` attributes. To analyze DOM, call `esdom.analyze(dom)`, and it will set attributes:\n\n| Attribute | Description |\n|---|---|\n| `data-scope=\u003cid\u003e` | Scope indicator |\n| `data-scope-global` | Global scope flag |\n| `data-scope-parent=\u003cscope-id\u003e` | Parent scope id |\n| `data-variable=\u003cid\u003e` | Variable indicator with unique id |\n| `data-variable-declaration` | Variable declaration flag |\n| `data-variable-scope=\u003cscope-id\u003e` | Variable holding scope |\n\n\n\n# API\n\n| Method | Description |\n|---|---|\n| `.toDOM(ast)` | Convert AST to DOM element. |\n| `.toAST(element)` | Build AST from DOM element. |\n| `.analyze(element)` | Mark up AST nodes |\n\n[![NPM](https://nodei.co/npm/esdom.png?downloads=true\u0026downloadRank=true\u0026stars=true)](https://nodei.co/npm/esdom/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdy%2Fesdom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdy%2Fesdom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdy%2Fesdom/lists"}