Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@gwicke
Last active August 11, 2016 22:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gwicke/f012b257e74223055065fe23a359bdc8 to your computer and use it in GitHub Desktop.
Save gwicke/f012b257e74223055065fe23a359bdc8 to your computer and use it in GitHub Desktop.
'use strict';
var assert = require('assert');
/**
* Simple utility for full-document editing with the section API introduced in
* https://phabricator.wikimedia.org/T94890.
*/
/**
* Compute section changes from an array of original IDs & an array of
* modified nodes.
*
* @param {Array<string>} oldIds, the array of original section ids.
* @param {Array<object>} newNodes, objects with
* - {string} id: The id of the node. Absent for new and copy/pasted
* (including moved) content.
* - {boolean} modified, indicating whether this node's content was
* modified.
* - {string} value, the outerHTML of this section. Should exclude ID
* attributes for copy/pasted (duplicated) content, but can include the ids
* for moved content.
* @return {object} Object with changes to the document, ready to be sent to
* the REST section to wikitext transform API.
*/
function sectionDiff(oldIds, newNodes) {
var changes = {};
var oldIdx = 0;
var prevNode = {id: 'mw0', value: ''};
for (var n = 0; n < newNodes.length; n++) {
// New content
while (n < newNodes.length && !newNodes[n].id) {
prevNode.value += newNodes[n].value;
changes[prevNode.id] = prevNode.value;
n++;
}
// Modified sections
var newNode = newNodes[n];
if (newNode.modified) { changes[newNode.id] = newNode.value; }
// Deletions
while (oldIds[oldIdx] !== newNode.id && oldIdx < oldIds.length) {
changes[oldIds[oldIdx]] = '';
oldIdx++;
}
oldIdx++;
prevNode = newNode;
}
for (;oldIdx < oldIds.length; oldIdx++) { changes[oldIds[oldIdx]] = ''; }
return changes;
}
// Basic tests
var origIds = ['a','b','c','d','e','f'];
assert.deepEqual(sectionDiff(origIds, [{id:'a',value:'a'},{id:'b',value:'b'},{id:'c',value:'c'},{id:'d',value:'d'},{id:'e',value:'e'},{id:'f',value:'f'}]), {});
assert.deepEqual(sectionDiff(origIds, [{id:'b',value:'b'},{id:'c',value:'c'},{id:'d',value:'d'},{id:'e',value:'e'},{id:'f',value:'f'}]), {a:''});
assert.deepEqual(sectionDiff(origIds, [{id:'a',value:'a'},{id:'c',value:'c'},{id:'d',value:'d'},{id:'e',value:'e'},{id:'f',value:'f'}]), {'b':''});
assert.deepEqual(sectionDiff(origIds, []), {a:'',b:'',c:'',d:'',e:'',f:''});
assert.deepEqual(sectionDiff(origIds, [{value:'foo'},{id:'b',value:'b'},{id:'c',value:'c'},{id:'d',value:'d'},{id:'e',value:'e'},{id:'f',value:'f'}]), {mw0:'foo',a:''});
assert.deepEqual(sectionDiff(origIds, [{id:'a',value:'a'},{id:'b', modified: true, value: 'bar'},{id:'d', modified: true, value: 'deee'},{id:'e',value:'e'},{id:'f',value:'f'}]), {b:'bar',c:'',d:'deee'});
assert.deepEqual(sectionDiff(origIds, [{id:'a',value:'a'},{id:'b',value:'b'},{id:'c',value:'c'},{id:'d',value:'d'},{id:'e',value:'e'}]), {f:''});
assert.deepEqual(sectionDiff(origIds, [{value: 'foo'},{id:'a',value:'a'},{id:'b',value:'b'},{id:'c',value:'c'},{id:'d',value:'d'},{id:'e'}]), {'mw0':'foo',f: ''});
assert.deepEqual(sectionDiff(origIds, [{value: 'foo'},{id:'a',value:'a'},{id:'b',value:'b'},{id:'c',value:'c'},{id:'d',value:'d'},{id:'e',value:'e'}]), {'mw0':'foo',f: ''});
assert.deepEqual(sectionDiff(origIds, [{id:'a', value:'aa'}, {id: 'b', value:'b'}, {value: 'foo'}, {id:'e', value: 'e'}]), {'b':'bfoo',c: '', d:'', f:''});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment