diff --git a/.babelrc b/.babelrc
deleted file mode 100644
index f91ebace..00000000
--- a/.babelrc
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "presets": [
- "env"
- ],
- "plugins": [
- "transform-object-rest-spread"
- ]
-}
diff --git a/.eslintignore b/.eslintignore
deleted file mode 100644
index e13c8ee0..00000000
--- a/.eslintignore
+++ /dev/null
@@ -1,3 +0,0 @@
-node_modules
-build
-dist
\ No newline at end of file
diff --git a/.eslintrc b/.eslintrc
index a17c522a..52926dc0 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,24 +1,3 @@
{
- "extends": ["standard"],
- "plugins": ["standard"],
- "rules": {
- "semi": [2, "always"],
- "space-before-function-paren": [2, "never"],
- "max-len": [2, 80, 2],
- "camelcase": [2, { "properties": "always" }],
- "linebreak-style": [2, "unix"],
- "new-cap": [2, { "newIsCap": true, "capIsNew": true }],
- "arrow-body-style": [2, "as-needed"],
- "arrow-parens": [2, "as-needed"],
- "prefer-arrow-callback": 0,
- "prefer-template": 0,
-
- "no-var": 2,
- "no-undef": 2,
- "no-param-reassign": 2,
- "comma-dangle": [2, "always-multiline"]
- },
- "env": {
- "node": true
- }
+ "extends": "plugin:bpmn-io/recommended"
}
diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml
new file mode 100644
index 00000000..7b95f6fd
--- /dev/null
+++ b/.github/workflows/CI.yml
@@ -0,0 +1,23 @@
+name: CI
+on: [ push, pull_request ]
+jobs:
+ Build:
+ runs-on: ${{ matrix.os }}
+
+ strategy:
+ matrix:
+ os: [ubuntu-latest]
+ node-version: [ 20 ]
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Use Node.js ${{matrix.node-version}}
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{matrix.node-version}}
+ cache: 'npm'
+ - name: Install dependencies
+ run: npm ci
+ - name: Build
+ run: npm run all
diff --git a/.gitignore b/.gitignore
index 64a41388..1fd04daf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,20 +1,3 @@
-node_modules
-lib-cov
-*.seed
-*.log
-*.csv
-*.dat
-*.out
-*.pid
-*.gz
-.DS_Store
-
-pids
-logs
-results
+node_modules
coverage
-.nyc_output
-dist
-build
-
-npm-debug.log
+.nyc_output
diff --git a/.npmignore b/.npmignore
deleted file mode 100644
index ce3eadf8..00000000
--- a/.npmignore
+++ /dev/null
@@ -1,8 +0,0 @@
-!dist
-test
-docs
-.editorconfig
-.eslintignore
-.eslintrc
-rollup.config.js
-.travis.yml
\ No newline at end of file
diff --git a/.npmrc b/.npmrc
deleted file mode 100644
index 9cf94950..00000000
--- a/.npmrc
+++ /dev/null
@@ -1 +0,0 @@
-package-lock=false
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 21fdee13..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-language: node_js
-node_js:
- - "node"
-
-script:
- - "npm run all"
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 00000000..314071a6
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,16 @@
+# Changelog
+
+All notable changes to [diffpatch](https://github.com/bpmn-io/diffpatch) are documented here. We use [semantic versioning](http://semver.org/) for releases.
+
+## Unreleased
+
+___Note:__ Yet to be released changes appear here._
+
+* `CHORE`: make ESM only module
+* `CHORE`: move library to `lib`
+* `CHORE`: dependency bumps
+* `CHORE`: drop `formatters` main export
+
+## ...
+
+See `git log` for older updates.
diff --git a/README.md b/README.md
index ff55e167..5afc89a4 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
# diffpatch
-[](http://travis-ci.com/bpmn-io/diffpatch)
+[](https://github.com/bpmn-io/diffpatch/actions/workflows/CI.yml)
Diff and patch JavaScript objects.
@@ -257,4 +257,4 @@ This library is a fork of [jsondiffpatch](https://github.com/benjamine/jsondiffp
## License
-MIT
\ No newline at end of file
+MIT
diff --git a/bin/diffpatch b/bin/diffpatch
new file mode 100755
index 00000000..544eb35f
--- /dev/null
+++ b/bin/diffpatch
@@ -0,0 +1,23 @@
+#!/usr/bin/env node
+
+/* eslint-env node */
+
+import { DiffPatcher } from '../lib/index.js';
+import ConsoleFormatter from '../lib/formatters/console.js';
+
+import fs from 'node:fs';
+
+const fileLeft = process.argv[2];
+const fileRight = process.argv[3];
+
+if (!fileLeft || !fileRight) {
+ console.log('\n USAGE: diffpatch left.json right.json');
+ process.exit(1);
+}
+
+const left = JSON.parse(fs.readFileSync(fileLeft));
+const right = JSON.parse(fs.readFileSync(fileRight));
+
+const delta = new DiffPatcher().diff(left, right);
+
+console.log(new ConsoleFormatter().format(delta));
diff --git a/bin/jsondiffpatch b/bin/jsondiffpatch
deleted file mode 100755
index 1c9fb205..00000000
--- a/bin/jsondiffpatch
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env node
-
-const jsondiffpatch = require('..');
-
-const fs = require('fs');
-
-const fileLeft = process.argv[2];
-const fileRight = process.argv[3];
-
-if (!fileLeft || !fileRight) {
- console.log('\n USAGE: jsondiffpatch left.json right.json');
- return;
-}
-
-const left = JSON.parse(fs.readFileSync(fileLeft));
-const right = JSON.parse(fs.readFileSync(fileRight));
-
-const delta = jsondiffpatch.diff(left, right);
-jsondiffpatch.console.log(delta);
diff --git a/src/clone.js b/lib/clone.js
similarity index 100%
rename from src/clone.js
rename to lib/clone.js
diff --git a/src/contexts/context.js b/lib/contexts/context.js
similarity index 93%
rename from src/contexts/context.js
rename to lib/contexts/context.js
index f31abd2d..4a312ee7 100644
--- a/src/contexts/context.js
+++ b/lib/contexts/context.js
@@ -1,4 +1,4 @@
-import Pipe from '../pipe';
+import Pipe from '../pipe.js';
export default class Context {
setResult(result) {
@@ -32,7 +32,7 @@ export default class Context {
child.root = this.root || this;
child.options = child.options || this.options;
if (!this.children) {
- this.children = [child];
+ this.children = [ child ];
this.nextAfterChildren = this.next || null;
this.next = child;
} else {
diff --git a/src/contexts/diff.js b/lib/contexts/diff.js
similarity index 89%
rename from src/contexts/diff.js
rename to lib/contexts/diff.js
index 5cd82435..e6e01a01 100644
--- a/src/contexts/diff.js
+++ b/lib/contexts/diff.js
@@ -1,5 +1,5 @@
-import Context from './context';
-import defaultClone from '../clone';
+import Context from './context.js';
+import defaultClone from '../clone.js';
class DiffContext extends Context {
constructor(left, right) {
diff --git a/src/contexts/patch.js b/lib/contexts/patch.js
similarity index 83%
rename from src/contexts/patch.js
rename to lib/contexts/patch.js
index f6d55722..d4594d0f 100644
--- a/src/contexts/patch.js
+++ b/lib/contexts/patch.js
@@ -1,4 +1,4 @@
-import Context from './context';
+import Context from './context.js';
class PatchContext extends Context {
constructor(left, delta) {
diff --git a/src/contexts/reverse.js b/lib/contexts/reverse.js
similarity index 82%
rename from src/contexts/reverse.js
rename to lib/contexts/reverse.js
index d49d6cb9..a5ae1942 100644
--- a/src/contexts/reverse.js
+++ b/lib/contexts/reverse.js
@@ -1,4 +1,4 @@
-import Context from './context';
+import Context from './context.js';
class ReverseContext extends Context {
constructor(delta) {
diff --git a/src/date-reviver.js b/lib/date-reviver.js
similarity index 100%
rename from src/date-reviver.js
rename to lib/date-reviver.js
diff --git a/src/diffpatcher.js b/lib/diffpatcher.js
similarity index 74%
rename from src/diffpatcher.js
rename to lib/diffpatcher.js
index b8977b81..8eb14a73 100644
--- a/src/diffpatcher.js
+++ b/lib/diffpatcher.js
@@ -1,17 +1,17 @@
-import Processor from './processor';
-import Pipe from './pipe';
-import DiffContext from './contexts/diff';
-import PatchContext from './contexts/patch';
-import ReverseContext from './contexts/reverse';
-import clone from './clone';
+import Processor from './processor.js';
+import Pipe from './pipe.js';
+import DiffContext from './contexts/diff.js';
+import PatchContext from './contexts/patch.js';
+import ReverseContext from './contexts/reverse.js';
+import clone from './clone.js';
-import * as trivial from './filters/trivial';
-import * as nested from './filters/nested';
-import * as arrays from './filters/arrays';
-import * as dates from './filters/dates';
-import * as texts from './filters/texts';
+import * as trivial from './filters/trivial.js';
+import * as nested from './filters/nested.js';
+import * as arrays from './filters/arrays.js';
+import * as dates from './filters/dates.js';
+import * as texts from './filters/texts.js';
-class DiffPatcher {
+export default class DiffPatcher {
constructor(options) {
this.processor = new Processor(options);
this.processor.pipe(
@@ -76,5 +76,3 @@ class DiffPatcher {
return clone(value);
}
}
-
-export default DiffPatcher;
diff --git a/src/filters/arrays.js b/lib/filters/arrays.js
similarity index 96%
rename from src/filters/arrays.js
rename to lib/filters/arrays.js
index b7c5f590..c929cfbe 100644
--- a/src/filters/arrays.js
+++ b/lib/filters/arrays.js
@@ -1,8 +1,8 @@
-import DiffContext from '../contexts/diff';
-import PatchContext from '../contexts/patch';
-import ReverseContext from '../contexts/reverse';
+import DiffContext from '../contexts/diff.js';
+import PatchContext from '../contexts/patch.js';
+import ReverseContext from '../contexts/reverse.js';
-import lcs from './lcs';
+import lcs from './lcs.js';
const ARRAY_MOVE = 3;
@@ -45,6 +45,7 @@ function matchItems(array1, array2, index1, index2, context) {
}
let objectHash = context.objectHash;
if (!objectHash) {
+
// no way to match objects was provided, try match by position
return context.matchByPosition && index1 === index2;
}
@@ -123,6 +124,7 @@ export const diffFilter = function arraysDiffFilter(context) {
context.push(child, index);
commonHead++;
}
+
// separate common tail
while (
commonTail + commonHead < len1 &&
@@ -144,31 +146,35 @@ export const diffFilter = function arraysDiffFilter(context) {
let result;
if (commonHead + commonTail === len1) {
if (len1 === len2) {
+
// arrays are identical
context.setResult(undefined).exit();
return;
}
+
// trivial case, a block (1 or more consecutive items) was added
result = result || {
_t: 'a',
};
for (index = commonHead; index < len2 - commonTail; index++) {
- result[index] = [array2[index]];
+ result[index] = [ array2[index] ];
}
context.setResult(result).exit();
return;
}
if (commonHead + commonTail === len2) {
+
// trivial case, a block (1 or more consecutive items) was removed
result = result || {
_t: 'a',
};
for (index = commonHead; index < len1 - commonTail; index++) {
- result[`_${index}`] = [array1[index], 0, 0];
+ result[`_${index}`] = [ array1[index], 0, 0 ];
}
context.setResult(result).exit();
return;
}
+
// reset hash cache
delete matchContext.hashCache1;
delete matchContext.hashCache2;
@@ -183,8 +189,9 @@ export const diffFilter = function arraysDiffFilter(context) {
};
for (index = commonHead; index < len1 - commonTail; index++) {
if (arrayIndexOf(seq.indices1, index - commonHead) < 0) {
+
// removed
- result[`_${index}`] = [array1[index], 0, 0];
+ result[`_${index}`] = [ array1[index], 0, 0 ];
removedItems.push(index);
}
}
@@ -210,6 +217,7 @@ export const diffFilter = function arraysDiffFilter(context) {
for (index = commonHead; index < len2 - commonTail; index++) {
let indexOnArray2 = arrayIndexOf(seq.indices2, index - commonHead);
if (indexOnArray2 < 0) {
+
// added, try to match with a removed item and register as position move
let isMove = false;
if (detectMove && removedItemsLength > 0) {
@@ -228,9 +236,11 @@ export const diffFilter = function arraysDiffFilter(context) {
matchContext
)
) {
+
// store position move as: [originalValue, newPosition, ARRAY_MOVE]
result[`_${index1}`].splice(1, 2, index, ARRAY_MOVE);
if (!includeValueOnMove) {
+
// don't include moved value on diff, to save bytes
result[`_${index1}`][0] = '';
}
@@ -248,10 +258,12 @@ export const diffFilter = function arraysDiffFilter(context) {
}
}
if (!isMove) {
+
// added
- result[index] = [array2[index]];
+ result[index] = [ array2[index] ];
}
} else {
+
// match, do inner diff
index1 = seq.indices1[indexOnArray2] + commonHead;
index2 = seq.indices2[indexOnArray2] + commonHead;
@@ -293,23 +305,26 @@ export const patchFilter = function nestedPatchFilter(context) {
for (index in delta) {
if (index !== '_t') {
if (index[0] === '_') {
+
// removed item from original array
if (delta[index][2] === 0 || delta[index][2] === ARRAY_MOVE) {
toRemove.push(parseInt(index.slice(1), 10));
} else {
throw new Error(
- `only removal or move can be applied at original array indices,` +
+ 'only removal or move can be applied at original array indices,' +
` invalid diff type: ${delta[index][2]}`
);
}
} else {
if (delta[index].length === 1) {
+
// added item at new array
toInsert.push({
index: parseInt(index, 10),
value: delta[index][0],
});
} else {
+
// modified item at new array
toModify.push({
index: parseInt(index, 10),
@@ -327,6 +342,7 @@ export const patchFilter = function nestedPatchFilter(context) {
let indexDiff = delta[`_${index1}`];
let removedValue = array.splice(index1, 1)[0];
if (indexDiff[2] === ARRAY_MOVE) {
+
// reinsert later
toInsert.push({
index: indexDiff[1],
@@ -366,7 +382,7 @@ export const patchFilter = function nestedPatchFilter(context) {
patchFilter.filterName = 'arrays';
export const collectChildrenPatchFilter = function collectChildrenPatchFilter(
- context
+ context
) {
if (!context || !context.children) {
return;
diff --git a/src/filters/dates.js b/lib/filters/dates.js
similarity index 68%
rename from src/filters/dates.js
rename to lib/filters/dates.js
index fc1f8aba..66d8650b 100644
--- a/src/filters/dates.js
+++ b/lib/filters/dates.js
@@ -2,16 +2,16 @@ export const diffFilter = function datesDiffFilter(context) {
if (context.left instanceof Date) {
if (context.right instanceof Date) {
if (context.left.getTime() !== context.right.getTime()) {
- context.setResult([context.left, context.right]);
+ context.setResult([ context.left, context.right ]);
} else {
context.setResult(undefined);
}
} else {
- context.setResult([context.left, context.right]);
+ context.setResult([ context.left, context.right ]);
}
context.exit();
} else if (context.right instanceof Date) {
- context.setResult([context.left, context.right]).exit();
+ context.setResult([ context.left, context.right ]).exit();
}
};
diffFilter.filterName = 'dates';
diff --git a/src/filters/lcs.js b/lib/filters/lcs.js
similarity index 97%
rename from src/filters/lcs.js
rename to lib/filters/lcs.js
index 857275a1..720fedd9 100644
--- a/src/filters/lcs.js
+++ b/lib/filters/lcs.js
@@ -16,14 +16,15 @@ const lengthMatrix = function(array1, array2, match, context) {
let x, y;
// initialize empty matrix of len1+1 x len2+1
- let matrix = [len1 + 1];
+ let matrix = [ len1 + 1 ];
for (x = 0; x < len1 + 1; x++) {
- matrix[x] = [len2 + 1];
+ matrix[x] = [ len2 + 1 ];
for (y = 0; y < len2 + 1; y++) {
matrix[x][y] = 0;
}
}
matrix.match = match;
+
// save sequence lengths for each coordinate
for (x = 1; x < len1 + 1; x++) {
for (y = 1; y < len2 + 1; y++) {
diff --git a/src/filters/nested.js b/lib/filters/nested.js
similarity index 95%
rename from src/filters/nested.js
rename to lib/filters/nested.js
index e478f23f..7553ebb9 100644
--- a/src/filters/nested.js
+++ b/lib/filters/nested.js
@@ -1,6 +1,6 @@
-import DiffContext from '../contexts/diff';
-import PatchContext from '../contexts/patch';
-import ReverseContext from '../contexts/reverse';
+import DiffContext from '../contexts/diff.js';
+import PatchContext from '../contexts/patch.js';
+import ReverseContext from '../contexts/reverse.js';
export function collectChildrenDiffFilter(context) {
if (!context || !context.children) {
@@ -81,7 +81,7 @@ export const patchFilter = function nestedPatchFilter(context) {
patchFilter.filterName = 'objects';
export const collectChildrenPatchFilter = function collectChildrenPatchFilter(
- context
+ context
) {
if (!context || !context.children) {
return;
diff --git a/src/filters/texts.js b/lib/filters/texts.js
similarity index 78%
rename from src/filters/texts.js
rename to lib/filters/texts.js
index cd3c085c..72ac8b7e 100644
--- a/src/filters/texts.js
+++ b/lib/filters/texts.js
@@ -1,29 +1,26 @@
-/* global diff_match_patch */
-import dmp from 'diff-match-patch';
-
let TEXT_DIFF = 2;
let DEFAULT_MIN_LENGTH = 60;
let cachedDiffPatch = null;
-let getDiffMatchPatch = function(required) {
+let getDiffMatchPatch = function(options = {}, required) {
+
/* jshint camelcase: false */
if (!cachedDiffPatch) {
let instance;
- /* eslint-disable camelcase, new-cap */
- if (typeof diff_match_patch !== 'undefined') {
- // already loaded, probably a browser
- instance =
- typeof diff_match_patch === 'function'
- ? new diff_match_patch()
- : new diff_match_patch.diff_match_patch();
- } else if (dmp) {
- try {
- instance = dmp && new dmp();
- } catch (err) {
- instance = null;
- }
+
+ const {
+ textDiff: {
+ diffMatchPatch
+ } = {}
+ } = options;
+
+ try {
+ instance = diffMatchPatch && new diffMatchPatch();
+ } catch (err) {
+ instance = null;
}
+
/* eslint-enable camelcase, new-cap */
if (!instance) {
if (!required) {
@@ -66,19 +63,21 @@ export const diffFilter = function textsDiffFilter(context) {
context.options.textDiff.minLength) ||
DEFAULT_MIN_LENGTH;
if (context.left.length < minLength || context.right.length < minLength) {
- context.setResult([context.left, context.right]).exit();
+ context.setResult([ context.left, context.right ]).exit();
return;
}
+
// large text, try to use a text-diff algorithm
- let diffMatchPatch = getDiffMatchPatch();
+ let diffMatchPatch = getDiffMatchPatch(context.options);
if (!diffMatchPatch) {
+
// diff-match-patch library not available,
// fallback to regular string replace
- context.setResult([context.left, context.right]).exit();
+ context.setResult([ context.left, context.right ]).exit();
return;
}
let diff = diffMatchPatch.diff;
- context.setResult([diff(context.left, context.right), 0, TEXT_DIFF]).exit();
+ context.setResult([ diff(context.left, context.right), 0, TEXT_DIFF ]).exit();
};
diffFilter.filterName = 'texts';
@@ -91,7 +90,7 @@ export const patchFilter = function textsPatchFilter(context) {
}
// text-diff, use a text-patch algorithm
- const patch = getDiffMatchPatch(true).patch;
+ const patch = getDiffMatchPatch(context.options, true).patch;
context.setResult(patch(context.left, context.delta[0])).exit();
};
patchFilter.filterName = 'texts';
@@ -127,6 +126,7 @@ const textDeltaReverse = function(delta) {
} else if (lineStart === '+') {
lines[i] = '-' + lines[i].slice(1);
if (lines[i - 1].slice(0, 1) === '+') {
+
// swap lines to keep default order (-+)
lineTmp = lines[i];
lines[i] = lines[i - 1];
@@ -148,6 +148,6 @@ export const reverseFilter = function textsReverseFilter(context) {
}
// text-diff, use a text-diff algorithm
- context.setResult([textDeltaReverse(context.delta[0]), 0, TEXT_DIFF]).exit();
+ context.setResult([ textDeltaReverse(context.delta[0]), 0, TEXT_DIFF ]).exit();
};
reverseFilter.filterName = 'texts';
diff --git a/src/filters/trivial.js b/lib/filters/trivial.js
similarity index 81%
rename from src/filters/trivial.js
rename to lib/filters/trivial.js
index c4ee1204..ca1f32a6 100644
--- a/src/filters/trivial.js
+++ b/lib/filters/trivial.js
@@ -14,11 +14,11 @@ export const diffFilter = function trivialMatchesDiffFilter(context) {
if (typeof context.right === 'function') {
throw new Error('functions are not supported');
}
- context.setResult([context.right]).exit();
+ context.setResult([ context.right ]).exit();
return;
}
if (typeof context.right === 'undefined') {
- context.setResult([context.left, 0, 0]).exit();
+ context.setResult([ context.left, 0, 0 ]).exit();
return;
}
if (
@@ -30,11 +30,11 @@ export const diffFilter = function trivialMatchesDiffFilter(context) {
context.leftType = context.left === null ? 'null' : typeof context.left;
context.rightType = context.right === null ? 'null' : typeof context.right;
if (context.leftType !== context.rightType) {
- context.setResult([context.left, context.right]).exit();
+ context.setResult([ context.left, context.right ]).exit();
return;
}
if (context.leftType === 'boolean' || context.leftType === 'number') {
- context.setResult([context.left, context.right]).exit();
+ context.setResult([ context.left, context.right ]).exit();
return;
}
if (context.leftType === 'object') {
@@ -44,17 +44,17 @@ export const diffFilter = function trivialMatchesDiffFilter(context) {
context.rightIsArray = isArray(context.right);
}
if (context.leftIsArray !== context.rightIsArray) {
- context.setResult([context.left, context.right]).exit();
+ context.setResult([ context.left, context.right ]).exit();
return;
}
if (context.left instanceof RegExp) {
if (context.right instanceof RegExp) {
context
- .setResult([context.left.toString(), context.right.toString()])
+ .setResult([ context.left.toString(), context.right.toString() ])
.exit();
} else {
- context.setResult([context.left, context.right]).exit();
+ context.setResult([ context.left, context.right ]).exit();
}
}
};
@@ -100,15 +100,15 @@ export const reverseFilter = function trivialReferseFilter(context) {
return;
}
if (context.delta.length === 1) {
- context.setResult([context.delta[0], 0, 0]).exit();
+ context.setResult([ context.delta[0], 0, 0 ]).exit();
return;
}
if (context.delta.length === 2) {
- context.setResult([context.delta[1], context.delta[0]]).exit();
+ context.setResult([ context.delta[1], context.delta[0] ]).exit();
return;
}
if (context.delta.length === 3 && context.delta[2] === 0) {
- context.setResult([context.delta[0]]).exit();
+ context.setResult([ context.delta[0] ]).exit();
}
};
reverseFilter.filterName = 'trivial';
diff --git a/src/formatters/annotated.js b/lib/formatters/annotated.js
similarity index 95%
rename from src/formatters/annotated.js
rename to lib/formatters/annotated.js
index 88835486..31007df3 100644
--- a/src/formatters/annotated.js
+++ b/lib/formatters/annotated.js
@@ -1,4 +1,4 @@
-import BaseFormatter from './base';
+import BaseFormatter from './base.js';
export default class AnnotatedFormatter extends BaseFormatter {
constructor() {
@@ -38,7 +38,7 @@ export default class AnnotatedFormatter extends BaseFormatter {
for (let i = 0, l = lines.length; i < l; i++) {
const line = lines[i];
context.out(
- `
` +
+ '
' +
`
${
line.location.line
}${
@@ -113,6 +113,7 @@ export default class AnnotatedFormatter extends BaseFormatter {
format_movedestination() {}
format_node(context, delta, left) {
+
// recurse
this.formatDeltaChildren(context, delta, left);
}
@@ -156,7 +157,7 @@ const deltaAnnotations = {
},
moved(delta, left, key, leftKey) {
return (
- `move from ` +
+ 'move from ' +
`index ${leftKey} to index ${delta[1]}`
);
@@ -170,7 +171,7 @@ const deltaAnnotations = {
: ` at property ${wrapPropertyName(leftKey)}`;
return (
`text diff${location}, format is a variation of Unidiff`
+ 'p/google-diff-match-patch/wiki/Unidiff">a variation of Unidiff'
);
},
};
@@ -183,6 +184,7 @@ const formatAnyChange = function(context, delta) {
annotator.apply(annotator, Array.prototype.slice.call(arguments, 1));
let json = JSON.stringify(delta, null, 2);
if (deltaType === 'textdiff') {
+
// split text diffs lines
json = json.split('\\n').join('\\n"+\n "');
}
diff --git a/src/formatters/base.js b/lib/formatters/base.js
similarity index 99%
rename from src/formatters/base.js
rename to lib/formatters/base.js
index 99e9f6d3..ea5d8ca5 100644
--- a/src/formatters/base.js
+++ b/lib/formatters/base.js
@@ -107,6 +107,8 @@ class BaseFormatter {
movedFrom
);
if (typeof console !== 'undefined' && console.error) {
+
+ /* global console */
console.error(err.stack);
}
}
@@ -150,6 +152,7 @@ class BaseFormatter {
}
}
}
+
// look for move destinations
for (name in delta) {
if (Object.prototype.hasOwnProperty.call(delta, name)) {
diff --git a/src/formatters/console.js b/lib/formatters/console.js
similarity index 91%
rename from src/formatters/console.js
rename to lib/formatters/console.js
index 237ab15a..32848457 100644
--- a/src/formatters/console.js
+++ b/lib/formatters/console.js
@@ -1,9 +1,9 @@
-import chalk from 'chalk';
-import BaseFormatter from './base';
+import picocolors from 'picocolors';
+import BaseFormatter from './base.js';
-function chalkColor(name) {
+function color(name) {
return (
- (chalk && chalk[name]) ||
+ (picocolors && picocolors[name]) ||
function(...args) {
return args;
}
@@ -11,13 +11,13 @@ function chalkColor(name) {
}
let colors = {
- added: chalkColor('green'),
- deleted: chalkColor('red'),
- movedestination: chalkColor('gray'),
- moved: chalkColor('yellow'),
- unchanged: chalkColor('gray'),
- error: chalkColor('white.bgRed'),
- textDiffLine: chalkColor('gray'),
+ added: color('green'),
+ deleted: color('red'),
+ movedestination: color('gray'),
+ moved: color('yellow'),
+ unchanged: color('gray'),
+ error: text => color('white')(color('bgRed')(text)),
+ textDiffLine: color('gray'),
};
export default class ConsoleFormatter extends BaseFormatter {
@@ -147,6 +147,7 @@ export default class ConsoleFormatter extends BaseFormatter {
}
format_node(context, delta, left) {
+
// recurse
this.formatDeltaChildren(context, delta, left);
}
diff --git a/src/formatters/html.js b/lib/formatters/html.js
similarity index 95%
rename from src/formatters/html.js
rename to lib/formatters/html.js
index 0770f68a..6d42864f 100644
--- a/src/formatters/html.js
+++ b/lib/formatters/html.js
@@ -1,4 +1,6 @@
-import BaseFormatter from './base';
+/* eslint-env browser */
+
+import BaseFormatter from './base.js';
export default class HtmlFormatter extends BaseFormatter {
typeFormattterErrorFormatter(context, err) {
@@ -15,7 +17,7 @@ export default class HtmlFormatter extends BaseFormatter {
for (let i = 0, l = lines.length; i < l; i++) {
let line = lines[i];
context.out(
- `` +
+ '
' +
`${
line.location.line
}${
@@ -28,7 +30,6 @@ export default class HtmlFormatter extends BaseFormatter {
pieceIndex < piecesLength;
pieceIndex++
) {
- /* global decodeURI */
let piece = pieces[pieceIndex];
context.out(
`${htmlEscape(
@@ -52,7 +53,7 @@ export default class HtmlFormatter extends BaseFormatter {
context.out(
`
${
context.hasArrows
- ? ``
: ''
}`
@@ -95,6 +96,7 @@ export default class HtmlFormatter extends BaseFormatter {
}
format_node(context, delta, left) {
+
// recurse
let nodeType = delta._t === 'a' ? 'array' : 'object';
context.out(
@@ -136,7 +138,7 @@ export default class HtmlFormatter extends BaseFormatter {
// draw an SVG arrow from here to move destination
context.out(
/* jshint multistr: true */
- `