start test suite for dubdiff engine
This commit is contained in:
parent
55a30797ec
commit
755143c0c3
@ -9,7 +9,8 @@
|
||||
"start": "npm run copy-css && webpack --progress --colors --watch",
|
||||
"serve": "node src/server/babel.index.js",
|
||||
"webpack-stats": "webpack --profile --json > stats.json",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
"test": "mocha --watch --compilers js:babel-register"
|
||||
|
||||
},
|
||||
"author": "",
|
||||
"license": "BSD-2-Clause",
|
||||
@ -39,7 +40,10 @@
|
||||
"babel-preset-es2015-native-modules": "^6.9.4",
|
||||
"babel-preset-node6": "^11.0.0",
|
||||
"babel-preset-react": "^6.3.13",
|
||||
"babel-register": "^6.18.0",
|
||||
"chai": "^3.5.0",
|
||||
"copyfiles": "^0.2.2",
|
||||
"mocha": "^3.2.0",
|
||||
"piping": "^1.0.0-rc.4",
|
||||
"webpack": "^2.1.0-beta.27"
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ import * as JsDiff from 'diff'
|
||||
// the diff would use a custom compare function that would disregard the spaces
|
||||
// alternately, the text could be split with the spaces included in the array and then compared with a
|
||||
// custom diff function that would treat the space elements as null/ignored
|
||||
|
||||
//the current mechanism for adding and removing spaces is fragile and broken
|
||||
export function plaintextDiff(original, final) {
|
||||
let arrOriginal = plaintextSplit(original)
|
||||
let arrFinal = plaintextSplit(final)
|
||||
@ -27,22 +29,29 @@ export function markdownDiff(original, final) {
|
||||
return diff
|
||||
}
|
||||
|
||||
|
||||
export function diffToLogString(diff) {
|
||||
// returns a string version of the diff, with "{+ ... +}" and "[- ... -]"
|
||||
// representing ins and del blocks
|
||||
export function diffToString(diff) {
|
||||
return diff.map(({added, removed, value}) => {
|
||||
let sym = added ? "+" : removed ? '-' : '/'
|
||||
return sym+value+sym
|
||||
})
|
||||
let start = added ? '{+' : removed ? '[-' : ''
|
||||
let end = added ? '+}' : removed ? '-]' : ''
|
||||
let string = value
|
||||
if (Array.isArray(value))
|
||||
string = value.join('')
|
||||
|
||||
return start+string+end
|
||||
}).join(' ')
|
||||
}
|
||||
|
||||
let plaintextSplit = text =>text.split(/[ ]|(\n)/)
|
||||
|
||||
function plaintextRestoreSpaces (diff) {
|
||||
return diff.map(({added, removed, value}) => ({
|
||||
added,
|
||||
removed,
|
||||
value:value.map((str, idx, arr) => (
|
||||
(str!='\n' && (idx<arr.length-1)) ? str+" " : str)
|
||||
).join('')
|
||||
)
|
||||
}))
|
||||
}
|
||||
|
||||
@ -79,7 +88,7 @@ function rewriteMarkdownDiff(diff) {
|
||||
function applyTransformationRule1(diff) {
|
||||
let transformedDiff = []
|
||||
|
||||
const B_ADD='added', B_REM='removed', B_SAME='same'
|
||||
const B_ADDED='added', B_REMOVED='removed', B_SAME='same'
|
||||
let previousBlockType = null
|
||||
let currentBlockType = null
|
||||
let previousBlockWasMultiline = false
|
||||
@ -90,13 +99,15 @@ function applyTransformationRule1(diff) {
|
||||
|
||||
previousBlockType = currentBlockType
|
||||
previousBlockWasMultiline = currentBlockIsMultiline
|
||||
currentBlockType = (currentBlock.added ? B_ADD : (currentBlock.removed ? B_REMOVED : B_SAME))
|
||||
currentBlockType = (currentBlock.added ? B_ADDED : (currentBlock.removed ? B_REMOVED : B_SAME))
|
||||
currentBlockIsMultiline = isMultilineDiffBlock(currentBlock)
|
||||
|
||||
//transform rule 1 applys when:
|
||||
// the previous block was a del and had multiple lines
|
||||
// the current block is an ins
|
||||
if (previousBlockType == B_REM && currentBlockType == B_INS && previousBlockWasMultiline) {
|
||||
if (previousBlockType == B_REMOVED && currentBlockType == B_ADDED && previousBlockWasMultiline) {
|
||||
console.log('trigger rule 1')
|
||||
|
||||
//split the first line from the current block
|
||||
let currentBlockSplit = splitMultilineDiffBlock(currentBlock)
|
||||
|
||||
@ -104,13 +115,14 @@ function applyTransformationRule1(diff) {
|
||||
let previousBlock = transformedDiff.pop()
|
||||
|
||||
//split the first line from the previous block
|
||||
let previousBlockSplit = splitMultilineDiffBlock(currentBlock)
|
||||
let previousBlockSplit = splitMultilineDiffBlock(previousBlock)
|
||||
|
||||
console.log({currentBlock, currentBlockSplit, previousBlock, previousBlockSplit})
|
||||
|
||||
//now add the blocks back, interleaving del and ins blocks
|
||||
for (let i=0; i<Math.max(previousBlockSplit.length, currentBlockSplit.length); i++) {
|
||||
if (i<previousBlockSplit.length)
|
||||
transformedDiff.push(previousBlockSplit[i])
|
||||
|
||||
if (i<currentBlockSplit.length)
|
||||
transformedDiff.push(currentBlockSplit[i])
|
||||
}
|
||||
@ -142,6 +154,7 @@ function applyTransformationRule2(diff) {
|
||||
|
||||
|
||||
/// ...
|
||||
/*
|
||||
transform.forEach(function(item) {
|
||||
//newlines are undecorated
|
||||
if (item.string == '\n') {
|
||||
@ -193,7 +206,7 @@ function applyTransformationRule2(diff) {
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
@ -213,23 +226,31 @@ function isMultilineDiffBlock({value}) {
|
||||
//if the diff block begins with a newline, the returned array will begin with an empty diff
|
||||
function splitMultilineDiffBlock({added, removed, value}) {
|
||||
//find the indices of the diff block that coorespond to newlines
|
||||
const splits = findIndicesOf(value, '\n')
|
||||
const splits = findIndicesOf(value, str => str=='\n')
|
||||
|
||||
splits.push(value.length)
|
||||
|
||||
//create a range from each index
|
||||
const ranges = splits.reduce(
|
||||
//the accumulator is a structure with the last index and the list of ranges
|
||||
//the ranges are a {start, end} structure
|
||||
({last, ranges}, i) => {i, ranges.concat([{start:last, end:i}])},
|
||||
({last, ranges}, i) => {
|
||||
ranges = ranges.concat([{start:last, end:i}])
|
||||
return {last:i, ranges}
|
||||
},
|
||||
//start with the zero index and an empty array
|
||||
{last: 0, ranges:[]}
|
||||
).ranges
|
||||
|
||||
|
||||
//map the ranges into blocks
|
||||
const blocks = ranges.map(
|
||||
//each block is the same as the given original block, but with the values split at newlines
|
||||
({start, end}) => {added, removed, value.slice(start, end)}
|
||||
({start, end}) => ({added, removed, value:value.slice(start, end)})
|
||||
)
|
||||
|
||||
console.log({value, splits, ranges, blocks})
|
||||
|
||||
return blocks
|
||||
}
|
||||
|
||||
|
48
test/dubdiffMarkdown.js
Normal file
48
test/dubdiffMarkdown.js
Normal file
@ -0,0 +1,48 @@
|
||||
/*eslint-env node, mocha */
|
||||
/*global expect */
|
||||
/*eslint no-console: 0*/
|
||||
'use strict';
|
||||
|
||||
import chai from 'chai'
|
||||
|
||||
import {markdownDiff, diffToString} from '../src/common/util/dubdiff'
|
||||
|
||||
let diff = (a,b) => diffToString(markdownDiff(a,b))
|
||||
|
||||
const expect = chai.expect
|
||||
|
||||
describe('dubdiff', () => {
|
||||
let db;
|
||||
|
||||
beforeEach(() => {
|
||||
});
|
||||
|
||||
it('plaintext diffs consecutive words', ()=>{
|
||||
expect(diff(
|
||||
'This is a smlb sentnce with no errors.',
|
||||
'This is a simple sentence with no errors.'
|
||||
)).to.equal('This is a [-smlb sentnce-] {+simple sentence+} with no errors.')
|
||||
})
|
||||
|
||||
it('plaintext diffs with word deletion', ()=>{
|
||||
expect(diff(
|
||||
'Gonna delete a word.',
|
||||
'Gonna delete word.'
|
||||
)).to.equal('Gonna delete [-a-] word.')
|
||||
})
|
||||
|
||||
it('plaintext diffs with word insertion', ()=>{
|
||||
expect(diff(
|
||||
'Gonna delete word.',
|
||||
'Gonna delete a word.'
|
||||
)).to.equal('Gonna delete {+a+} word.')
|
||||
})
|
||||
|
||||
it('reorganizes insertions after multiline deletions', ()=>{
|
||||
expect(diff(
|
||||
`# Title
|
||||
other`,
|
||||
`# Subtitle`
|
||||
)).to.equal('# [-Title-] {+Subtitle+}[-\nother-]')
|
||||
})
|
||||
})
|
63
test/dubdiffPlaintext.js
Normal file
63
test/dubdiffPlaintext.js
Normal file
@ -0,0 +1,63 @@
|
||||
/*eslint-env node, mocha */
|
||||
/*global expect */
|
||||
/*eslint no-console: 0*/
|
||||
'use strict';
|
||||
|
||||
import chai from 'chai'
|
||||
|
||||
import {plaintextDiff, diffToString} from '../src/common/util/dubdiff'
|
||||
|
||||
let diff = (a,b) => diffToString(plaintextDiff(a,b))
|
||||
|
||||
const expect = chai.expect
|
||||
|
||||
describe('dubdiff', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
});
|
||||
|
||||
it('diffs single words', ()=>{
|
||||
expect(diff(
|
||||
'This is a smlb sentence.',
|
||||
'This is a simple sentence.'
|
||||
)).to.equal('This is a [-smlb-] {+simple+} sentence.')
|
||||
})
|
||||
|
||||
it('diffs consecutive words', ()=>{
|
||||
expect(diff(
|
||||
'This is a smlb sentnce with no errors.',
|
||||
'This is a simple sentence with no errors.'
|
||||
)).to.equal('This is a [-smlb sentnce-] {+simple sentence+} with no errors.')
|
||||
})
|
||||
|
||||
it('diffs with word deletion', ()=>{
|
||||
expect(diff(
|
||||
'Gonna delete a word.',
|
||||
'Gonna delete word.'
|
||||
)).to.equal('Gonna delete [-a-] word.')
|
||||
})
|
||||
it('diffs with word insertion', ()=>{
|
||||
expect(diff(
|
||||
'Gonna delete word.',
|
||||
'Gonna delete a word.'
|
||||
)).to.equal('Gonna delete {+a+} word.')
|
||||
})
|
||||
it('diffs accross newline without weird spaces', () => {
|
||||
expect(diff(
|
||||
'This is a flawed\ncomment',
|
||||
'This is a corrected\nitem'
|
||||
)).to.equal('This is a [-flawed-] {+corrected+}\n[-comment-] {+item+}')
|
||||
})
|
||||
it('doesn\'t add spaces after newline', () => {
|
||||
expect(diff(
|
||||
'\nhere',
|
||||
'\nhere'
|
||||
)).to.equal('\nhere')
|
||||
})
|
||||
it('doesn\'t add spaces before newline', () => {
|
||||
expect(diff(
|
||||
'there\n',
|
||||
'there\n'
|
||||
)).to.equal('there\n')
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue
Block a user