{"id":20513830,"url":"https://github.com/webreflection/domdiff","last_synced_at":"2025-04-05T04:09:10.916Z","repository":{"id":45738449,"uuid":"113048391","full_name":"WebReflection/domdiff","owner":"WebReflection","description":"Diffing the DOM without virtual DOM","archived":false,"fork":false,"pushed_at":"2022-12-04T22:08:32.000Z","size":178,"stargazers_count":223,"open_issues_count":0,"forks_count":14,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-03-29T03:07:01.496Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/WebReflection.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-12-04T13:49:37.000Z","updated_at":"2025-02-04T23:53:35.000Z","dependencies_parsed_at":"2023-01-22T22:15:18.773Z","dependency_job_id":null,"html_url":"https://github.com/WebReflection/domdiff","commit_stats":null,"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebReflection%2Fdomdiff","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebReflection%2Fdomdiff/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebReflection%2Fdomdiff/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/WebReflection%2Fdomdiff/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/WebReflection","download_url":"https://codeload.github.com/WebReflection/domdiff/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247284948,"owners_count":20913704,"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-15T21:13:21.255Z","updated_at":"2025-04-05T04:09:10.872Z","avatar_url":"https://github.com/WebReflection.png","language":"JavaScript","readme":"# domdiff\n\n[![donate](https://img.shields.io/badge/$-donate-ff69b4.svg?maxAge=2592000\u0026style=flat)](https://github.com/WebReflection/donate) [![Coverage Status](https://coveralls.io/repos/github/WebReflection/domdiff/badge.svg?branch=master)](https://coveralls.io/github/WebReflection/domdiff?branch=master) [![Build Status](https://travis-ci.org/WebReflection/domdiff.svg?branch=master)](https://travis-ci.org/WebReflection/domdiff) [![License: ISC](https://img.shields.io/badge/License-ISC-yellow.svg)](https://opensource.org/licenses/ISC)\n\n\nA vDOM-less implementation of the [petit-dom](https://github.com/yelouafi/petit-dom) diffing logic, at the core of [hyperHTML](https://github.com/WebReflection/hyperHTML).\n\n\n### V2 breaking change\n\n  * the good old snabdom diff logic has been 100% replaced\n  * lists with `null` or `undefined` nodes are not allowed anymore\n\n\u003csup\u003e\u003csub\u003e... but I guess having null nodes in the equation was quite possibly a bad idea in the first place ...\u003c/sub\u003e\u003c/sup\u003e\n\n#### V2 Diffing Strategies:\n\n  * common prefixes\n  * common suffixes\n  * skip same lists\n  * add boundaries\n  * remove boundaries\n  * simple sub-sequences insertions and removals\n  * one to many and many to one replacements\n  * fast inverted list swap\n  * O(ND) algo with a limit of 50 attempts\n  * last fallback with a simplified Hunt Szymanski algorithm\n\nThe current goal is to have in about 1K the best DOM diffing library out there.\n\n#### V1 breaking change\n\nThe signature has moved from `parent, current[], future[], getNode(), beforeNode` to `parent, current[], future[], {before, compare(), node()}`.\n\n\n### Signature\n\n```js\nfutureNodes = domdiff(\n  parentNode,     // where changes happen\n  currentNodes,   // Array of current items/nodes\n  futureNodes,    // Array of future items/nodes (returned)\n  options         // optional object with one of the following properties\n                  //  before: domNode\n                  //  compare(generic, generic) =\u003e true if same generic\n                  //  node(generic) =\u003e Node\n);\n```\n\n\n### How to import it:\n\n  * via **CDN**, as global variable: `https://unpkg.com/domdiff`\n  * via **ESM**, as external module: `https://unpkg.com/domdiff/esm/index.js`\n  * via **CJS**: `const EventTarget = require('domdiff').default;` \u003csup\u003e\u003csub\u003e( or `require('domdiff/cjs').default` )\u003c/sub\u003e\u003c/sup\u003e\n  * via bundlers/transpilers: `import domdiff from 'domdiff';` \u003csup\u003e\u003csub\u003e( or `from 'domdiff/esm'` )\u003c/sub\u003e\u003c/sup\u003e\n\n\n### Example\n\n```js\nvar nodes = {\n  a: document.createTextNode('a'),\n  b: document.createTextNode('b'),\n  c: document.createTextNode('c')\n};\n\nvar parentNode = document.createElement('p');\nvar childNodes = [nodes.a, nodes.c];\nparentNode.append(...childNodes);\nparentNode.textContent;\n// \"ac\"\n\nchildNodes = domdiff(\n  parentNode,\n  childNodes,\n  [nodes.a, nodes.b, nodes.c]\n);\n\nparentNode.textContent;\n// \"abc\"\n```\n\n\n### Compatibility:\n\nEvery. JavaScript. Engine.\n\n\n### A `{node: (generic, info) =\u003e node}` callback for complex data\n\nThe optional `{node: (generic, info) =\u003e node}` is invoked per each operation on the DOM.\n\nThis can be useful to represent node through wrappers, whenever that is needed.\n\nThe passed `info` value can be:\n\n  * `1` when the item/node is being appended\n  * `0` when the item/node is being used as insert _before_ reference\n  * `-0` when the item/node is being used as insert _after_ reference\n  * `-1` when the item/node is being removed\n\n[Example](https://codepen.io/WebReflection/pen/bYJVPd?editors=0010)\n\n```js\nfunction node(item, i) {\n  // case removal or case after\n  if ((1 / i) \u003c 0) {\n    // case removal\n    if (i) {\n      // if the item has more than a node\n      // remove all other nodes at once\n      if (item.length \u003e 1) {\n        const range = document.createRange();\n        range.setStartBefore(item[1]);\n        range.setEndAfter(item[item.length - 1]);\n        range.deleteContents();\n      }\n      // return the first node to be removed\n      return item[0];\n    }\n    // case after\n    else {\n      return item[item.length - 1];\n    }\n  }\n  // case insert\n  else if (i) {\n    const fragment = document.createDocumentFragment();\n    fragment.append(...item);\n    return fragment;\n  }\n  // case before\n  else {\n    return item[0];\n  }\n}\n\nconst and = [document.createTextNode(' \u0026 ')];\n\nconst Bob = [\n  document.createTextNode('B'),\n  document.createTextNode('o'),\n  document.createTextNode('b')\n];\n\nconst Lucy = [\n  document.createTextNode('L'),\n  document.createTextNode('u'),\n  document.createTextNode('c'),\n  document.createTextNode('y')\n];\n\n// clean the body for demo purpose\ndocument.body.textContent = '';\nlet content = domdiff(\n  document.body,\n  [],\n  [Bob, and, Lucy],\n  {node}\n);\n\n// ... later on ...\ncontent = domdiff(\n  document.body,\n  content,\n  [Lucy, and, Bob],\n  {node}\n);\n\n// clean up\ndomdiff(\n  document.body,\n  content,\n  [],\n  {node}\n);\n\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebreflection%2Fdomdiff","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwebreflection%2Fdomdiff","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwebreflection%2Fdomdiff/lists"}