@sanity/diff
Advanced tools
Comparing version 2.25.5-next.6 to 2.26.1-purple-unicorn.560
862
lib/index.js
@@ -1,39 +0,835 @@ | ||
"use strict"; | ||
import { diff_match_patch, DIFF_INSERT, DIFF_DELETE, DIFF_EQUAL } from 'diff-match-patch'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
var _exportNames = { | ||
diffInput: true, | ||
wrap: true | ||
}; | ||
Object.defineProperty(exports, "diffInput", { | ||
enumerable: true, | ||
get: function get() { | ||
return _diffInput.diffInput; | ||
} | ||
}); | ||
Object.defineProperty(exports, "wrap", { | ||
enumerable: true, | ||
get: function get() { | ||
return _inputWrappers.wrap; | ||
} | ||
}); | ||
function replaceProperty(parent, prop, value) { | ||
delete parent[prop]; | ||
parent[prop] = value; | ||
return value; | ||
} | ||
var _types = require("./types"); | ||
/* | ||
* Longest common subsequence implementation, for diffing arrays | ||
* Reference: http://en.wikipedia.org/wiki/Longest_common_subsequence_problem | ||
*/ | ||
function getLongestCommonSubsequence(previous, next) { | ||
const matrix = getLengthMatrix(previous, next); | ||
const result = backtrack(matrix, previous, next); | ||
return result; | ||
} | ||
function getLengthMatrix(previous, next) { | ||
const len1 = previous.length; | ||
const len2 = next.length; | ||
let x = 0; | ||
let y = 0; | ||
// initialize empty matrix of len1+1 x len2+1 | ||
const matrix = new Array(len1 + 1); | ||
for (x = 0; x < len1 + 1; x++) { | ||
matrix[x] = [len2 + 1]; | ||
for (y = 0; y < len2 + 1; y++) { | ||
matrix[x][y] = 0; | ||
} | ||
} | ||
// save sequence lengths for each coordinate | ||
for (x = 1; x < len1 + 1; x++) { | ||
for (y = 1; y < len2 + 1; y++) { | ||
if (previous[x - 1] === next[y - 1]) { | ||
matrix[x][y] = matrix[x - 1][y - 1] + 1; | ||
} | ||
else { | ||
matrix[x][y] = Math.max(matrix[x - 1][y], matrix[x][y - 1]); | ||
} | ||
} | ||
} | ||
return matrix; | ||
} | ||
function backtrack(matrix, previous, next) { | ||
let prevIndex = previous.length; | ||
let nextIndex = next.length; | ||
const subsequence = { | ||
sequence: [], | ||
prevIndices: [], | ||
nextIndices: [], | ||
}; | ||
while (prevIndex !== 0 && nextIndex !== 0) { | ||
const areEqual = previous[prevIndex - 1] === next[nextIndex - 1]; | ||
if (areEqual) { | ||
subsequence.sequence.unshift(previous[prevIndex - 1]); | ||
subsequence.prevIndices.unshift(prevIndex - 1); | ||
subsequence.nextIndices.unshift(nextIndex - 1); | ||
--prevIndex; | ||
--nextIndex; | ||
} | ||
else { | ||
const valueAtMatrixAbove = matrix[prevIndex][nextIndex - 1]; | ||
const valueAtMatrixLeft = matrix[prevIndex - 1][nextIndex]; | ||
if (valueAtMatrixAbove > valueAtMatrixLeft) { | ||
--nextIndex; | ||
} | ||
else { | ||
--prevIndex; | ||
} | ||
} | ||
} | ||
return subsequence; | ||
} | ||
Object.keys(_types).forEach(function (key) { | ||
if (key === "default" || key === "__esModule") return; | ||
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; | ||
if (key in exports && exports[key] === _types[key]) return; | ||
Object.defineProperty(exports, key, { | ||
enumerable: true, | ||
get: function get() { | ||
return _types[key]; | ||
function diffArray(fromInput, toInput, options) { | ||
if (fromInput === toInput) { | ||
const fromValue = fromInput.value; | ||
const toValue = toInput.value; | ||
return { | ||
type: 'array', | ||
action: 'unchanged', | ||
isChanged: false, | ||
fromValue, | ||
toValue, | ||
get items() { | ||
const items = diffExactByPosition(fromInput, toInput, options); | ||
if (!items) | ||
throw new Error('invariant broken: equivalent input, but diff detected'); | ||
return replaceProperty(this, 'items', items); | ||
}, | ||
}; | ||
} | ||
}); | ||
}); | ||
// The key-ed approach should handle most cases (_key'ed objects, primitives): | ||
const keyedA = indexByKey(fromInput); | ||
const keyedB = indexByKey(toInput); | ||
if (keyedA && keyedB) { | ||
return diffArrayByKey(fromInput, keyedA, toInput, keyedB); | ||
} | ||
// Check if they are 100% equivalent: | ||
const items = diffExactByPosition(fromInput, toInput, options); | ||
if (items) | ||
return buildArrayDiff(fromInput, toInput, items, false); | ||
// Otherwise we create a diff where we model it as removing the from-items and adding the to-items. | ||
return diffArrayByReinsert(fromInput, toInput); | ||
} | ||
function buildArrayDiff(fromInput, toInput, items, isChanged) { | ||
const fromValue = fromInput.value; | ||
const toValue = toInput.value; | ||
return isChanged | ||
? { | ||
type: 'array', | ||
action: 'changed', | ||
isChanged: true, | ||
fromValue, | ||
toValue, | ||
items, | ||
annotation: toInput.annotation, | ||
} | ||
: { | ||
type: 'array', | ||
action: 'unchanged', | ||
isChanged: false, | ||
fromValue, | ||
toValue, | ||
items, | ||
}; | ||
} | ||
/** | ||
* Diffes the two arrays by position. Returns an `items` array if they are unchanged, or undefined | ||
* if there are any changes anywhere. | ||
*/ | ||
function diffExactByPosition(fromInput, toInput, options) { | ||
if (fromInput.length !== toInput.length) { | ||
return undefined; | ||
} | ||
const items = []; | ||
for (let idx = 0; idx < fromInput.length; idx++) { | ||
const diff = diffInput(fromInput.at(idx), toInput.at(idx), options); | ||
if (diff.isChanged) { | ||
return undefined; | ||
} | ||
items.push({ | ||
fromIndex: idx, | ||
toIndex: idx, | ||
hasMoved: false, | ||
diff, | ||
annotation: toInput.annotationAt(idx), | ||
}); | ||
} | ||
return items; | ||
} | ||
function diffArrayByReinsert(fromInput, toInput, options) { | ||
const items = []; | ||
for (let idx = 0; idx < toInput.length; idx++) { | ||
const input = toInput.at(idx); | ||
items.push({ | ||
fromIndex: undefined, | ||
toIndex: idx, | ||
hasMoved: false, | ||
diff: addedInput(input, undefined), | ||
annotation: input.annotation, | ||
}); | ||
} | ||
for (let idx = 0; idx < fromInput.length; idx++) { | ||
const input = fromInput.at(idx); | ||
items.push({ | ||
fromIndex: idx, | ||
toIndex: undefined, | ||
hasMoved: false, | ||
diff: removedInput(input, undefined), | ||
annotation: input.annotation, | ||
}); | ||
} | ||
return buildArrayDiff(fromInput, toInput, items, true); | ||
} | ||
/** | ||
* Diff an array when all the elements have _key in the same position. | ||
*/ | ||
function diffArrayByKey(fromArray, fromKeyIndex, toArray, toKeyIndex, options) { | ||
const items = []; | ||
let isChanged = false; | ||
function diffCommon(key, fromIndex, toIndex, hasMoved) { | ||
deletePositionInIndex(fromKeyIndex.index, key, fromIndex); | ||
deletePositionInIndex(toKeyIndex.index, key, toIndex); | ||
const fromInput = fromArray.at(fromIndex); | ||
const toInput = toArray.at(toIndex); | ||
const diff = diffInput(fromInput, toInput); | ||
items.push({ | ||
fromIndex, | ||
toIndex, | ||
hasMoved, | ||
diff, | ||
annotation: toArray.annotationAt(toIndex), | ||
}); | ||
if (diff.isChanged || fromIndex !== toIndex) { | ||
isChanged = true; | ||
} | ||
} | ||
const lcs = getLongestCommonSubsequence(fromKeyIndex.keys, toKeyIndex.keys); | ||
for (let fromIndex = 0; fromIndex < fromKeyIndex.keys.length; fromIndex++) { | ||
const key = fromKeyIndex.keys[fromIndex]; | ||
const subsequenceIdx = lcs.prevIndices.indexOf(fromIndex); | ||
if (subsequenceIdx !== -1) { | ||
// Part of the common subsequence => hasMoved:false | ||
diffCommon(key, fromIndex, lcs.nextIndices[subsequenceIdx], false); | ||
continue; | ||
} | ||
// Not a part of the subsequence. Try to find another item which has the same key | ||
// and also is not part of the common subsequence. | ||
const toIndexes = toKeyIndex.index.get(key); | ||
const toIndex = toIndexes && toIndexes.find((idx) => !lcs.nextIndices.includes(idx)); | ||
if (toIndex !== undefined) { | ||
diffCommon(key, fromIndex, toIndex, true); | ||
continue; | ||
} | ||
const input = fromArray.at(fromIndex); | ||
items.push({ | ||
fromIndex, | ||
toIndex: undefined, | ||
hasMoved: false, | ||
diff: removedInput(input, undefined), | ||
annotation: fromArray.annotationAt(fromIndex), | ||
}); | ||
isChanged = true; | ||
} | ||
// The remaining data in toKeyIndex are the new elements which has been added | ||
for (const positions of toKeyIndex.index.values()) { | ||
for (const toIndex of positions) { | ||
const input = toArray.at(toIndex); | ||
items.push({ | ||
fromIndex: undefined, | ||
toIndex, | ||
hasMoved: false, | ||
diff: addedInput(input, undefined), | ||
annotation: toArray.annotationAt(toIndex), | ||
}); | ||
} | ||
isChanged = true; | ||
} | ||
items.sort(compareItemDiff); | ||
return buildArrayDiff(fromArray, toArray, items, isChanged); | ||
} | ||
function compareItemDiff(a, b) { | ||
if (a.toIndex !== undefined && b.toIndex !== undefined) { | ||
return a.toIndex - b.toIndex; | ||
} | ||
if (a.fromIndex !== undefined && b.fromIndex !== undefined) { | ||
return a.fromIndex - b.fromIndex; | ||
} | ||
if (a.fromIndex !== undefined && b.toIndex !== undefined) { | ||
// A was removed and B was added. Prefer to sort removals last. | ||
return -1; | ||
} | ||
if (a.toIndex !== undefined && b.fromIndex !== undefined) { | ||
// A was added and B was removed. Prefer to sort removals last. | ||
return 1; | ||
} | ||
throw new Error('invalid item diff comparison'); | ||
} | ||
function deletePositionInIndex(index, key, pos) { | ||
const positions = index.get(key); | ||
deleteArrayValue(positions, pos); | ||
if (positions.length === 0) { | ||
index.delete(key); | ||
} | ||
} | ||
function deleteArrayValue(arr, value) { | ||
const idx = arr.indexOf(value); | ||
if (idx === -1) | ||
throw new Error('value not found'); | ||
arr.splice(idx, 1); | ||
} | ||
/** | ||
* Indexes the array by a key. This handles cases where the items are: | ||
* | ||
* - Objects with _key | ||
* - Strings | ||
* - Numbers | ||
*/ | ||
function indexByKey(arr) { | ||
const index = new Map(); | ||
const keys = []; | ||
const length = arr.length; | ||
for (let i = 0; i < length; i++) { | ||
const item = arr.at(i); | ||
let key = null; | ||
switch (item.type) { | ||
case 'string': | ||
key = `s${item.value}`; | ||
break; | ||
case 'number': | ||
key = item.value; | ||
break; | ||
case 'boolean': | ||
key = item.value; | ||
break; | ||
case 'null': | ||
key = 'n'; | ||
break; | ||
case 'object': | ||
{ | ||
const keyField = item.get('_key'); | ||
if (keyField && keyField.type === 'string') { | ||
key = `k${keyField.value}`; | ||
// We do not handle duplicate _key | ||
if (index.has(key)) | ||
return undefined; | ||
} | ||
} | ||
break; | ||
} | ||
// No key => abort | ||
if (key === null) | ||
return undefined; | ||
keys.push(key); | ||
let positions = index.get(key); | ||
if (!positions) { | ||
positions = []; | ||
index.set(key, positions); | ||
} | ||
positions.push(i); | ||
} | ||
// All is good. | ||
return { keys, index }; | ||
} | ||
function removedArray(input, toValue, options) { | ||
return { | ||
type: 'array', | ||
action: 'removed', | ||
isChanged: true, | ||
fromValue: input.value, | ||
toValue, | ||
annotation: input.annotation, | ||
get items() { | ||
const items = []; | ||
for (let i = 0; i < input.length; i++) { | ||
const item = input.at(i); | ||
items.push({ | ||
fromIndex: i, | ||
toIndex: undefined, | ||
hasMoved: false, | ||
diff: removedInput(item, undefined), | ||
annotation: input.annotationAt(i), | ||
}); | ||
} | ||
return replaceProperty(this, 'items', items); | ||
}, | ||
}; | ||
} | ||
function addedArray(input, fromValue, options) { | ||
return { | ||
type: 'array', | ||
action: 'added', | ||
isChanged: true, | ||
fromValue, | ||
toValue: input.value, | ||
annotation: input.annotation, | ||
get items() { | ||
const items = []; | ||
for (let i = 0; i < input.length; i++) { | ||
const item = input.at(i); | ||
items.push({ | ||
fromIndex: undefined, | ||
toIndex: i, | ||
hasMoved: false, | ||
diff: addedInput(item, undefined), | ||
annotation: input.annotationAt(i), | ||
}); | ||
} | ||
return replaceProperty(this, 'items', items); | ||
}, | ||
}; | ||
} | ||
var _diffInput = require("./calculate/diffInput"); | ||
const dmp = new diff_match_patch(); | ||
function diffString(fromInput, toInput, options) { | ||
const fromValue = fromInput.value; | ||
const toValue = toInput.value; | ||
if (fromValue === toValue) { | ||
return { | ||
type: 'string', | ||
action: 'unchanged', | ||
isChanged: false, | ||
fromValue, | ||
toValue, | ||
segments: [{ type: 'stringSegment', action: 'unchanged', text: fromValue }], | ||
}; | ||
} | ||
return { | ||
type: 'string', | ||
action: 'changed', | ||
isChanged: true, | ||
fromValue, | ||
toValue, | ||
annotation: toInput.annotation, | ||
// Compute and memoize string segments only when accessed | ||
get segments() { | ||
const segments = buildSegments(fromInput, toInput); | ||
return replaceProperty(this, 'segments', segments); | ||
}, | ||
}; | ||
} | ||
function buildSegments(fromInput, toInput) { | ||
const segments = []; | ||
const dmpDiffs = dmp.diff_main(fromInput.value, toInput.value); | ||
dmp.diff_cleanupSemantic(dmpDiffs); | ||
let fromIdx = 0; | ||
let toIdx = 0; | ||
for (const [op, text] of dmpDiffs) { | ||
switch (op) { | ||
case DIFF_EQUAL: | ||
segments.push({ type: 'stringSegment', action: 'unchanged', text }); | ||
fromIdx += text.length; | ||
toIdx += text.length; | ||
break; | ||
case DIFF_DELETE: | ||
for (const segment of fromInput.sliceAnnotation(fromIdx, fromIdx + text.length)) { | ||
segments.push({ | ||
type: 'stringSegment', | ||
action: 'removed', | ||
text: segment.text, | ||
annotation: segment.annotation, | ||
}); | ||
} | ||
fromIdx += text.length; | ||
break; | ||
case DIFF_INSERT: | ||
for (const segment of toInput.sliceAnnotation(toIdx, toIdx + text.length)) { | ||
segments.push({ | ||
type: 'stringSegment', | ||
action: 'added', | ||
text: segment.text, | ||
annotation: segment.annotation, | ||
}); | ||
} | ||
toIdx += text.length; | ||
break; | ||
default: | ||
throw new Error(`Unhandled diff-match-patch operation "${op}"`); | ||
} | ||
} | ||
return segments; | ||
} | ||
function removedString(input, toValue, options) { | ||
return { | ||
type: 'string', | ||
action: 'removed', | ||
isChanged: true, | ||
fromValue: input.value, | ||
toValue, | ||
annotation: input.annotation, | ||
get segments() { | ||
const segments = input | ||
.sliceAnnotation(0, input.value.length) | ||
.map((segment) => ({ type: 'stringSegment', action: 'removed', ...segment })); | ||
return replaceProperty(this, 'segments', segments); | ||
}, | ||
}; | ||
} | ||
function addedString(input, fromValue, options) { | ||
return { | ||
type: 'string', | ||
action: 'added', | ||
isChanged: true, | ||
fromValue, | ||
toValue: input.value, | ||
annotation: input.annotation, | ||
get segments() { | ||
const segments = input | ||
.sliceAnnotation(0, input.value.length) | ||
.map((segment) => ({ type: 'stringSegment', action: 'added', ...segment })); | ||
return replaceProperty(this, 'segments', segments); | ||
}, | ||
}; | ||
} | ||
var _inputWrappers = require("./inputWrappers"); | ||
function diffTypeChange(fromInput, toInput, options) { | ||
return { | ||
type: 'typeChange', | ||
action: 'changed', | ||
isChanged: true, | ||
fromType: fromInput.type, | ||
fromValue: fromInput.value, | ||
fromDiff: removedInput(fromInput, undefined), | ||
toType: toInput.type, | ||
toValue: toInput.value, | ||
toDiff: addedInput(toInput, undefined), | ||
annotation: toInput.annotation, | ||
}; | ||
} | ||
const ignoredFields = new Set(['_id', '_type', '_createdAt', '_updatedAt', '_rev', '_weak']); | ||
function diffObject(fromInput, toInput, options) { | ||
const fields = {}; | ||
let isChanged = false; | ||
for (const key of fromInput.keys) { | ||
if (ignoredFields.has(key)) | ||
continue; | ||
const fromField = fromInput.get(key); | ||
const toField = toInput.get(key); | ||
if (toField) { | ||
const fieldDiff = diffInput(fromField, toField, options); | ||
fields[key] = fieldDiff; | ||
if (fieldDiff.isChanged) | ||
isChanged = true; | ||
} | ||
else { | ||
fields[key] = removedInput(fromField, undefined); | ||
isChanged = true; | ||
} | ||
} | ||
for (const key of toInput.keys) { | ||
if (ignoredFields.has(key)) | ||
continue; | ||
// Already handled above | ||
if (fromInput.get(key)) | ||
continue; | ||
const toField = toInput.get(key); | ||
fields[key] = addedInput(toField, undefined); | ||
isChanged = true; | ||
} | ||
const fromValue = fromInput.value; | ||
const toValue = toInput.value; | ||
if (!isChanged) { | ||
return { | ||
type: 'object', | ||
action: 'unchanged', | ||
isChanged: false, | ||
fromValue, | ||
toValue, | ||
fields, | ||
}; | ||
} | ||
return { | ||
type: 'object', | ||
action: 'changed', | ||
isChanged: true, | ||
fromValue, | ||
toValue, | ||
fields, | ||
annotation: toInput.annotation, | ||
}; | ||
} | ||
function removedObject(input, toValue, options) { | ||
return { | ||
type: 'object', | ||
action: 'removed', | ||
isChanged: true, | ||
fromValue: input.value, | ||
toValue, | ||
annotation: input.annotation, | ||
get fields() { | ||
const fields = {}; | ||
for (const key of input.keys) { | ||
const value = input.get(key); | ||
fields[key] = removedInput(value, undefined); | ||
} | ||
return replaceProperty(this, 'fields', fields); | ||
}, | ||
}; | ||
} | ||
function addedObject(input, fromValue, options) { | ||
return { | ||
type: 'object', | ||
action: 'added', | ||
isChanged: true, | ||
fromValue, | ||
toValue: input.value, | ||
annotation: input.annotation, | ||
get fields() { | ||
const fields = {}; | ||
for (const key of input.keys) { | ||
const value = input.get(key); | ||
fields[key] = addedInput(value, undefined); | ||
} | ||
return replaceProperty(this, 'fields', fields); | ||
}, | ||
}; | ||
} | ||
function diffNumber(fromInput, toInput, options) { | ||
const fromValue = fromInput.value; | ||
const toValue = toInput.value; | ||
const type = fromInput.type; | ||
if (fromValue === toValue) | ||
return { | ||
type, | ||
action: 'unchanged', | ||
fromValue, | ||
toValue, | ||
isChanged: false, | ||
}; | ||
return { | ||
type: fromInput.type, | ||
action: 'changed', | ||
isChanged: true, | ||
fromValue: fromValue, | ||
toValue: toValue, | ||
annotation: toInput.annotation, | ||
}; | ||
} | ||
function diffBoolean(fromInput, toInput, options) { | ||
const fromValue = fromInput.value; | ||
const toValue = toInput.value; | ||
const type = fromInput.type; | ||
if (fromValue === toValue) | ||
return { | ||
type, | ||
action: 'unchanged', | ||
fromValue, | ||
toValue, | ||
isChanged: false, | ||
}; | ||
return { | ||
type: fromInput.type, | ||
action: 'changed', | ||
isChanged: true, | ||
fromValue: fromValue, | ||
toValue: toValue, | ||
annotation: toInput.annotation, | ||
}; | ||
} | ||
function diffInput(fromInput, toInput, options = {}) { | ||
if (fromInput.type !== toInput.type) { | ||
if (fromInput.type === 'null') { | ||
return addedInput(toInput, null); | ||
} | ||
if (toInput.type === 'null') { | ||
return removedInput(fromInput, null); | ||
} | ||
return diffTypeChange(fromInput, toInput); | ||
} | ||
return diffWithType(fromInput.type, fromInput, toInput, options); | ||
} | ||
function diffWithType(type, fromInput, toInput, options) { | ||
switch (type) { | ||
case 'null': | ||
return { | ||
type: 'null', | ||
action: 'unchanged', | ||
isChanged: false, | ||
toValue: null, | ||
fromValue: null, | ||
}; | ||
case 'boolean': | ||
return diffBoolean(fromInput, toInput); | ||
case 'number': | ||
return diffNumber(fromInput, toInput); | ||
case 'string': | ||
return diffString(fromInput, toInput); | ||
case 'array': | ||
return diffArray(fromInput, toInput, options); | ||
case 'object': | ||
return diffObject(fromInput, toInput, options); | ||
default: | ||
throw new Error(`Unhandled diff type "${type}"`); | ||
} | ||
} | ||
function removedInput(input, toValue, options) { | ||
switch (input.type) { | ||
case 'null': | ||
return { | ||
type: 'null', | ||
action: 'removed', | ||
isChanged: true, | ||
fromValue: null, | ||
toValue, | ||
annotation: input.annotation, | ||
}; | ||
case 'boolean': | ||
return { | ||
type: 'boolean', | ||
action: 'removed', | ||
isChanged: true, | ||
fromValue: input.value, | ||
toValue, | ||
annotation: input.annotation, | ||
}; | ||
case 'number': | ||
return { | ||
type: 'number', | ||
action: 'removed', | ||
isChanged: true, | ||
fromValue: input.value, | ||
toValue, | ||
annotation: input.annotation, | ||
}; | ||
case 'string': | ||
return removedString(input, toValue); | ||
case 'array': | ||
return removedArray(input, toValue); | ||
case 'object': | ||
return removedObject(input, toValue); | ||
default: | ||
throw new Error('Unhandled diff type'); | ||
} | ||
} | ||
function addedInput(input, fromValue, options) { | ||
switch (input.type) { | ||
case 'null': | ||
return { | ||
type: 'null', | ||
action: 'added', | ||
isChanged: true, | ||
fromValue, | ||
toValue: null, | ||
annotation: input.annotation, | ||
}; | ||
case 'boolean': | ||
return { | ||
type: 'boolean', | ||
action: 'added', | ||
isChanged: true, | ||
fromValue, | ||
toValue: input.value, | ||
annotation: input.annotation, | ||
}; | ||
case 'number': | ||
return { | ||
type: 'number', | ||
action: 'added', | ||
isChanged: true, | ||
fromValue, | ||
toValue: input.value, | ||
annotation: input.annotation, | ||
}; | ||
case 'string': | ||
return addedString(input, fromValue); | ||
case 'array': | ||
return addedArray(input, fromValue); | ||
case 'object': | ||
return addedObject(input, fromValue); | ||
default: | ||
throw new Error('Unhandled diff type'); | ||
} | ||
} | ||
class ArrayWrapper { | ||
type = 'array'; | ||
length; | ||
value; | ||
annotation; | ||
elements = []; | ||
constructor(value, annotation) { | ||
this.annotation = annotation; | ||
this.value = value; | ||
this.length = value.length; | ||
} | ||
at(idx) { | ||
if (idx >= this.length) | ||
throw new Error('out of bounds'); | ||
const input = this.elements[idx]; | ||
if (input) { | ||
return input; | ||
} | ||
return (this.elements[idx] = wrap(this.value[idx], this.annotation)); | ||
} | ||
annotationAt() { | ||
return this.annotation; | ||
} | ||
} | ||
class ObjectWrapper { | ||
type = 'object'; | ||
value; | ||
keys; | ||
annotation; | ||
fields = {}; | ||
constructor(value, annotation) { | ||
this.value = value; | ||
this.annotation = annotation; | ||
this.keys = Object.keys(value); | ||
} | ||
get(key) { | ||
const input = this.fields[key]; | ||
if (input) { | ||
return input; | ||
} | ||
if (!this.value.hasOwnProperty(key)) { | ||
return undefined; | ||
} | ||
const raw = this.value[key]; | ||
return (this.fields[key] = wrap(raw, this.annotation)); | ||
} | ||
} | ||
class StringWrapper { | ||
type = 'string'; | ||
value; | ||
annotation; | ||
constructor(value, annotation) { | ||
this.value = value; | ||
this.annotation = annotation; | ||
} | ||
sliceAnnotation(start, end) { | ||
return [{ text: this.value.slice(start, end), annotation: this.annotation }]; | ||
} | ||
} | ||
class BasicWrapper { | ||
type; | ||
value; | ||
annotation; | ||
constructor(type, value, annotation) { | ||
this.type = type; | ||
this.value = value; | ||
this.annotation = annotation; | ||
} | ||
} | ||
function wrap(input, annotation) { | ||
if (Array.isArray(input)) { | ||
return new ArrayWrapper(input, annotation); | ||
} | ||
else if (input === null) { | ||
return new BasicWrapper('null', input, annotation); | ||
} | ||
const type = typeof input; | ||
switch (type) { | ||
case 'number': | ||
return new BasicWrapper(type, input, annotation); | ||
case 'boolean': | ||
return new BasicWrapper(type, input, annotation); | ||
case 'object': | ||
return new ObjectWrapper(input, annotation); | ||
case 'string': | ||
return new StringWrapper(input, annotation); | ||
default: | ||
throw new Error(`cannot wrap value of type: ${type}`); | ||
} | ||
} | ||
export { diffInput, wrap }; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "@sanity/diff", | ||
"version": "2.25.5-next.6+9e5a11cb0", | ||
"version": "2.26.1-purple-unicorn.560+8672b3b5e3", | ||
"description": "Generates diffs between documents and primitive types", | ||
"main": "./lib/index.js", | ||
"types": "./dist/dts", | ||
"main": "./lib/index.cjs", | ||
"module": "./lib/index.js", | ||
"exports": { | ||
".": { | ||
"source": "./src/index.ts", | ||
"require": "./lib/index.cjs", | ||
"default": "./lib/index.js" | ||
} | ||
}, | ||
"types": "./lib/dts/src/index.d.ts", | ||
"author": "Sanity.io <hello@sanity.io>", | ||
@@ -13,3 +21,6 @@ "engines": { | ||
"scripts": { | ||
"clean": "rimraf lib coverage" | ||
"build": "../../../bin/pkg-utils bundle", | ||
"clean": "rimraf lib coverage", | ||
"prebuild": "yarn clean", | ||
"watch": "../../../bin/pkg-utils bundle --watch" | ||
}, | ||
@@ -31,3 +42,3 @@ "keywords": [ | ||
"devDependencies": { | ||
"rimraf": "^2.7.1" | ||
"rimraf": "^3.0.2" | ||
}, | ||
@@ -43,3 +54,3 @@ "repository": { | ||
"homepage": "https://www.sanity.io/", | ||
"gitHead": "9e5a11cb084b22b074ed0f204f9cc640b489529d" | ||
"gitHead": "8672b3b5e39b2aeea500d16ac197b068ba7c943c" | ||
} |
@@ -85,13 +85,7 @@ export type DiffOptions = Record<string, never> | ||
type FullDiff<A, V, P> = ( | ||
| AddedDiff<A, V> | ||
| RemovedDiff<A, V> | ||
| ChangedDiff<A, V> | ||
| UnchangedDiff<A, V> | ||
) & | ||
P | ||
type FullDiff<A, V> = AddedDiff<A, V> | RemovedDiff<A, V> | ChangedDiff<A, V> | UnchangedDiff<A, V> | ||
export type StringDiff<A> = FullDiff<A, string, {type: 'string'; segments: StringDiffSegment<A>[]}> | ||
export type NumberDiff<A> = FullDiff<A, number, {type: 'number'}> | ||
export type BooleanDiff<A> = FullDiff<A, boolean, {type: 'boolean'}> | ||
export type StringDiff<A> = FullDiff<A, string> & {type: 'string'; segments: StringDiffSegment<A>[]} | ||
export type NumberDiff<A> = FullDiff<A, number> & {type: 'number'} | ||
export type BooleanDiff<A> = FullDiff<A, boolean> & {type: 'boolean'} | ||
export type TypeChangeDiff<A> = { | ||
@@ -113,13 +107,11 @@ type: 'typeChange' | ||
export type ObjectDiff<A, T extends object = Record<string, any>> = FullDiff< | ||
A, | ||
T, | ||
{ | ||
type: 'object' | ||
fields: Record<keyof T, Diff<A>> | ||
} | ||
> | ||
export type ArrayDiff<A, V = unknown> = FullDiff<A, V[], {type: 'array'; items: ItemDiff<A>[]}> | ||
export type NullDiff<A> = FullDiff<A, null, {type: 'null'}> | ||
export type ObjectDiff<A, T extends object = Record<string, any>> = FullDiff<A, T> & { | ||
type: 'object' | ||
fields: Record<keyof T, Diff<A>> | ||
} | ||
export type ArrayDiff<A, V = unknown> = FullDiff<A, V[]> & {type: 'array'; items: ItemDiff<A>[]} | ||
export type NullDiff<A> = FullDiff<A, null> & {type: 'null'} | ||
export type Diff<A> = | ||
@@ -126,0 +118,0 @@ | NullDiff<A> |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
214950
2936
53
2