Skip to content
This repository has been archived by the owner on Jul 30, 2020. It is now read-only.

Commit

Permalink
Add section diff utility for VE
Browse files Browse the repository at this point in the history
  • Loading branch information
gwicke committed Aug 24, 2016
1 parent 5d11ddd commit efa4c07
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 1 deletion.
3 changes: 2 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict';

module.exports = {
sections: require('./lib/sections')
sections: require('./lib/sections'),
sectionDiff: require('./lib/section_diff'),
};
53 changes: 53 additions & 0 deletions lib/section_diff.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'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;
}

module.exports = sectionDiff;
43 changes: 43 additions & 0 deletions test/section_diff.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use strict';

const assert = require('assert');
const sectionDiff = require('../').sectionDiff;

const origIds = ['a','b','c','d','e','f'];

// Basic tests
module.exports = {
'Section diff': {
'No change': () => {
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'}]), {});
},
'Single deleted section': () => {
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:''});
},
'Single deleted section, middle': () => {
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':''});
},
'Delete everything': () => {
assert.deepEqual(sectionDiff(origIds, []), {a:'',b:'',c:'',d:'',e:'',f:''});
},
'Replace first section': () => {
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:''});
},
'Edit + section replacement': () => {
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'});
},
'Delete last section': () => {
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:''});
},
'Prepend & delete last section': () => {
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: ''});
},
'Reorder sections 1': () => {
assert.deepEqual(sectionDiff(origIds, [{id:'a', value:'aa'}, {id: 'b',
value:'b'}, {value: 'foo'}, {id:'e', value: 'e'}]), {'b':'bfoo',c:
'', d:'', f:''});
}
}
};

0 comments on commit efa4c07

Please sign in to comment.