znerol / node-delta

Delta.js - A JavaScript diff and patch engine for DOM trees
http://znerol.github.com/node-delta/
MIT License
47 stars 11 forks source link

HTML5 support #4

Open johanneswilm opened 11 years ago

johanneswilm commented 11 years ago

node-delta currently only supports corretly formed XHTML code. With my example code (see below and discussion here https://github.com/znerol/node-delta/issues/3 ) I make it work with BR- and IMG-tags from pure HTML5, but it's relying on many uncertain factors (such as ther enot being any ">" inside the attributes. Also, it still spits out errors for example when   is found in the code.

/* Simple Delta.js for browsers. 
 * License: MIT
 * 
 * Compile by copying to lib directory of node-delta and running browserify THIS_FILENAME.js > OUTPUT_FILENAME.js
 * 
 * Provides:
 * 
 * delta.Diff(html-string-1, html-string-2):
 * OUTPUT - a diff as a string.
 * 
 * delta.Patch(html-string, diff)
 * OUTPUT - the html-string with the diff applied as a patch
 * 
 * delta.Unpatch(html-string,diff)
 * OUTPUT - the html-string with the diff removed as a patch
 * 
*/

// DIFF
var delta = {};

var diffcmd = require('./delta/diff');
var diffmod = require('./delta/diff-skelmatch-factory');
var docmod = require('./delta/doc-xml-factory');
var deltamod = require('./delta/delta-xml-factory');

var difffact = new diffmod.DiffSkelmatchFactory();
var docfact = new docmod.DocumentXMLFactory();
var deltafact = new deltamod.DeltaXMLFactory();

var htmlToXhtml = function (htmlString) {
        htmlString = htmlString.replace(/<br>/g, "<br />");
        htmlString = htmlString.replace(/(<img[^>]+)>/gm, "$1 />");
        return htmlString;
};

var xhtmlToHtml = function (xhtmlString) {
        xhtmlString = xhtmlString.replace(/<br \/>/g, "<br>");
        xhtmlString = xhtmlString.replace(/(<img[^\/]+)\//gm, "$1");
        return xhtmlString;
};

delta.Diff = function(origcontent, changedcontent) {
    var doc1 = docfact.loadOriginalDocument(htmlToXhtml(origcontent));
    var doc2 = docfact.loadInputDocument(changedcontent);

    var d = new diffcmd.Diff(difffact, docfact, deltafact);
    var deltadoc = d.diff(doc1, doc2);

    return deltafact.serializeDocument(deltadoc);
};

// PATCH 
var resolverProfile = require('./profiles/algo-resolve-xcc');
var docProfile = require('./profiles/doc-tree-xml');
var deltaProfile = require('./profiles/delta-tree-xml');
var patch = require('./delta/patch');

delta.Patch = function(document_content, patch_content) {
    var p = new patch.Patch(resolverProfile, docProfile, deltaProfile);
    var doc = docProfile.loadOriginalDocument(document_content);
    var fragadapter = docProfile.createFragmentAdapter(doc.type);
    var delta = deltaProfile.loadDocument(patch_content, fragadapter);

    p.patch(doc, delta);

return xhtmlToHtml(docProfile.serializeDocument(doc));
};

// UNPATCH

var contextdelta = require('./delta/contextdelta');

delta.Unpatch = function(document_content, unpatch_content) {

    var p = new patch.Patch(resolverProfile, docProfile, deltaProfile);
    var doc = docProfile.loadOriginalDocument(document_content);
    var fragadapter = docProfile.createFragmentAdapter(doc.type);
    var delta = deltaProfile.loadDocument(unpatch_content, fragadapter);
    var reverse_delta_detached = [];

    delta.detached.forEach(function(op) {
        reverse_delta_detached.push(new contextdelta.DetachedContextOperation(op.type, op.path, op.insert, op.remove, op.head, op.tail));
    });

    delta.detached = reverse_delta_detached;

    p.patch(doc, delta);

    return xhtmlToHtml(docProfile.serializeDocument(doc));
};

window.delta = delta;