{"id":19541398,"url":"https://github.com/wingify/dom-comparator","last_synced_at":"2025-04-26T17:30:49.633Z","repository":{"id":41492029,"uuid":"22723891","full_name":"wingify/dom-comparator","owner":"wingify","description":"A JS Library that compares two DOM Nodes and outputs what changed between the two.","archived":false,"fork":false,"pushed_at":"2016-06-26T08:10:15.000Z","size":338,"stargazers_count":154,"open_issues_count":1,"forks_count":18,"subscribers_count":45,"default_branch":"master","last_synced_at":"2025-04-04T16:14:03.842Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://engineering.wingify.com/dom-comparator/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wingify.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":"2014-08-07T14:18:44.000Z","updated_at":"2023-11-19T12:40:37.000Z","dependencies_parsed_at":"2022-08-28T19:20:49.236Z","dependency_job_id":null,"html_url":"https://github.com/wingify/dom-comparator","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wingify%2Fdom-comparator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wingify%2Fdom-comparator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wingify%2Fdom-comparator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wingify%2Fdom-comparator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wingify","download_url":"https://codeload.github.com/wingify/dom-comparator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251025584,"owners_count":21524829,"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-11-11T03:10:15.812Z","updated_at":"2025-04-26T17:30:49.342Z","avatar_url":"https://github.com/wingify.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DOM Comparator\n\nDOM Comparator is a library that, simply put, compares two strings of DOM nodes (which are called `stringA` and `stringB`), and returns an output containing the minimal number of steps that must be taken (like attribute changes, style changes, text changes and DOM manimpulation) to convert `stringA` into `stringB`.\n\nThe output returned by DOM Comparator is an array of `VWO.Operation` objects, which can also be expressed as jQuery code. Here's a simple example:\n\n```js\nvar stringA = '\u003cul\u003e\u003cli class=\"active\"\u003elist item 1\u003c/li\u003e\u003cli\u003elist item 2\u003c/li\u003e\u003c/ul\u003e';\nvar stringB = '\u003cul\u003e\u003cli\u003elist item 1\u003c/li\u003e\u003cli\u003elist item 2\u003c/li\u003e\u003c/ul\u003e';\n\n// Compare the two strings\nvar result = VWO.DOMComparator.create({\n\tstringA: stringA,\n\tstringB: stringB\n});\n\n// Expect an array of VWO.Operation objects to be returned.\nexpect(result).toEqual(jasmine.any(Array));\nexpect(result[0]).toEqual(jasmine.any(VWO.Operation));\n\n// Expect the first operation to be a 'removeAttr' operation.\nexpect(result[0].name).toEqual('removeAttr');\n\n// The operation is on an element identified by the following selector path\nexpect(result[0].selectorPath).toEqual('UL:first-child \u003e LI:first-child');\n\n// With below content\nexpect(result[0].content).toEqual({class: 'active'});\n```\n\n## Setting Up\n\n### Installation\n\n* To install all the dependencies run `npm install`.\n* Then run `bower install` for `jasmine`, `jquery` and `underscore` library dependencies.\n* Install grunt globally, which is a Javascript Task Runner `npm install -g grunt-cli`.\n\n### Downloads\n\n* [Development version](https://github.com/wingify/dom-comparator/blob/master/dist/dom-comparator.js) (unminified with comments)\n* [Production version](https://github.com/wingify/dom-comparator/blob/master/dist/dom-comparator.min.js) (minified)\n* [Source map](https://github.com/wingify/dom-comparator/blob/master/dist/dom-comparator.min.js.map)\n\n### Live Demo\n\nA live demo can be found here: http://engineering.wingify.com/dom-comparator/live-demo.html\n\n### Running Tests\n\n* For testing, we use Jasmine.\n* Tests are written in the `test/unit` folder. Each file in the `src` directory have different test cases files associataed with them in the `test/unit` directory. The majority of the test cases that test the library as a black box are in `dom-comparator.spec.js`.\n* To run tests, run `grunt; testem server;` (from the root directory of the repository)\n* To see the final outputs open http://localhost:7357/ in the browser, open the JavaScript console and look for the `final_results` array.\n\n### Cases which don't work\n* If there are multiple occurrences of a node in the DOM. For example:\n\n\u003e `nodeA`:\n```html\n\u003cdiv style=\"display: block;\"\u003e\n\t\u003cul class=\"navigation vwo_1405423029796\" style=\"cursor: auto; display: block;\"\u003e\n\t\u003c/ul\u003e\n\t\u003cdiv class=\"clr\"\u003eORIGINAL TEXT\u003c/div\u003e\n\u003c/div\u003e\n```\n\n\u003e `nodeB`:\n```html\n\u003cdiv class=\"clr\"\u003eORIGINAL TEXT\u003c/div\u003e\n\u003cdiv style=\"display: block;\"\u003e\n\t\u003cul class=\"navigation vwo_1405423029796\" style=\"cursor: auto; display: INLINE;\"\u003e\n\t\u003c/ul\u003e\n\t\u003cdiv class=\"clr\"\u003eORIGINAL TEXT\u003c/div\u003e\n\u003c/div\u003e\n```\n\n\u003e Here, since there are 2 occurrences of `\u003cdiv class=\"clr\"\u003eORIGINAL TEXT\u003c/div\u003e` in `nodeB`, the exact match of it cannot be found in `nodeA`, due to which the resulted output is not as expected.\n\n* When the wrapping of the original node is changed. For example:\n\n\u003e `nodeA`:\n```html\n\u003cdiv style=\"display: block;\"\u003e\n\t\u003cdiv class=\"clr\"\u003eORIGINAL TEXT\u003c/div\u003e\n\u003c/div\u003e\n```\n\n\u003e `nodeB`:\n```html\n\u003cdiv\u003e\n\t\u003cdiv style=\"display: block;\"\u003e\n\t\t\u003cdiv class=\"clr\"\u003eORIGINAL TEXT\u003c/div\u003e\n\t\u003c/div\u003e\n\u003c/div\u003e\n```\n\n\u003e Here, since the wrapping of `nodeB` is changed (wrapped by `\u003cdiv\u003e ... \u003c/div\u003e`), the whole content in `nodeB` would be considered as inserted (because matching heirarchy is top to bottom).\n\n## Documentation\n\nThe general usage documentation can be found on http://engineering.wingify.com/dom-comparator/\n\n## Authors\n\n* Himanshu Kapoor ([@fleon](http://github.com/fleon))\n* Himanshu Kela ([@himanshukela](http://github.com/himanshukela))\n\n## License\n\n[The MIT License](http://opensource.org/licenses/MIT)\n\nCopyright (c) 2014-16 Wingify Software Pvt. Ltd.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwingify%2Fdom-comparator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwingify%2Fdom-comparator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwingify%2Fdom-comparator/lists"}