Skip to content

WebReflection/domdiff

Repository files navigation

domdiff

donateCoverage StatusBuild StatusLicense: ISC

A vDOM-less implementation of the petit-dom diffing logic, at the core of hyperHTML.

V2 breaking change

  • the good old snabdom diff logic has been 100% replaced
  • lists with null or undefined nodes are not allowed anymore

... but I guess having null nodes in the equation was quite possibly a bad idea in the first place ...

V2 Diffing Strategies:

  • common prefixes
  • common suffixes
  • skip same lists
  • add boundaries
  • remove boundaries
  • simple sub-sequences insertions and removals
  • one to many and many to one replacements
  • fast inverted list swap
  • O(ND) algo with a limit of 50 attempts
  • last fallback with a simplified Hunt Szymanski algorithm

The current goal is to have in about 1K the best DOM diffing library out there.

V1 breaking change

The signature has moved from parent, current[], future[], getNode(), beforeNode to parent, current[], future[],{before, compare(), node()}.

Signature

futureNodes=domdiff(parentNode,// where changes happencurrentNodes,// Array of current items/nodesfutureNodes,// Array of future items/nodes (returned)options// optional object with one of the following properties// before: domNode// compare(generic, generic) => true if same generic// node(generic) => Node);

How to import it:

  • via CDN, as global variable: https://unpkg.com/domdiff
  • via ESM, as external module: https://unpkg.com/domdiff/esm/index.js
  • via CJS: const EventTarget = require('domdiff').default;( or require('domdiff/cjs').default )
  • via bundlers/transpilers: import domdiff from 'domdiff';( or from 'domdiff/esm' )

Example

varnodes={a: document.createTextNode('a'),b: document.createTextNode('b'),c: document.createTextNode('c')};varparentNode=document.createElement('p');varchildNodes=[nodes.a,nodes.c];parentNode.append(...childNodes);parentNode.textContent;// "ac"childNodes=domdiff(parentNode,childNodes,[nodes.a,nodes.b,nodes.c]);parentNode.textContent;// "abc"

Compatibility:

Every. JavaScript. Engine.

A {node: (generic, info) => node} callback for complex data

The optional {node: (generic, info) => node} is invoked per each operation on the DOM.

This can be useful to represent node through wrappers, whenever that is needed.

The passed info value can be:

  • 1 when the item/node is being appended
  • 0 when the item/node is being used as insert before reference
  • -0 when the item/node is being used as insert after reference
  • -1 when the item/node is being removed

Example

functionnode(item,i){// case removal or case afterif((1/i)<0){// case removalif(i){// if the item has more than a node// remove all other nodes at onceif(item.length>1){constrange=document.createRange();range.setStartBefore(item[1]);range.setEndAfter(item[item.length-1]);range.deleteContents();}// return the first node to be removedreturnitem[0];}// case afterelse{returnitem[item.length-1];}}// case insertelseif(i){constfragment=document.createDocumentFragment();fragment.append(...item);returnfragment;}// case beforeelse{returnitem[0];}}constand=[document.createTextNode(' & ')];constBob=[document.createTextNode('B'),document.createTextNode('o'),document.createTextNode('b')];constLucy=[document.createTextNode('L'),document.createTextNode('u'),document.createTextNode('c'),document.createTextNode('y')];// clean the body for demo purposedocument.body.textContent='';letcontent=domdiff(document.body,[],[Bob,and,Lucy],{node});// ... later on ...content=domdiff(document.body,content,[Lucy,and,Bob],{node});// clean updomdiff(document.body,content,[],{node});

About

Diffing the DOM without virtual DOM

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •