node-diff3
Advanced tools
+433
| var __defProp = Object.defineProperty; | ||
| var __markAsModule = (target) => __defProp(target, "__esModule", { value: true }); | ||
| var __export = (target, all) => { | ||
| __markAsModule(target); | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| __export(exports, { | ||
| LCS: () => LCS, | ||
| diff3Merge: () => diff3Merge, | ||
| diff3MergeRegions: () => diff3MergeRegions, | ||
| diffComm: () => diffComm, | ||
| diffIndices: () => diffIndices, | ||
| diffPatch: () => diffPatch, | ||
| invertPatch: () => invertPatch, | ||
| merge: () => merge, | ||
| mergeDiff3: () => mergeDiff3, | ||
| mergeDigIn: () => mergeDigIn, | ||
| patch: () => patch, | ||
| stripPatch: () => stripPatch | ||
| }); | ||
| function LCS(buffer1, buffer2) { | ||
| let equivalenceClasses = {}; | ||
| for (let j = 0; j < buffer2.length; j++) { | ||
| const item = buffer2[j]; | ||
| if (equivalenceClasses[item]) { | ||
| equivalenceClasses[item].push(j); | ||
| } else { | ||
| equivalenceClasses[item] = [j]; | ||
| } | ||
| } | ||
| const NULLRESULT = { buffer1index: -1, buffer2index: -1, chain: null }; | ||
| let candidates = [NULLRESULT]; | ||
| for (let i = 0; i < buffer1.length; i++) { | ||
| const item = buffer1[i]; | ||
| const buffer2indices = equivalenceClasses[item] || []; | ||
| let r = 0; | ||
| let c = candidates[0]; | ||
| for (let jx = 0; jx < buffer2indices.length; jx++) { | ||
| const j = buffer2indices[jx]; | ||
| let s; | ||
| for (s = r; s < candidates.length; s++) { | ||
| if (candidates[s].buffer2index < j && (s === candidates.length - 1 || candidates[s + 1].buffer2index > j)) { | ||
| break; | ||
| } | ||
| } | ||
| if (s < candidates.length) { | ||
| const newCandidate = { buffer1index: i, buffer2index: j, chain: candidates[s] }; | ||
| if (r === candidates.length) { | ||
| candidates.push(c); | ||
| } else { | ||
| candidates[r] = c; | ||
| } | ||
| r = s + 1; | ||
| c = newCandidate; | ||
| if (r === candidates.length) { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| candidates[r] = c; | ||
| } | ||
| return candidates[candidates.length - 1]; | ||
| } | ||
| function diffComm(buffer1, buffer2) { | ||
| const lcs = LCS(buffer1, buffer2); | ||
| let result = []; | ||
| let tail1 = buffer1.length; | ||
| let tail2 = buffer2.length; | ||
| let common = { common: [] }; | ||
| function processCommon() { | ||
| if (common.common.length) { | ||
| common.common.reverse(); | ||
| result.push(common); | ||
| common = { common: [] }; | ||
| } | ||
| } | ||
| for (let candidate = lcs; candidate !== null; candidate = candidate.chain) { | ||
| let different = { buffer1: [], buffer2: [] }; | ||
| while (--tail1 > candidate.buffer1index) { | ||
| different.buffer1.push(buffer1[tail1]); | ||
| } | ||
| while (--tail2 > candidate.buffer2index) { | ||
| different.buffer2.push(buffer2[tail2]); | ||
| } | ||
| if (different.buffer1.length || different.buffer2.length) { | ||
| processCommon(); | ||
| different.buffer1.reverse(); | ||
| different.buffer2.reverse(); | ||
| result.push(different); | ||
| } | ||
| if (tail1 >= 0) { | ||
| common.common.push(buffer1[tail1]); | ||
| } | ||
| } | ||
| processCommon(); | ||
| result.reverse(); | ||
| return result; | ||
| } | ||
| function diffIndices(buffer1, buffer2) { | ||
| const lcs = LCS(buffer1, buffer2); | ||
| let result = []; | ||
| let tail1 = buffer1.length; | ||
| let tail2 = buffer2.length; | ||
| for (let candidate = lcs; candidate !== null; candidate = candidate.chain) { | ||
| const mismatchLength1 = tail1 - candidate.buffer1index - 1; | ||
| const mismatchLength2 = tail2 - candidate.buffer2index - 1; | ||
| tail1 = candidate.buffer1index; | ||
| tail2 = candidate.buffer2index; | ||
| if (mismatchLength1 || mismatchLength2) { | ||
| result.push({ | ||
| buffer1: [tail1 + 1, mismatchLength1], | ||
| buffer1Content: buffer1.slice(tail1 + 1, tail1 + 1 + mismatchLength1), | ||
| buffer2: [tail2 + 1, mismatchLength2], | ||
| buffer2Content: buffer2.slice(tail2 + 1, tail2 + 1 + mismatchLength2) | ||
| }); | ||
| } | ||
| } | ||
| result.reverse(); | ||
| return result; | ||
| } | ||
| function diffPatch(buffer1, buffer2) { | ||
| const lcs = LCS(buffer1, buffer2); | ||
| let result = []; | ||
| let tail1 = buffer1.length; | ||
| let tail2 = buffer2.length; | ||
| function chunkDescription(buffer, offset, length) { | ||
| let chunk = []; | ||
| for (let i = 0; i < length; i++) { | ||
| chunk.push(buffer[offset + i]); | ||
| } | ||
| return { | ||
| offset, | ||
| length, | ||
| chunk | ||
| }; | ||
| } | ||
| for (let candidate = lcs; candidate !== null; candidate = candidate.chain) { | ||
| const mismatchLength1 = tail1 - candidate.buffer1index - 1; | ||
| const mismatchLength2 = tail2 - candidate.buffer2index - 1; | ||
| tail1 = candidate.buffer1index; | ||
| tail2 = candidate.buffer2index; | ||
| if (mismatchLength1 || mismatchLength2) { | ||
| result.push({ | ||
| buffer1: chunkDescription(buffer1, candidate.buffer1index + 1, mismatchLength1), | ||
| buffer2: chunkDescription(buffer2, candidate.buffer2index + 1, mismatchLength2) | ||
| }); | ||
| } | ||
| } | ||
| result.reverse(); | ||
| return result; | ||
| } | ||
| function diff3MergeRegions(a, o, b) { | ||
| let hunks = []; | ||
| function addHunk(h, ab) { | ||
| hunks.push({ | ||
| ab, | ||
| oStart: h.buffer1[0], | ||
| oLength: h.buffer1[1], | ||
| abStart: h.buffer2[0], | ||
| abLength: h.buffer2[1] | ||
| }); | ||
| } | ||
| diffIndices(o, a).forEach((item) => addHunk(item, "a")); | ||
| diffIndices(o, b).forEach((item) => addHunk(item, "b")); | ||
| hunks.sort((x, y) => x.oStart - y.oStart); | ||
| let results = []; | ||
| let currOffset = 0; | ||
| function advanceTo(endOffset) { | ||
| if (endOffset > currOffset) { | ||
| results.push({ | ||
| stable: true, | ||
| buffer: "o", | ||
| bufferStart: currOffset, | ||
| bufferLength: endOffset - currOffset, | ||
| bufferContent: o.slice(currOffset, endOffset) | ||
| }); | ||
| currOffset = endOffset; | ||
| } | ||
| } | ||
| while (hunks.length) { | ||
| let hunk = hunks.shift(); | ||
| let regionStart = hunk.oStart; | ||
| let regionEnd = hunk.oStart + hunk.oLength; | ||
| let regionHunks = [hunk]; | ||
| advanceTo(regionStart); | ||
| while (hunks.length) { | ||
| const nextHunk = hunks[0]; | ||
| const nextHunkStart = nextHunk.oStart; | ||
| if (nextHunkStart > regionEnd) | ||
| break; | ||
| regionEnd = Math.max(regionEnd, nextHunkStart + nextHunk.oLength); | ||
| regionHunks.push(hunks.shift()); | ||
| } | ||
| if (regionHunks.length === 1) { | ||
| if (hunk.abLength > 0) { | ||
| const buffer = hunk.ab === "a" ? a : b; | ||
| results.push({ | ||
| stable: true, | ||
| buffer: hunk.ab, | ||
| bufferStart: hunk.abStart, | ||
| bufferLength: hunk.abLength, | ||
| bufferContent: buffer.slice(hunk.abStart, hunk.abStart + hunk.abLength) | ||
| }); | ||
| } | ||
| } else { | ||
| let bounds = { | ||
| a: [a.length, -1, o.length, -1], | ||
| b: [b.length, -1, o.length, -1] | ||
| }; | ||
| while (regionHunks.length) { | ||
| hunk = regionHunks.shift(); | ||
| const oStart = hunk.oStart; | ||
| const oEnd = oStart + hunk.oLength; | ||
| const abStart = hunk.abStart; | ||
| const abEnd = abStart + hunk.abLength; | ||
| let b2 = bounds[hunk.ab]; | ||
| b2[0] = Math.min(abStart, b2[0]); | ||
| b2[1] = Math.max(abEnd, b2[1]); | ||
| b2[2] = Math.min(oStart, b2[2]); | ||
| b2[3] = Math.max(oEnd, b2[3]); | ||
| } | ||
| const aStart = bounds.a[0] + (regionStart - bounds.a[2]); | ||
| const aEnd = bounds.a[1] + (regionEnd - bounds.a[3]); | ||
| const bStart = bounds.b[0] + (regionStart - bounds.b[2]); | ||
| const bEnd = bounds.b[1] + (regionEnd - bounds.b[3]); | ||
| let result = { | ||
| stable: false, | ||
| aStart, | ||
| aLength: aEnd - aStart, | ||
| aContent: a.slice(aStart, aEnd), | ||
| oStart: regionStart, | ||
| oLength: regionEnd - regionStart, | ||
| oContent: o.slice(regionStart, regionEnd), | ||
| bStart, | ||
| bLength: bEnd - bStart, | ||
| bContent: b.slice(bStart, bEnd) | ||
| }; | ||
| results.push(result); | ||
| } | ||
| currOffset = regionEnd; | ||
| } | ||
| advanceTo(o.length); | ||
| return results; | ||
| } | ||
| function diff3Merge(a, o, b, options) { | ||
| let defaults = { | ||
| excludeFalseConflicts: true, | ||
| stringSeparator: /\s+/ | ||
| }; | ||
| options = Object.assign(defaults, options); | ||
| const aString = typeof a === "string"; | ||
| const oString = typeof o === "string"; | ||
| const bString = typeof b === "string"; | ||
| if (aString) | ||
| a = a.split(options.stringSeparator); | ||
| if (oString) | ||
| o = o.split(options.stringSeparator); | ||
| if (bString) | ||
| b = b.split(options.stringSeparator); | ||
| let results = []; | ||
| const regions = diff3MergeRegions(a, o, b); | ||
| let okBuffer = []; | ||
| function flushOk() { | ||
| if (okBuffer.length) { | ||
| results.push({ ok: okBuffer }); | ||
| } | ||
| okBuffer = []; | ||
| } | ||
| function isFalseConflict(a2, b2) { | ||
| if (a2.length !== b2.length) | ||
| return false; | ||
| for (let i = 0; i < a2.length; i++) { | ||
| if (a2[i] !== b2[i]) | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| regions.forEach((region) => { | ||
| if (region.stable) { | ||
| okBuffer.push(...region.bufferContent); | ||
| } else { | ||
| if (options.excludeFalseConflicts && isFalseConflict(region.aContent, region.bContent)) { | ||
| okBuffer.push(...region.aContent); | ||
| } else { | ||
| flushOk(); | ||
| results.push({ | ||
| conflict: { | ||
| a: region.aContent, | ||
| aIndex: region.aStart, | ||
| o: region.oContent, | ||
| oIndex: region.oStart, | ||
| b: region.bContent, | ||
| bIndex: region.bStart | ||
| } | ||
| }); | ||
| } | ||
| } | ||
| }); | ||
| flushOk(); | ||
| return results; | ||
| } | ||
| function mergeDiff3(a, o, b, options) { | ||
| let defaults = { | ||
| excludeFalseConflicts: true, | ||
| stringSeparator: /\s+/, | ||
| label: {} | ||
| }; | ||
| options = Object.assign(defaults, options); | ||
| const mergeResult = diff3Merge(a, o, b, options); | ||
| let conflict = false; | ||
| let lines = []; | ||
| mergeResult.forEach((result) => { | ||
| if (result.ok) { | ||
| lines = lines.concat(result.ok); | ||
| } else if (result.conflict) { | ||
| conflict = true; | ||
| lines.push(`<<<<<<<${options.label.a ? ` ${options.label.a}` : ""}`); | ||
| lines = lines.concat(result.conflict.a); | ||
| lines.push(`|||||||${options.label.o ? ` ${options.label.o}` : ""}`); | ||
| lines = lines.concat(result.conflict.o); | ||
| lines.push("======="); | ||
| lines = lines.concat(result.conflict.b); | ||
| lines.push(`>>>>>>>${options.label.b ? ` ${options.label.b}` : ""}`); | ||
| } | ||
| }); | ||
| return { | ||
| conflict, | ||
| result: lines | ||
| }; | ||
| } | ||
| function merge(a, o, b, options) { | ||
| let defaults = { | ||
| excludeFalseConflicts: true, | ||
| stringSeparator: /\s+/ | ||
| }; | ||
| options = Object.assign(defaults, options); | ||
| const merger = diff3Merge(a, o, b, options); | ||
| let conflict = false; | ||
| let lines = []; | ||
| for (let i = 0; i < merger.length; i++) { | ||
| const item = merger[i]; | ||
| if (item.ok) { | ||
| lines = lines.concat(item.ok); | ||
| } else { | ||
| conflict = true; | ||
| lines = lines.concat(["\n<<<<<<<<<\n"], item.conflict.a, ["\n=========\n"], item.conflict.b, ["\n>>>>>>>>>\n"]); | ||
| } | ||
| } | ||
| return { | ||
| conflict, | ||
| result: lines | ||
| }; | ||
| } | ||
| function mergeDigIn(a, o, b, options) { | ||
| let defaults = { | ||
| excludeFalseConflicts: false, | ||
| stringSeparator: /\s+/ | ||
| }; | ||
| options = Object.assign(defaults, options); | ||
| const merger = diff3Merge(a, o, b, options); | ||
| let conflict = false; | ||
| let lines = []; | ||
| for (let i = 0; i < merger.length; i++) { | ||
| const item = merger[i]; | ||
| if (item.ok) { | ||
| lines = lines.concat(item.ok); | ||
| } else { | ||
| const c = diffComm(item.conflict.a, item.conflict.b); | ||
| for (let j = 0; j < c.length; j++) { | ||
| let inner = c[j]; | ||
| if (inner.common) { | ||
| lines = lines.concat(inner.common); | ||
| } else { | ||
| conflict = true; | ||
| lines = lines.concat(["\n<<<<<<<<<\n"], inner.buffer1, ["\n=========\n"], inner.buffer2, ["\n>>>>>>>>>\n"]); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return { | ||
| conflict, | ||
| result: lines | ||
| }; | ||
| } | ||
| function patch(buffer, patch2) { | ||
| let result = []; | ||
| let currOffset = 0; | ||
| function advanceTo(targetOffset) { | ||
| while (currOffset < targetOffset) { | ||
| result.push(buffer[currOffset]); | ||
| currOffset++; | ||
| } | ||
| } | ||
| for (let chunkIndex = 0; chunkIndex < patch2.length; chunkIndex++) { | ||
| let chunk = patch2[chunkIndex]; | ||
| advanceTo(chunk.buffer1.offset); | ||
| for (let itemIndex = 0; itemIndex < chunk.buffer2.chunk.length; itemIndex++) { | ||
| result.push(chunk.buffer2.chunk[itemIndex]); | ||
| } | ||
| currOffset += chunk.buffer1.length; | ||
| } | ||
| advanceTo(buffer.length); | ||
| return result; | ||
| } | ||
| function stripPatch(patch2) { | ||
| return patch2.map((chunk) => ({ | ||
| buffer1: { offset: chunk.buffer1.offset, length: chunk.buffer1.length }, | ||
| buffer2: { chunk: chunk.buffer2.chunk } | ||
| })); | ||
| } | ||
| function invertPatch(patch2) { | ||
| return patch2.map((chunk) => ({ | ||
| buffer1: chunk.buffer2, | ||
| buffer2: chunk.buffer1 | ||
| })); | ||
| } | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| LCS, | ||
| diff3Merge, | ||
| diff3MergeRegions, | ||
| diffComm, | ||
| diffIndices, | ||
| diffPatch, | ||
| invertPatch, | ||
| merge, | ||
| mergeDiff3, | ||
| mergeDigIn, | ||
| patch, | ||
| stripPatch | ||
| }); | ||
| //# sourceMappingURL=index.cjs.map |
| { | ||
| "version": 3, | ||
| "sources": ["../index.mjs"], | ||
| "sourcesContent": ["export {\n LCS,\n diffComm,\n diffIndices,\n diffPatch,\n diff3MergeRegions,\n diff3Merge,\n mergeDiff3,\n merge,\n mergeDigIn,\n patch,\n stripPatch,\n invertPatch\n};\n\n\n// Text diff algorithm following Hunt and McIlroy 1976.\n// J. W. Hunt and M. D. McIlroy, An algorithm for differential buffer\n// comparison, Bell Telephone Laboratories CSTR #41 (1976)\n// http://www.cs.dartmouth.edu/~doug/\n// https://en.wikipedia.org/wiki/Longest_common_subsequence_problem\n//\n// Expects two arrays, finds longest common sequence\nfunction LCS(buffer1, buffer2) {\n\n let equivalenceClasses = {};\n for (let j = 0; j < buffer2.length; j++) {\n const item = buffer2[j];\n if (equivalenceClasses[item]) {\n equivalenceClasses[item].push(j);\n } else {\n equivalenceClasses[item] = [j];\n }\n }\n\n const NULLRESULT = { buffer1index: -1, buffer2index: -1, chain: null };\n let candidates = [NULLRESULT];\n\n for (let i = 0; i < buffer1.length; i++) {\n const item = buffer1[i];\n const buffer2indices = equivalenceClasses[item] || [];\n let r = 0;\n let c = candidates[0];\n\n for (let jx = 0; jx < buffer2indices.length; jx++) {\n const j = buffer2indices[jx];\n\n let s;\n for (s = r; s < candidates.length; s++) {\n if ((candidates[s].buffer2index < j) && ((s === candidates.length - 1) || (candidates[s + 1].buffer2index > j))) {\n break;\n }\n }\n\n if (s < candidates.length) {\n const newCandidate = { buffer1index: i, buffer2index: j, chain: candidates[s] };\n if (r === candidates.length) {\n candidates.push(c);\n } else {\n candidates[r] = c;\n }\n r = s + 1;\n c = newCandidate;\n if (r === candidates.length) {\n break; // no point in examining further (j)s\n }\n }\n }\n\n candidates[r] = c;\n }\n\n // At this point, we know the LCS: it's in the reverse of the\n // linked-list through .chain of candidates[candidates.length - 1].\n\n return candidates[candidates.length - 1];\n}\n\n\n// We apply the LCS to build a 'comm'-style picture of the\n// differences between buffer1 and buffer2.\nfunction diffComm(buffer1, buffer2) {\n const lcs = LCS(buffer1, buffer2);\n let result = [];\n let tail1 = buffer1.length;\n let tail2 = buffer2.length;\n let common = {common: []};\n\n function processCommon() {\n if (common.common.length) {\n common.common.reverse();\n result.push(common);\n common = {common: []};\n }\n }\n\n for (let candidate = lcs; candidate !== null; candidate = candidate.chain) {\n let different = {buffer1: [], buffer2: []};\n\n while (--tail1 > candidate.buffer1index) {\n different.buffer1.push(buffer1[tail1]);\n }\n\n while (--tail2 > candidate.buffer2index) {\n different.buffer2.push(buffer2[tail2]);\n }\n\n if (different.buffer1.length || different.buffer2.length) {\n processCommon();\n different.buffer1.reverse();\n different.buffer2.reverse();\n result.push(different);\n }\n\n if (tail1 >= 0) {\n common.common.push(buffer1[tail1]);\n }\n }\n\n processCommon();\n\n result.reverse();\n return result;\n}\n\n\n// We apply the LCS to give a simple representation of the\n// offsets and lengths of mismatched chunks in the input\n// buffers. This is used by diff3MergeRegions.\nfunction diffIndices(buffer1, buffer2) {\n const lcs = LCS(buffer1, buffer2);\n let result = [];\n let tail1 = buffer1.length;\n let tail2 = buffer2.length;\n\n for (let candidate = lcs; candidate !== null; candidate = candidate.chain) {\n const mismatchLength1 = tail1 - candidate.buffer1index - 1;\n const mismatchLength2 = tail2 - candidate.buffer2index - 1;\n tail1 = candidate.buffer1index;\n tail2 = candidate.buffer2index;\n\n if (mismatchLength1 || mismatchLength2) {\n result.push({\n buffer1: [tail1 + 1, mismatchLength1],\n buffer1Content: buffer1.slice(tail1 + 1, tail1 + 1 + mismatchLength1),\n buffer2: [tail2 + 1, mismatchLength2],\n buffer2Content: buffer2.slice(tail2 + 1, tail2 + 1 + mismatchLength2)\n });\n }\n }\n\n result.reverse();\n return result;\n}\n\n\n// We apply the LCS to build a JSON representation of a\n// diff(1)-style patch.\nfunction diffPatch(buffer1, buffer2) {\n const lcs = LCS(buffer1, buffer2);\n let result = [];\n let tail1 = buffer1.length;\n let tail2 = buffer2.length;\n\n function chunkDescription(buffer, offset, length) {\n let chunk = [];\n for (let i = 0; i < length; i++) {\n chunk.push(buffer[offset + i]);\n }\n return {\n offset: offset,\n length: length,\n chunk: chunk\n };\n }\n\n for (let candidate = lcs; candidate !== null; candidate = candidate.chain) {\n const mismatchLength1 = tail1 - candidate.buffer1index - 1;\n const mismatchLength2 = tail2 - candidate.buffer2index - 1;\n tail1 = candidate.buffer1index;\n tail2 = candidate.buffer2index;\n\n if (mismatchLength1 || mismatchLength2) {\n result.push({\n buffer1: chunkDescription(buffer1, candidate.buffer1index + 1, mismatchLength1),\n buffer2: chunkDescription(buffer2, candidate.buffer2index + 1, mismatchLength2)\n });\n }\n }\n\n result.reverse();\n return result;\n}\n\n\n// Given three buffers, A, O, and B, where both A and B are\n// independently derived from O, returns a fairly complicated\n// internal representation of merge decisions it's taken. The\n// interested reader may wish to consult\n//\n// Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce.\n// 'A Formal Investigation of ' In Arvind and Prasad,\n// editors, Foundations of Software Technology and Theoretical\n// Computer Science (FSTTCS), December 2007.\n//\n// (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf)\n//\nfunction diff3MergeRegions(a, o, b) {\n\n // \"hunks\" are array subsets where `a` or `b` are different from `o`\n // https://www.gnu.org/software/diffutils/manual/html_node/diff3-Hunks.html\n let hunks = [];\n function addHunk(h, ab) {\n hunks.push({\n ab: ab,\n oStart: h.buffer1[0],\n oLength: h.buffer1[1], // length of o to remove\n abStart: h.buffer2[0],\n abLength: h.buffer2[1] // length of a/b to insert\n // abContent: (ab === 'a' ? a : b).slice(h.buffer2[0], h.buffer2[0] + h.buffer2[1])\n });\n }\n\n diffIndices(o, a).forEach(item => addHunk(item, 'a'));\n diffIndices(o, b).forEach(item => addHunk(item, 'b'));\n hunks.sort((x,y) => x.oStart - y.oStart);\n\n let results = [];\n let currOffset = 0;\n\n function advanceTo(endOffset) {\n if (endOffset > currOffset) {\n results.push({\n stable: true,\n buffer: 'o',\n bufferStart: currOffset,\n bufferLength: endOffset - currOffset,\n bufferContent: o.slice(currOffset, endOffset)\n });\n currOffset = endOffset;\n }\n }\n\n while (hunks.length) {\n let hunk = hunks.shift();\n let regionStart = hunk.oStart;\n let regionEnd = hunk.oStart + hunk.oLength;\n let regionHunks = [hunk];\n advanceTo(regionStart);\n\n // Try to pull next overlapping hunk into this region\n while (hunks.length) {\n const nextHunk = hunks[0];\n const nextHunkStart = nextHunk.oStart;\n if (nextHunkStart > regionEnd) break; // no overlap\n\n regionEnd = Math.max(regionEnd, nextHunkStart + nextHunk.oLength);\n regionHunks.push(hunks.shift());\n }\n\n if (regionHunks.length === 1) {\n // Only one hunk touches this region, meaning that there is no conflict here.\n // Either `a` or `b` is inserting into a region of `o` unchanged by the other.\n if (hunk.abLength > 0) {\n const buffer = (hunk.ab === 'a' ? a : b);\n results.push({\n stable: true,\n buffer: hunk.ab,\n bufferStart: hunk.abStart,\n bufferLength: hunk.abLength,\n bufferContent: buffer.slice(hunk.abStart, hunk.abStart + hunk.abLength)\n });\n }\n } else {\n // A true a/b conflict. Determine the bounds involved from `a`, `o`, and `b`.\n // Effectively merge all the `a` hunks into one giant hunk, then do the\n // same for the `b` hunks; then, correct for skew in the regions of `o`\n // that each side changed, and report appropriate spans for the three sides.\n let bounds = {\n a: [a.length, -1, o.length, -1],\n b: [b.length, -1, o.length, -1]\n };\n while (regionHunks.length) {\n hunk = regionHunks.shift();\n const oStart = hunk.oStart;\n const oEnd = oStart + hunk.oLength;\n const abStart = hunk.abStart;\n const abEnd = abStart + hunk.abLength;\n let b = bounds[hunk.ab];\n b[0] = Math.min(abStart, b[0]);\n b[1] = Math.max(abEnd, b[1]);\n b[2] = Math.min(oStart, b[2]);\n b[3] = Math.max(oEnd, b[3]);\n }\n\n const aStart = bounds.a[0] + (regionStart - bounds.a[2]);\n const aEnd = bounds.a[1] + (regionEnd - bounds.a[3]);\n const bStart = bounds.b[0] + (regionStart - bounds.b[2]);\n const bEnd = bounds.b[1] + (regionEnd - bounds.b[3]);\n\n let result = {\n stable: false,\n aStart: aStart,\n aLength: aEnd - aStart,\n aContent: a.slice(aStart, aEnd),\n oStart: regionStart,\n oLength: regionEnd - regionStart,\n oContent: o.slice(regionStart, regionEnd),\n bStart: bStart,\n bLength: bEnd - bStart,\n bContent: b.slice(bStart, bEnd)\n };\n results.push(result);\n }\n currOffset = regionEnd;\n }\n\n advanceTo(o.length);\n\n return results;\n}\n\n\n// Applies the output of diff3MergeRegions to actually\n// construct the merged buffer; the returned result alternates\n// between 'ok' and 'conflict' blocks.\n// A \"false conflict\" is where `a` and `b` both change the same from `o`\nfunction diff3Merge(a, o, b, options) {\n let defaults = {\n excludeFalseConflicts: true,\n stringSeparator: /\\s+/\n };\n options = Object.assign(defaults, options);\n\n const aString = (typeof a === 'string');\n const oString = (typeof o === 'string');\n const bString = (typeof b === 'string');\n\n if (aString) a = a.split(options.stringSeparator);\n if (oString) o = o.split(options.stringSeparator);\n if (bString) b = b.split(options.stringSeparator);\n\n let results = [];\n const regions = diff3MergeRegions(a, o, b);\n\n let okBuffer = [];\n function flushOk() {\n if (okBuffer.length) {\n results.push({ ok: okBuffer });\n }\n okBuffer = [];\n }\n\n function isFalseConflict(a, b) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n regions.forEach(region => {\n if (region.stable) {\n okBuffer.push(...region.bufferContent);\n } else {\n if (options.excludeFalseConflicts && isFalseConflict(region.aContent, region.bContent)) {\n okBuffer.push(...region.aContent);\n } else {\n flushOk();\n results.push({\n conflict: {\n a: region.aContent,\n aIndex: region.aStart,\n o: region.oContent,\n oIndex: region.oStart,\n b: region.bContent,\n bIndex: region.bStart\n }\n });\n }\n }\n });\n\n flushOk();\n return results;\n}\n\nfunction mergeDiff3(a, o, b, options) {\n let defaults = {\n excludeFalseConflicts: true,\n stringSeparator: /\\s+/,\n label: {}\n };\n options = Object.assign(defaults, options);\n\n const mergeResult = diff3Merge(a, o, b, options);\n\n let conflict = false;\n let lines = [];\n\n mergeResult.forEach(result => {\n if (result.ok) {\n lines = lines.concat(result.ok);\n } else if (result.conflict) {\n conflict = true;\n lines.push(`<<<<<<<${options.label.a ? ` ${options.label.a}` : ''}`);\n lines = lines.concat(result.conflict.a);\n lines.push(`|||||||${options.label.o ? ` ${options.label.o}` : ''}`);\n lines = lines.concat(result.conflict.o);\n lines.push('=======');\n lines = lines.concat(result.conflict.b);\n lines.push(`>>>>>>>${options.label.b ? ` ${options.label.b}` : ''}`);\n }\n });\n\n return {\n conflict: conflict,\n result: lines\n };\n}\n\nfunction merge(a, o, b, options) {\n let defaults = {\n excludeFalseConflicts: true,\n stringSeparator: /\\s+/\n };\n options = Object.assign(defaults, options);\n\n const merger = diff3Merge(a, o, b, options);\n let conflict = false;\n let lines = [];\n for (let i = 0; i < merger.length; i++) {\n const item = merger[i];\n if (item.ok) {\n lines = lines.concat(item.ok);\n } else {\n conflict = true;\n lines = lines.concat(\n ['\\n<<<<<<<<<\\n'], item.conflict.a,\n ['\\n=========\\n'], item.conflict.b,\n ['\\n>>>>>>>>>\\n']\n );\n }\n }\n return {\n conflict: conflict,\n result: lines\n };\n}\n\n\nfunction mergeDigIn(a, o, b, options) {\n let defaults = {\n excludeFalseConflicts: false,\n stringSeparator: /\\s+/\n };\n options = Object.assign(defaults, options);\n\n const merger = diff3Merge(a, o, b, options);\n let conflict = false;\n let lines = [];\n for (let i = 0; i < merger.length; i++) {\n const item = merger[i];\n if (item.ok) {\n lines = lines.concat(item.ok);\n } else {\n const c = diffComm(item.conflict.a, item.conflict.b);\n for (let j = 0; j < c.length; j++) {\n let inner = c[j];\n if (inner.common) {\n lines = lines.concat(inner.common);\n } else {\n conflict = true;\n lines = lines.concat(\n ['\\n<<<<<<<<<\\n'], inner.buffer1,\n ['\\n=========\\n'], inner.buffer2,\n ['\\n>>>>>>>>>\\n']\n );\n }\n }\n }\n }\n return {\n conflict: conflict,\n result: lines\n };\n}\n\n\n// Applies a patch to a buffer.\n// Given buffer1 and buffer2, `patch(buffer1, diffPatch(buffer1, buffer2))` should give buffer2.\nfunction patch(buffer, patch) {\n let result = [];\n let currOffset = 0;\n\n function advanceTo(targetOffset) {\n while (currOffset < targetOffset) {\n result.push(buffer[currOffset]);\n currOffset++;\n }\n }\n\n for (let chunkIndex = 0; chunkIndex < patch.length; chunkIndex++) {\n let chunk = patch[chunkIndex];\n advanceTo(chunk.buffer1.offset);\n for (let itemIndex = 0; itemIndex < chunk.buffer2.chunk.length; itemIndex++) {\n result.push(chunk.buffer2.chunk[itemIndex]);\n }\n currOffset += chunk.buffer1.length;\n }\n\n advanceTo(buffer.length);\n return result;\n}\n\n\n// Takes the output of diffPatch(), and removes extra information from it.\n// It can still be used by patch(), below, but can no longer be inverted.\nfunction stripPatch(patch) {\n return patch.map(chunk => ({\n buffer1: { offset: chunk.buffer1.offset, length: chunk.buffer1.length },\n buffer2: { chunk: chunk.buffer2.chunk }\n }));\n}\n\n\n// Takes the output of diffPatch(), and inverts the sense of it, so that it\n// can be applied to buffer2 to give buffer1 rather than the other way around.\nfunction invertPatch(patch) {\n return patch.map(chunk => ({\n buffer1: chunk.buffer2,\n buffer2: chunk.buffer1\n }));\n}\n"], | ||
| "mappings": "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", | ||
| "names": [] | ||
| } |
| var Diff3 = (() => { | ||
| var __defProp = Object.defineProperty; | ||
| var __markAsModule = (target) => __defProp(target, "__esModule", { value: true }); | ||
| var __export = (target, all) => { | ||
| __markAsModule(target); | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| // index.mjs | ||
| var node_diff3_exports = {}; | ||
| __export(node_diff3_exports, { | ||
| LCS: () => LCS, | ||
| diff3Merge: () => diff3Merge, | ||
| diff3MergeRegions: () => diff3MergeRegions, | ||
| diffComm: () => diffComm, | ||
| diffIndices: () => diffIndices, | ||
| diffPatch: () => diffPatch, | ||
| invertPatch: () => invertPatch, | ||
| merge: () => merge, | ||
| mergeDiff3: () => mergeDiff3, | ||
| mergeDigIn: () => mergeDigIn, | ||
| patch: () => patch, | ||
| stripPatch: () => stripPatch | ||
| }); | ||
| function LCS(buffer1, buffer2) { | ||
| let equivalenceClasses = {}; | ||
| for (let j = 0; j < buffer2.length; j++) { | ||
| const item = buffer2[j]; | ||
| if (equivalenceClasses[item]) { | ||
| equivalenceClasses[item].push(j); | ||
| } else { | ||
| equivalenceClasses[item] = [j]; | ||
| } | ||
| } | ||
| const NULLRESULT = { buffer1index: -1, buffer2index: -1, chain: null }; | ||
| let candidates = [NULLRESULT]; | ||
| for (let i = 0; i < buffer1.length; i++) { | ||
| const item = buffer1[i]; | ||
| const buffer2indices = equivalenceClasses[item] || []; | ||
| let r = 0; | ||
| let c = candidates[0]; | ||
| for (let jx = 0; jx < buffer2indices.length; jx++) { | ||
| const j = buffer2indices[jx]; | ||
| let s; | ||
| for (s = r; s < candidates.length; s++) { | ||
| if (candidates[s].buffer2index < j && (s === candidates.length - 1 || candidates[s + 1].buffer2index > j)) { | ||
| break; | ||
| } | ||
| } | ||
| if (s < candidates.length) { | ||
| const newCandidate = { buffer1index: i, buffer2index: j, chain: candidates[s] }; | ||
| if (r === candidates.length) { | ||
| candidates.push(c); | ||
| } else { | ||
| candidates[r] = c; | ||
| } | ||
| r = s + 1; | ||
| c = newCandidate; | ||
| if (r === candidates.length) { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| candidates[r] = c; | ||
| } | ||
| return candidates[candidates.length - 1]; | ||
| } | ||
| function diffComm(buffer1, buffer2) { | ||
| const lcs = LCS(buffer1, buffer2); | ||
| let result = []; | ||
| let tail1 = buffer1.length; | ||
| let tail2 = buffer2.length; | ||
| let common = { common: [] }; | ||
| function processCommon() { | ||
| if (common.common.length) { | ||
| common.common.reverse(); | ||
| result.push(common); | ||
| common = { common: [] }; | ||
| } | ||
| } | ||
| for (let candidate = lcs; candidate !== null; candidate = candidate.chain) { | ||
| let different = { buffer1: [], buffer2: [] }; | ||
| while (--tail1 > candidate.buffer1index) { | ||
| different.buffer1.push(buffer1[tail1]); | ||
| } | ||
| while (--tail2 > candidate.buffer2index) { | ||
| different.buffer2.push(buffer2[tail2]); | ||
| } | ||
| if (different.buffer1.length || different.buffer2.length) { | ||
| processCommon(); | ||
| different.buffer1.reverse(); | ||
| different.buffer2.reverse(); | ||
| result.push(different); | ||
| } | ||
| if (tail1 >= 0) { | ||
| common.common.push(buffer1[tail1]); | ||
| } | ||
| } | ||
| processCommon(); | ||
| result.reverse(); | ||
| return result; | ||
| } | ||
| function diffIndices(buffer1, buffer2) { | ||
| const lcs = LCS(buffer1, buffer2); | ||
| let result = []; | ||
| let tail1 = buffer1.length; | ||
| let tail2 = buffer2.length; | ||
| for (let candidate = lcs; candidate !== null; candidate = candidate.chain) { | ||
| const mismatchLength1 = tail1 - candidate.buffer1index - 1; | ||
| const mismatchLength2 = tail2 - candidate.buffer2index - 1; | ||
| tail1 = candidate.buffer1index; | ||
| tail2 = candidate.buffer2index; | ||
| if (mismatchLength1 || mismatchLength2) { | ||
| result.push({ | ||
| buffer1: [tail1 + 1, mismatchLength1], | ||
| buffer1Content: buffer1.slice(tail1 + 1, tail1 + 1 + mismatchLength1), | ||
| buffer2: [tail2 + 1, mismatchLength2], | ||
| buffer2Content: buffer2.slice(tail2 + 1, tail2 + 1 + mismatchLength2) | ||
| }); | ||
| } | ||
| } | ||
| result.reverse(); | ||
| return result; | ||
| } | ||
| function diffPatch(buffer1, buffer2) { | ||
| const lcs = LCS(buffer1, buffer2); | ||
| let result = []; | ||
| let tail1 = buffer1.length; | ||
| let tail2 = buffer2.length; | ||
| function chunkDescription(buffer, offset, length) { | ||
| let chunk = []; | ||
| for (let i = 0; i < length; i++) { | ||
| chunk.push(buffer[offset + i]); | ||
| } | ||
| return { | ||
| offset, | ||
| length, | ||
| chunk | ||
| }; | ||
| } | ||
| for (let candidate = lcs; candidate !== null; candidate = candidate.chain) { | ||
| const mismatchLength1 = tail1 - candidate.buffer1index - 1; | ||
| const mismatchLength2 = tail2 - candidate.buffer2index - 1; | ||
| tail1 = candidate.buffer1index; | ||
| tail2 = candidate.buffer2index; | ||
| if (mismatchLength1 || mismatchLength2) { | ||
| result.push({ | ||
| buffer1: chunkDescription(buffer1, candidate.buffer1index + 1, mismatchLength1), | ||
| buffer2: chunkDescription(buffer2, candidate.buffer2index + 1, mismatchLength2) | ||
| }); | ||
| } | ||
| } | ||
| result.reverse(); | ||
| return result; | ||
| } | ||
| function diff3MergeRegions(a, o, b) { | ||
| let hunks = []; | ||
| function addHunk(h, ab) { | ||
| hunks.push({ | ||
| ab, | ||
| oStart: h.buffer1[0], | ||
| oLength: h.buffer1[1], | ||
| abStart: h.buffer2[0], | ||
| abLength: h.buffer2[1] | ||
| }); | ||
| } | ||
| diffIndices(o, a).forEach((item) => addHunk(item, "a")); | ||
| diffIndices(o, b).forEach((item) => addHunk(item, "b")); | ||
| hunks.sort((x, y) => x.oStart - y.oStart); | ||
| let results = []; | ||
| let currOffset = 0; | ||
| function advanceTo(endOffset) { | ||
| if (endOffset > currOffset) { | ||
| results.push({ | ||
| stable: true, | ||
| buffer: "o", | ||
| bufferStart: currOffset, | ||
| bufferLength: endOffset - currOffset, | ||
| bufferContent: o.slice(currOffset, endOffset) | ||
| }); | ||
| currOffset = endOffset; | ||
| } | ||
| } | ||
| while (hunks.length) { | ||
| let hunk = hunks.shift(); | ||
| let regionStart = hunk.oStart; | ||
| let regionEnd = hunk.oStart + hunk.oLength; | ||
| let regionHunks = [hunk]; | ||
| advanceTo(regionStart); | ||
| while (hunks.length) { | ||
| const nextHunk = hunks[0]; | ||
| const nextHunkStart = nextHunk.oStart; | ||
| if (nextHunkStart > regionEnd) | ||
| break; | ||
| regionEnd = Math.max(regionEnd, nextHunkStart + nextHunk.oLength); | ||
| regionHunks.push(hunks.shift()); | ||
| } | ||
| if (regionHunks.length === 1) { | ||
| if (hunk.abLength > 0) { | ||
| const buffer = hunk.ab === "a" ? a : b; | ||
| results.push({ | ||
| stable: true, | ||
| buffer: hunk.ab, | ||
| bufferStart: hunk.abStart, | ||
| bufferLength: hunk.abLength, | ||
| bufferContent: buffer.slice(hunk.abStart, hunk.abStart + hunk.abLength) | ||
| }); | ||
| } | ||
| } else { | ||
| let bounds = { | ||
| a: [a.length, -1, o.length, -1], | ||
| b: [b.length, -1, o.length, -1] | ||
| }; | ||
| while (regionHunks.length) { | ||
| hunk = regionHunks.shift(); | ||
| const oStart = hunk.oStart; | ||
| const oEnd = oStart + hunk.oLength; | ||
| const abStart = hunk.abStart; | ||
| const abEnd = abStart + hunk.abLength; | ||
| let b2 = bounds[hunk.ab]; | ||
| b2[0] = Math.min(abStart, b2[0]); | ||
| b2[1] = Math.max(abEnd, b2[1]); | ||
| b2[2] = Math.min(oStart, b2[2]); | ||
| b2[3] = Math.max(oEnd, b2[3]); | ||
| } | ||
| const aStart = bounds.a[0] + (regionStart - bounds.a[2]); | ||
| const aEnd = bounds.a[1] + (regionEnd - bounds.a[3]); | ||
| const bStart = bounds.b[0] + (regionStart - bounds.b[2]); | ||
| const bEnd = bounds.b[1] + (regionEnd - bounds.b[3]); | ||
| let result = { | ||
| stable: false, | ||
| aStart, | ||
| aLength: aEnd - aStart, | ||
| aContent: a.slice(aStart, aEnd), | ||
| oStart: regionStart, | ||
| oLength: regionEnd - regionStart, | ||
| oContent: o.slice(regionStart, regionEnd), | ||
| bStart, | ||
| bLength: bEnd - bStart, | ||
| bContent: b.slice(bStart, bEnd) | ||
| }; | ||
| results.push(result); | ||
| } | ||
| currOffset = regionEnd; | ||
| } | ||
| advanceTo(o.length); | ||
| return results; | ||
| } | ||
| function diff3Merge(a, o, b, options) { | ||
| let defaults = { | ||
| excludeFalseConflicts: true, | ||
| stringSeparator: /\s+/ | ||
| }; | ||
| options = Object.assign(defaults, options); | ||
| const aString = typeof a === "string"; | ||
| const oString = typeof o === "string"; | ||
| const bString = typeof b === "string"; | ||
| if (aString) | ||
| a = a.split(options.stringSeparator); | ||
| if (oString) | ||
| o = o.split(options.stringSeparator); | ||
| if (bString) | ||
| b = b.split(options.stringSeparator); | ||
| let results = []; | ||
| const regions = diff3MergeRegions(a, o, b); | ||
| let okBuffer = []; | ||
| function flushOk() { | ||
| if (okBuffer.length) { | ||
| results.push({ ok: okBuffer }); | ||
| } | ||
| okBuffer = []; | ||
| } | ||
| function isFalseConflict(a2, b2) { | ||
| if (a2.length !== b2.length) | ||
| return false; | ||
| for (let i = 0; i < a2.length; i++) { | ||
| if (a2[i] !== b2[i]) | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| regions.forEach((region) => { | ||
| if (region.stable) { | ||
| okBuffer.push(...region.bufferContent); | ||
| } else { | ||
| if (options.excludeFalseConflicts && isFalseConflict(region.aContent, region.bContent)) { | ||
| okBuffer.push(...region.aContent); | ||
| } else { | ||
| flushOk(); | ||
| results.push({ | ||
| conflict: { | ||
| a: region.aContent, | ||
| aIndex: region.aStart, | ||
| o: region.oContent, | ||
| oIndex: region.oStart, | ||
| b: region.bContent, | ||
| bIndex: region.bStart | ||
| } | ||
| }); | ||
| } | ||
| } | ||
| }); | ||
| flushOk(); | ||
| return results; | ||
| } | ||
| function mergeDiff3(a, o, b, options) { | ||
| let defaults = { | ||
| excludeFalseConflicts: true, | ||
| stringSeparator: /\s+/, | ||
| label: {} | ||
| }; | ||
| options = Object.assign(defaults, options); | ||
| const mergeResult = diff3Merge(a, o, b, options); | ||
| let conflict = false; | ||
| let lines = []; | ||
| mergeResult.forEach((result) => { | ||
| if (result.ok) { | ||
| lines = lines.concat(result.ok); | ||
| } else if (result.conflict) { | ||
| conflict = true; | ||
| lines.push(`<<<<<<<${options.label.a ? ` ${options.label.a}` : ""}`); | ||
| lines = lines.concat(result.conflict.a); | ||
| lines.push(`|||||||${options.label.o ? ` ${options.label.o}` : ""}`); | ||
| lines = lines.concat(result.conflict.o); | ||
| lines.push("======="); | ||
| lines = lines.concat(result.conflict.b); | ||
| lines.push(`>>>>>>>${options.label.b ? ` ${options.label.b}` : ""}`); | ||
| } | ||
| }); | ||
| return { | ||
| conflict, | ||
| result: lines | ||
| }; | ||
| } | ||
| function merge(a, o, b, options) { | ||
| let defaults = { | ||
| excludeFalseConflicts: true, | ||
| stringSeparator: /\s+/ | ||
| }; | ||
| options = Object.assign(defaults, options); | ||
| const merger = diff3Merge(a, o, b, options); | ||
| let conflict = false; | ||
| let lines = []; | ||
| for (let i = 0; i < merger.length; i++) { | ||
| const item = merger[i]; | ||
| if (item.ok) { | ||
| lines = lines.concat(item.ok); | ||
| } else { | ||
| conflict = true; | ||
| lines = lines.concat(["\n<<<<<<<<<\n"], item.conflict.a, ["\n=========\n"], item.conflict.b, ["\n>>>>>>>>>\n"]); | ||
| } | ||
| } | ||
| return { | ||
| conflict, | ||
| result: lines | ||
| }; | ||
| } | ||
| function mergeDigIn(a, o, b, options) { | ||
| let defaults = { | ||
| excludeFalseConflicts: false, | ||
| stringSeparator: /\s+/ | ||
| }; | ||
| options = Object.assign(defaults, options); | ||
| const merger = diff3Merge(a, o, b, options); | ||
| let conflict = false; | ||
| let lines = []; | ||
| for (let i = 0; i < merger.length; i++) { | ||
| const item = merger[i]; | ||
| if (item.ok) { | ||
| lines = lines.concat(item.ok); | ||
| } else { | ||
| const c = diffComm(item.conflict.a, item.conflict.b); | ||
| for (let j = 0; j < c.length; j++) { | ||
| let inner = c[j]; | ||
| if (inner.common) { | ||
| lines = lines.concat(inner.common); | ||
| } else { | ||
| conflict = true; | ||
| lines = lines.concat(["\n<<<<<<<<<\n"], inner.buffer1, ["\n=========\n"], inner.buffer2, ["\n>>>>>>>>>\n"]); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return { | ||
| conflict, | ||
| result: lines | ||
| }; | ||
| } | ||
| function patch(buffer, patch2) { | ||
| let result = []; | ||
| let currOffset = 0; | ||
| function advanceTo(targetOffset) { | ||
| while (currOffset < targetOffset) { | ||
| result.push(buffer[currOffset]); | ||
| currOffset++; | ||
| } | ||
| } | ||
| for (let chunkIndex = 0; chunkIndex < patch2.length; chunkIndex++) { | ||
| let chunk = patch2[chunkIndex]; | ||
| advanceTo(chunk.buffer1.offset); | ||
| for (let itemIndex = 0; itemIndex < chunk.buffer2.chunk.length; itemIndex++) { | ||
| result.push(chunk.buffer2.chunk[itemIndex]); | ||
| } | ||
| currOffset += chunk.buffer1.length; | ||
| } | ||
| advanceTo(buffer.length); | ||
| return result; | ||
| } | ||
| function stripPatch(patch2) { | ||
| return patch2.map((chunk) => ({ | ||
| buffer1: { offset: chunk.buffer1.offset, length: chunk.buffer1.length }, | ||
| buffer2: { chunk: chunk.buffer2.chunk } | ||
| })); | ||
| } | ||
| function invertPatch(patch2) { | ||
| return patch2.map((chunk) => ({ | ||
| buffer1: chunk.buffer2, | ||
| buffer2: chunk.buffer1 | ||
| })); | ||
| } | ||
| return node_diff3_exports; | ||
| })(); | ||
| //# sourceMappingURL=index.iife.js.map |
| { | ||
| "version": 3, | ||
| "sources": ["../index.mjs"], | ||
| "sourcesContent": ["export {\n LCS,\n diffComm,\n diffIndices,\n diffPatch,\n diff3MergeRegions,\n diff3Merge,\n mergeDiff3,\n merge,\n mergeDigIn,\n patch,\n stripPatch,\n invertPatch\n};\n\n\n// Text diff algorithm following Hunt and McIlroy 1976.\n// J. W. Hunt and M. D. McIlroy, An algorithm for differential buffer\n// comparison, Bell Telephone Laboratories CSTR #41 (1976)\n// http://www.cs.dartmouth.edu/~doug/\n// https://en.wikipedia.org/wiki/Longest_common_subsequence_problem\n//\n// Expects two arrays, finds longest common sequence\nfunction LCS(buffer1, buffer2) {\n\n let equivalenceClasses = {};\n for (let j = 0; j < buffer2.length; j++) {\n const item = buffer2[j];\n if (equivalenceClasses[item]) {\n equivalenceClasses[item].push(j);\n } else {\n equivalenceClasses[item] = [j];\n }\n }\n\n const NULLRESULT = { buffer1index: -1, buffer2index: -1, chain: null };\n let candidates = [NULLRESULT];\n\n for (let i = 0; i < buffer1.length; i++) {\n const item = buffer1[i];\n const buffer2indices = equivalenceClasses[item] || [];\n let r = 0;\n let c = candidates[0];\n\n for (let jx = 0; jx < buffer2indices.length; jx++) {\n const j = buffer2indices[jx];\n\n let s;\n for (s = r; s < candidates.length; s++) {\n if ((candidates[s].buffer2index < j) && ((s === candidates.length - 1) || (candidates[s + 1].buffer2index > j))) {\n break;\n }\n }\n\n if (s < candidates.length) {\n const newCandidate = { buffer1index: i, buffer2index: j, chain: candidates[s] };\n if (r === candidates.length) {\n candidates.push(c);\n } else {\n candidates[r] = c;\n }\n r = s + 1;\n c = newCandidate;\n if (r === candidates.length) {\n break; // no point in examining further (j)s\n }\n }\n }\n\n candidates[r] = c;\n }\n\n // At this point, we know the LCS: it's in the reverse of the\n // linked-list through .chain of candidates[candidates.length - 1].\n\n return candidates[candidates.length - 1];\n}\n\n\n// We apply the LCS to build a 'comm'-style picture of the\n// differences between buffer1 and buffer2.\nfunction diffComm(buffer1, buffer2) {\n const lcs = LCS(buffer1, buffer2);\n let result = [];\n let tail1 = buffer1.length;\n let tail2 = buffer2.length;\n let common = {common: []};\n\n function processCommon() {\n if (common.common.length) {\n common.common.reverse();\n result.push(common);\n common = {common: []};\n }\n }\n\n for (let candidate = lcs; candidate !== null; candidate = candidate.chain) {\n let different = {buffer1: [], buffer2: []};\n\n while (--tail1 > candidate.buffer1index) {\n different.buffer1.push(buffer1[tail1]);\n }\n\n while (--tail2 > candidate.buffer2index) {\n different.buffer2.push(buffer2[tail2]);\n }\n\n if (different.buffer1.length || different.buffer2.length) {\n processCommon();\n different.buffer1.reverse();\n different.buffer2.reverse();\n result.push(different);\n }\n\n if (tail1 >= 0) {\n common.common.push(buffer1[tail1]);\n }\n }\n\n processCommon();\n\n result.reverse();\n return result;\n}\n\n\n// We apply the LCS to give a simple representation of the\n// offsets and lengths of mismatched chunks in the input\n// buffers. This is used by diff3MergeRegions.\nfunction diffIndices(buffer1, buffer2) {\n const lcs = LCS(buffer1, buffer2);\n let result = [];\n let tail1 = buffer1.length;\n let tail2 = buffer2.length;\n\n for (let candidate = lcs; candidate !== null; candidate = candidate.chain) {\n const mismatchLength1 = tail1 - candidate.buffer1index - 1;\n const mismatchLength2 = tail2 - candidate.buffer2index - 1;\n tail1 = candidate.buffer1index;\n tail2 = candidate.buffer2index;\n\n if (mismatchLength1 || mismatchLength2) {\n result.push({\n buffer1: [tail1 + 1, mismatchLength1],\n buffer1Content: buffer1.slice(tail1 + 1, tail1 + 1 + mismatchLength1),\n buffer2: [tail2 + 1, mismatchLength2],\n buffer2Content: buffer2.slice(tail2 + 1, tail2 + 1 + mismatchLength2)\n });\n }\n }\n\n result.reverse();\n return result;\n}\n\n\n// We apply the LCS to build a JSON representation of a\n// diff(1)-style patch.\nfunction diffPatch(buffer1, buffer2) {\n const lcs = LCS(buffer1, buffer2);\n let result = [];\n let tail1 = buffer1.length;\n let tail2 = buffer2.length;\n\n function chunkDescription(buffer, offset, length) {\n let chunk = [];\n for (let i = 0; i < length; i++) {\n chunk.push(buffer[offset + i]);\n }\n return {\n offset: offset,\n length: length,\n chunk: chunk\n };\n }\n\n for (let candidate = lcs; candidate !== null; candidate = candidate.chain) {\n const mismatchLength1 = tail1 - candidate.buffer1index - 1;\n const mismatchLength2 = tail2 - candidate.buffer2index - 1;\n tail1 = candidate.buffer1index;\n tail2 = candidate.buffer2index;\n\n if (mismatchLength1 || mismatchLength2) {\n result.push({\n buffer1: chunkDescription(buffer1, candidate.buffer1index + 1, mismatchLength1),\n buffer2: chunkDescription(buffer2, candidate.buffer2index + 1, mismatchLength2)\n });\n }\n }\n\n result.reverse();\n return result;\n}\n\n\n// Given three buffers, A, O, and B, where both A and B are\n// independently derived from O, returns a fairly complicated\n// internal representation of merge decisions it's taken. The\n// interested reader may wish to consult\n//\n// Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce.\n// 'A Formal Investigation of ' In Arvind and Prasad,\n// editors, Foundations of Software Technology and Theoretical\n// Computer Science (FSTTCS), December 2007.\n//\n// (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf)\n//\nfunction diff3MergeRegions(a, o, b) {\n\n // \"hunks\" are array subsets where `a` or `b` are different from `o`\n // https://www.gnu.org/software/diffutils/manual/html_node/diff3-Hunks.html\n let hunks = [];\n function addHunk(h, ab) {\n hunks.push({\n ab: ab,\n oStart: h.buffer1[0],\n oLength: h.buffer1[1], // length of o to remove\n abStart: h.buffer2[0],\n abLength: h.buffer2[1] // length of a/b to insert\n // abContent: (ab === 'a' ? a : b).slice(h.buffer2[0], h.buffer2[0] + h.buffer2[1])\n });\n }\n\n diffIndices(o, a).forEach(item => addHunk(item, 'a'));\n diffIndices(o, b).forEach(item => addHunk(item, 'b'));\n hunks.sort((x,y) => x.oStart - y.oStart);\n\n let results = [];\n let currOffset = 0;\n\n function advanceTo(endOffset) {\n if (endOffset > currOffset) {\n results.push({\n stable: true,\n buffer: 'o',\n bufferStart: currOffset,\n bufferLength: endOffset - currOffset,\n bufferContent: o.slice(currOffset, endOffset)\n });\n currOffset = endOffset;\n }\n }\n\n while (hunks.length) {\n let hunk = hunks.shift();\n let regionStart = hunk.oStart;\n let regionEnd = hunk.oStart + hunk.oLength;\n let regionHunks = [hunk];\n advanceTo(regionStart);\n\n // Try to pull next overlapping hunk into this region\n while (hunks.length) {\n const nextHunk = hunks[0];\n const nextHunkStart = nextHunk.oStart;\n if (nextHunkStart > regionEnd) break; // no overlap\n\n regionEnd = Math.max(regionEnd, nextHunkStart + nextHunk.oLength);\n regionHunks.push(hunks.shift());\n }\n\n if (regionHunks.length === 1) {\n // Only one hunk touches this region, meaning that there is no conflict here.\n // Either `a` or `b` is inserting into a region of `o` unchanged by the other.\n if (hunk.abLength > 0) {\n const buffer = (hunk.ab === 'a' ? a : b);\n results.push({\n stable: true,\n buffer: hunk.ab,\n bufferStart: hunk.abStart,\n bufferLength: hunk.abLength,\n bufferContent: buffer.slice(hunk.abStart, hunk.abStart + hunk.abLength)\n });\n }\n } else {\n // A true a/b conflict. Determine the bounds involved from `a`, `o`, and `b`.\n // Effectively merge all the `a` hunks into one giant hunk, then do the\n // same for the `b` hunks; then, correct for skew in the regions of `o`\n // that each side changed, and report appropriate spans for the three sides.\n let bounds = {\n a: [a.length, -1, o.length, -1],\n b: [b.length, -1, o.length, -1]\n };\n while (regionHunks.length) {\n hunk = regionHunks.shift();\n const oStart = hunk.oStart;\n const oEnd = oStart + hunk.oLength;\n const abStart = hunk.abStart;\n const abEnd = abStart + hunk.abLength;\n let b = bounds[hunk.ab];\n b[0] = Math.min(abStart, b[0]);\n b[1] = Math.max(abEnd, b[1]);\n b[2] = Math.min(oStart, b[2]);\n b[3] = Math.max(oEnd, b[3]);\n }\n\n const aStart = bounds.a[0] + (regionStart - bounds.a[2]);\n const aEnd = bounds.a[1] + (regionEnd - bounds.a[3]);\n const bStart = bounds.b[0] + (regionStart - bounds.b[2]);\n const bEnd = bounds.b[1] + (regionEnd - bounds.b[3]);\n\n let result = {\n stable: false,\n aStart: aStart,\n aLength: aEnd - aStart,\n aContent: a.slice(aStart, aEnd),\n oStart: regionStart,\n oLength: regionEnd - regionStart,\n oContent: o.slice(regionStart, regionEnd),\n bStart: bStart,\n bLength: bEnd - bStart,\n bContent: b.slice(bStart, bEnd)\n };\n results.push(result);\n }\n currOffset = regionEnd;\n }\n\n advanceTo(o.length);\n\n return results;\n}\n\n\n// Applies the output of diff3MergeRegions to actually\n// construct the merged buffer; the returned result alternates\n// between 'ok' and 'conflict' blocks.\n// A \"false conflict\" is where `a` and `b` both change the same from `o`\nfunction diff3Merge(a, o, b, options) {\n let defaults = {\n excludeFalseConflicts: true,\n stringSeparator: /\\s+/\n };\n options = Object.assign(defaults, options);\n\n const aString = (typeof a === 'string');\n const oString = (typeof o === 'string');\n const bString = (typeof b === 'string');\n\n if (aString) a = a.split(options.stringSeparator);\n if (oString) o = o.split(options.stringSeparator);\n if (bString) b = b.split(options.stringSeparator);\n\n let results = [];\n const regions = diff3MergeRegions(a, o, b);\n\n let okBuffer = [];\n function flushOk() {\n if (okBuffer.length) {\n results.push({ ok: okBuffer });\n }\n okBuffer = [];\n }\n\n function isFalseConflict(a, b) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n regions.forEach(region => {\n if (region.stable) {\n okBuffer.push(...region.bufferContent);\n } else {\n if (options.excludeFalseConflicts && isFalseConflict(region.aContent, region.bContent)) {\n okBuffer.push(...region.aContent);\n } else {\n flushOk();\n results.push({\n conflict: {\n a: region.aContent,\n aIndex: region.aStart,\n o: region.oContent,\n oIndex: region.oStart,\n b: region.bContent,\n bIndex: region.bStart\n }\n });\n }\n }\n });\n\n flushOk();\n return results;\n}\n\nfunction mergeDiff3(a, o, b, options) {\n let defaults = {\n excludeFalseConflicts: true,\n stringSeparator: /\\s+/,\n label: {}\n };\n options = Object.assign(defaults, options);\n\n const mergeResult = diff3Merge(a, o, b, options);\n\n let conflict = false;\n let lines = [];\n\n mergeResult.forEach(result => {\n if (result.ok) {\n lines = lines.concat(result.ok);\n } else if (result.conflict) {\n conflict = true;\n lines.push(`<<<<<<<${options.label.a ? ` ${options.label.a}` : ''}`);\n lines = lines.concat(result.conflict.a);\n lines.push(`|||||||${options.label.o ? ` ${options.label.o}` : ''}`);\n lines = lines.concat(result.conflict.o);\n lines.push('=======');\n lines = lines.concat(result.conflict.b);\n lines.push(`>>>>>>>${options.label.b ? ` ${options.label.b}` : ''}`);\n }\n });\n\n return {\n conflict: conflict,\n result: lines\n };\n}\n\nfunction merge(a, o, b, options) {\n let defaults = {\n excludeFalseConflicts: true,\n stringSeparator: /\\s+/\n };\n options = Object.assign(defaults, options);\n\n const merger = diff3Merge(a, o, b, options);\n let conflict = false;\n let lines = [];\n for (let i = 0; i < merger.length; i++) {\n const item = merger[i];\n if (item.ok) {\n lines = lines.concat(item.ok);\n } else {\n conflict = true;\n lines = lines.concat(\n ['\\n<<<<<<<<<\\n'], item.conflict.a,\n ['\\n=========\\n'], item.conflict.b,\n ['\\n>>>>>>>>>\\n']\n );\n }\n }\n return {\n conflict: conflict,\n result: lines\n };\n}\n\n\nfunction mergeDigIn(a, o, b, options) {\n let defaults = {\n excludeFalseConflicts: false,\n stringSeparator: /\\s+/\n };\n options = Object.assign(defaults, options);\n\n const merger = diff3Merge(a, o, b, options);\n let conflict = false;\n let lines = [];\n for (let i = 0; i < merger.length; i++) {\n const item = merger[i];\n if (item.ok) {\n lines = lines.concat(item.ok);\n } else {\n const c = diffComm(item.conflict.a, item.conflict.b);\n for (let j = 0; j < c.length; j++) {\n let inner = c[j];\n if (inner.common) {\n lines = lines.concat(inner.common);\n } else {\n conflict = true;\n lines = lines.concat(\n ['\\n<<<<<<<<<\\n'], inner.buffer1,\n ['\\n=========\\n'], inner.buffer2,\n ['\\n>>>>>>>>>\\n']\n );\n }\n }\n }\n }\n return {\n conflict: conflict,\n result: lines\n };\n}\n\n\n// Applies a patch to a buffer.\n// Given buffer1 and buffer2, `patch(buffer1, diffPatch(buffer1, buffer2))` should give buffer2.\nfunction patch(buffer, patch) {\n let result = [];\n let currOffset = 0;\n\n function advanceTo(targetOffset) {\n while (currOffset < targetOffset) {\n result.push(buffer[currOffset]);\n currOffset++;\n }\n }\n\n for (let chunkIndex = 0; chunkIndex < patch.length; chunkIndex++) {\n let chunk = patch[chunkIndex];\n advanceTo(chunk.buffer1.offset);\n for (let itemIndex = 0; itemIndex < chunk.buffer2.chunk.length; itemIndex++) {\n result.push(chunk.buffer2.chunk[itemIndex]);\n }\n currOffset += chunk.buffer1.length;\n }\n\n advanceTo(buffer.length);\n return result;\n}\n\n\n// Takes the output of diffPatch(), and removes extra information from it.\n// It can still be used by patch(), below, but can no longer be inverted.\nfunction stripPatch(patch) {\n return patch.map(chunk => ({\n buffer1: { offset: chunk.buffer1.offset, length: chunk.buffer1.length },\n buffer2: { chunk: chunk.buffer2.chunk }\n }));\n}\n\n\n// Takes the output of diffPatch(), and inverts the sense of it, so that it\n// can be applied to buffer2 to give buffer1 rather than the other way around.\nfunction invertPatch(patch) {\n return patch.map(chunk => ({\n buffer1: chunk.buffer2,\n buffer2: chunk.buffer1\n }));\n}\n"], | ||
| "mappings": "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", | ||
| "names": [] | ||
| } |
+40
-21
| { | ||
| "name": "node-diff3", | ||
| "version": "2.1.2", | ||
| "version": "3.0.0", | ||
| "license": "MIT", | ||
| "repository": "bhousel/node-diff3", | ||
| "repository": "github:bhousel/node-diff3", | ||
| "description": "A node.js module for text diffing and three-way-merge.", | ||
| "contributors": [ | ||
| "Bryan Housel <bhousel@gmail.com> (https://github.com/bhousel)" | ||
| ], | ||
| "keywords": [ | ||
| "diff", | ||
| "diff3", | ||
| "diffutils", | ||
| "gnu", | ||
| "javascript", | ||
| "merge", | ||
| "nodejs", | ||
| "javascript" | ||
| "patch" | ||
| ], | ||
| "contributors": [ | ||
| "Bryan Housel <bhousel@gmail.com> (https://github.com/bhousel)" | ||
| "files": [ | ||
| "index.mjs", | ||
| "index.d.ts", | ||
| "dist/" | ||
| ], | ||
| "main": "dist/index.js", | ||
| "module": "index.mjs", | ||
| "types": "index.d.ts", | ||
| "devDependencies": { | ||
| "@rollup/plugin-buble": "^0.21.3", | ||
| "coveralls": "^3.1.0", | ||
| "eslint": "^7.25.0", | ||
| "npm-run-all": "^4.1.5", | ||
| "rollup": "^2.47.0", | ||
| "tap": "^15.0.6" | ||
| "type": "module", | ||
| "source": "./index.mjs", | ||
| "types": "./index.d.ts", | ||
| "main": "./dist/index.cjs", | ||
| "module": "./index.mjs", | ||
| "exports": { | ||
| "import": "./index.mjs", | ||
| "require": "./dist/index.cjs" | ||
| }, | ||
| "scripts": { | ||
| "all": "npm run test", | ||
| "build": "run-s dist:**", | ||
| "dist:js": "rollup --config config/rollup.config.js", | ||
| "dist:es5": "rollup --config config/rollup.config.es5.js", | ||
| "all": "run-s clean test", | ||
| "clean": "shx rm -rf dist", | ||
| "build": "run-p build:**", | ||
| "build:browser": "esbuild ./index.mjs --platform=browser --format=iife --global-name=Diff3 --bundle --sourcemap --outfile=./dist/index.iife.js", | ||
| "build:cjs": "esbuild ./index.mjs --platform=node --format=cjs --sourcemap --outfile=./dist/index.cjs", | ||
| "lint": "eslint index.mjs test/*.js", | ||
| "test": "npm run lint && npm run build && tap --reporter terse --no-check-coverage test/*.js" | ||
| "tap": "c8 tap --reporter terse --no-cov test/*.js", | ||
| "test": "run-s build lint tap" | ||
| }, | ||
| "devDependencies": { | ||
| "c8": "^7.7.3", | ||
| "esbuild": "^0.12.9", | ||
| "eslint": "^7.29.0", | ||
| "npm-run-all": "^4.1.5", | ||
| "shx": "^0.3.3", | ||
| "tap": "^15.0.9" | ||
| }, | ||
| "publishConfig": { | ||
| "access": "public" | ||
| }, | ||
| "engines": { | ||
| "node": ">=10" | ||
| "node": "^12.20.0 || ^14.13.1 || >=16.0.0" | ||
| } | ||
| } |
+21
-20
@@ -17,2 +17,4 @@ [](https://github.com/bhousel/node-diff3/actions?query=workflow%3A%22build%22) | ||
| ### Use in Node | ||
| To install node-diff3 as a dependency in your project: | ||
@@ -23,33 +25,32 @@ ```bash | ||
| **node-diff3** is distributed in both UMD and ES6 module formats for maxmimum compatibility. ([Read more about Javascript module formats](https://dev.to/iggredible/what-the-heck-are-cjs-amd-umd-and-esm-ikm)) | ||
| * `index.mjs` - ES6 module | ||
| * `dist/index.js` - UMD module, ES6 syntax | ||
| * `dist/index.es5.js` - UMD module, ES5 syntax | ||
| **node-diff3** is distributed in CJS and ESM module formats for maxmimum compatibility. ([Read more about Javascript module formats](https://dev.to/iggredible/what-the-heck-are-cjs-amd-umd-and-esm-ikm)) | ||
| Whether you require or import it, it should just work. | ||
| ```js | ||
| const Diff3 = require('node-diff3'); // UMD import all | ||
| const diff3Merge = require('node-diff3').diff3Merge; // UMD import named | ||
| const Diff3 = require('node-diff3'); // CommonJS import all | ||
| const diff3Merge = require('node-diff3').diff3Merge; // CommonJS import named | ||
| // or | ||
| import * as Diff3 from 'node-diff3'; // ES6 import all | ||
| import { diff3Merge } from 'node-diff3'; // ES6 import named | ||
| import * as Diff3 from 'node-diff3'; // ESM import all | ||
| import { diff3Merge } from 'node-diff3'; // ESM import named | ||
| ``` | ||
| You can also use **node-diff3** directly in a web browser. A good way to do this is to fetch the file from the [jsDelivr CDN](https://www.jsdelivr.com/), which can even deliver minified versions. | ||
| ### Use in Browsers | ||
| The latest versions of many web browsers now support [ES6 modules in script tags](https://caniuse.com/#feat=es6-module) like this: | ||
| ```html | ||
| <script type="module" src="https://cdn.jsdelivr.net/npm/node-diff3@2/index.min.mjs"></script> | ||
| ``` | ||
| You can also use **node-diff3** directly in a web browser. A good way to do this is to fetch the ["iife"](https://esbuild.github.io/api/#format-iife) bundle from the [jsDelivr CDN](https://www.jsdelivr.com/), which can even deliver minified versions. | ||
| Older versions of modern ES6-capable browsers can still load the UMD build: | ||
| When you load this file in a `<script>` tag, you'll get a `Diff3` global to use elsewhere in your scripts: | ||
| ```html | ||
| <script src="https://cdn.jsdelivr.net/npm/node-diff3@2/dist/index.min.js"></script> | ||
| <head> | ||
| <script src="https://cdn.jsdelivr.net/npm/node-diff3@3.0/dist/index.iife.min.js"></script> | ||
| </head> | ||
| … | ||
| <script> | ||
| const o = ['AA', 'ZZ', '00', 'M', '99']; | ||
| const a = ['AA', 'a', 'b', 'c', 'ZZ', 'new', '00', 'a', 'a', 'M', '99']; | ||
| const b = ['AA', 'a', 'd', 'c', 'ZZ', '11', 'M', 'z', 'z', '99']; | ||
| const result = Diff3.diff3Merge(a, o, b); | ||
| </script> | ||
| ``` | ||
| Or if you need to support even older browsers like Internet Explorer, fetch the ES5 version: | ||
| ```html | ||
| <script src="https://cdn.jsdelivr.net/npm/node-diff3@2/dist/index.es5.min.js"></script> | ||
| ``` | ||
| 👉 This project uses modern JavaScript syntax for use in supported node versions and modern browsers. If you need support for legacy environments like ES5 or Internet Explorer, you'll need to build your own bundle with something like [Babel](https://babeljs.io/docs/en/index.html). | ||
@@ -56,0 +57,0 @@ |
-63
| { | ||
| "env": { | ||
| "node": true, | ||
| "es6": true | ||
| }, | ||
| "parserOptions": { | ||
| "ecmaVersion": 6, | ||
| "sourceType": "module" | ||
| }, | ||
| "extends": [ | ||
| "eslint:recommended" | ||
| ], | ||
| "rules": { | ||
| "dot-notation": "error", | ||
| "eqeqeq": ["error", "smart"], | ||
| "indent": ["off", 4], | ||
| "keyword-spacing": "error", | ||
| "linebreak-style": ["error", "unix"], | ||
| "no-caller": "error", | ||
| "no-catch-shadow": "error", | ||
| "no-console": "warn", | ||
| "no-div-regex": "error", | ||
| "no-extend-native": "error", | ||
| "no-extra-bind": "error", | ||
| "no-floating-decimal": "error", | ||
| "no-implied-eval": "error", | ||
| "no-invalid-this": "error", | ||
| "no-iterator": "error", | ||
| "no-labels": "error", | ||
| "no-label-var": "error", | ||
| "no-lone-blocks": "error", | ||
| "no-loop-func": "error", | ||
| "no-multi-str": "error", | ||
| "no-native-reassign": "error", | ||
| "no-new": "error", | ||
| "no-new-func": "error", | ||
| "no-new-wrappers": "error", | ||
| "no-octal": "error", | ||
| "no-octal-escape": "error", | ||
| "no-process-env": "error", | ||
| "no-proto": "error", | ||
| "no-return-assign": "off", | ||
| "no-script-url": "error", | ||
| "no-self-compare": "error", | ||
| "no-sequences": "error", | ||
| "no-shadow": "off", | ||
| "no-shadow-restricted-names": "error", | ||
| "no-throw-literal": "error", | ||
| "no-unneeded-ternary": "error", | ||
| "no-unused-expressions": "error", | ||
| "no-unexpected-multiline": "error", | ||
| "no-unused-vars": "warn", | ||
| "no-void": "error", | ||
| "no-warning-comments": "warn", | ||
| "no-with": "error", | ||
| "no-use-before-define": ["off", "nofunc"], | ||
| "semi": ["error", "always"], | ||
| "semi-spacing": "error", | ||
| "space-unary-ops": "error", | ||
| "wrap-regex": "off", | ||
| "quotes": ["error", "single"] | ||
| } | ||
| } |
-88
| # What's New | ||
| **node-diff3** is an open source project. You can submit bug reports, help out, | ||
| or learn more by visiting our project page on GitHub: :octocat: https://github.com/bhousel/node-diff3 | ||
| Please star our project on GitHub to show your support! :star: | ||
| _Breaking changes, which may affect downstream projects, are marked with a_ :warning: | ||
| <!-- | ||
| # A.B.C | ||
| ##### YYYY-MMM-DD | ||
| * | ||
| [#xxx]: https://github.com/bhousel/node-diff3/issues/xxx | ||
| --> | ||
| ## 2.1.2 | ||
| ##### 2021-may-04 | ||
| * ([#44]) Fix "Type 'Buffer' is not generic." TypeScript error | ||
| [#44]: https://github.com/bhousel/node-diff3/issues/44 | ||
| ## 2.1.1 | ||
| ##### 2021-apr-26 | ||
| * ([#42]) Fix typo and add TypeScript definition for `patch` | ||
| [#42]: https://github.com/bhousel/node-diff3/issues/42 | ||
| ## 2.1.0 | ||
| ##### 2020-jul-17 | ||
| * ([#39]) Added a `mergeDiff3` function to help print out Diff3 merge result | ||
| * ([#37]) Fixed error in TypeScript definition for `MergeRegion` | ||
| [#39]: https://github.com/bhousel/node-diff3/issues/39 | ||
| [#37]: https://github.com/bhousel/node-diff3/issues/37 | ||
| ## 2.0.1 | ||
| ##### 2020-may-18 | ||
| * ([#35]) Added TypeScript declaration file | ||
| [#35]: https://github.com/bhousel/node-diff3/issues/35 | ||
| ## 2.0.0 | ||
| ##### 2020-apr-08 | ||
| * :warning: Several breaking changes: | ||
| * `invertPatch` now returns a copy instead of modifying patch in place ([#33]) | ||
| * `diff3Merge`, `merge`, `mergeDigIn` now accept `options` object instead of `excludeFalseConflicts` argument | ||
| * Strings are split on whitespace by default. Use `stringSeparator` option to override this behavior. ([#9]) | ||
| * `diff3MergeIndices` renamed to `diff3MergeRegions` | ||
| * Add test coverage for everything ([#3]) | ||
| [#33]: https://github.com/bhousel/node-diff3/issues/33 | ||
| [#9]: https://github.com/bhousel/node-diff3/issues/9 | ||
| [#3]: https://github.com/bhousel/node-diff3/issues/3 | ||
| ## 1.0.0 | ||
| ##### 2017-nov-21 | ||
| * Pushing major version bump due to change in npm ownership | ||
| ## 0.1.0 | ||
| ##### 2017-oct-24 | ||
| * :warning: Distribute both ES6 `index.mjs` and CJS `index.js` | ||
| * Fix improper hunk sorting ([iD#3058]) | ||
| * Add tests, TravisCI | ||
| [iD#3058]: https://github.com/openstreetmap/iD/issues/3058 | ||
| ## 0.0.1 | ||
| ##### 2014-aug-21 | ||
| * Initial release |
| (function (global, factory) { | ||
| typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
| typeof define === 'function' && define.amd ? define(['exports'], factory) : | ||
| (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Diff3 = {})); | ||
| }(this, (function (exports) { 'use strict'; | ||
| // Text diff algorithm following Hunt and McIlroy 1976. | ||
| // J. W. Hunt and M. D. McIlroy, An algorithm for differential buffer | ||
| // comparison, Bell Telephone Laboratories CSTR #41 (1976) | ||
| // http://www.cs.dartmouth.edu/~doug/ | ||
| // https://en.wikipedia.org/wiki/Longest_common_subsequence_problem | ||
| // | ||
| // Expects two arrays, finds longest common sequence | ||
| function LCS(buffer1, buffer2) { | ||
| var equivalenceClasses = {}; | ||
| for (var j = 0; j < buffer2.length; j++) { | ||
| var item = buffer2[j]; | ||
| if (equivalenceClasses[item]) { | ||
| equivalenceClasses[item].push(j); | ||
| } else { | ||
| equivalenceClasses[item] = [j]; | ||
| } | ||
| } | ||
| var NULLRESULT = { buffer1index: -1, buffer2index: -1, chain: null }; | ||
| var candidates = [NULLRESULT]; | ||
| for (var i = 0; i < buffer1.length; i++) { | ||
| var item$1 = buffer1[i]; | ||
| var buffer2indices = equivalenceClasses[item$1] || []; | ||
| var r = 0; | ||
| var c = candidates[0]; | ||
| for (var jx = 0; jx < buffer2indices.length; jx++) { | ||
| var j$1 = buffer2indices[jx]; | ||
| var s = (void 0); | ||
| for (s = r; s < candidates.length; s++) { | ||
| if ((candidates[s].buffer2index < j$1) && ((s === candidates.length - 1) || (candidates[s + 1].buffer2index > j$1))) { | ||
| break; | ||
| } | ||
| } | ||
| if (s < candidates.length) { | ||
| var newCandidate = { buffer1index: i, buffer2index: j$1, chain: candidates[s] }; | ||
| if (r === candidates.length) { | ||
| candidates.push(c); | ||
| } else { | ||
| candidates[r] = c; | ||
| } | ||
| r = s + 1; | ||
| c = newCandidate; | ||
| if (r === candidates.length) { | ||
| break; // no point in examining further (j)s | ||
| } | ||
| } | ||
| } | ||
| candidates[r] = c; | ||
| } | ||
| // At this point, we know the LCS: it's in the reverse of the | ||
| // linked-list through .chain of candidates[candidates.length - 1]. | ||
| return candidates[candidates.length - 1]; | ||
| } | ||
| // We apply the LCS to build a 'comm'-style picture of the | ||
| // differences between buffer1 and buffer2. | ||
| function diffComm(buffer1, buffer2) { | ||
| var lcs = LCS(buffer1, buffer2); | ||
| var result = []; | ||
| var tail1 = buffer1.length; | ||
| var tail2 = buffer2.length; | ||
| var common = {common: []}; | ||
| function processCommon() { | ||
| if (common.common.length) { | ||
| common.common.reverse(); | ||
| result.push(common); | ||
| common = {common: []}; | ||
| } | ||
| } | ||
| for (var candidate = lcs; candidate !== null; candidate = candidate.chain) { | ||
| var different = {buffer1: [], buffer2: []}; | ||
| while (--tail1 > candidate.buffer1index) { | ||
| different.buffer1.push(buffer1[tail1]); | ||
| } | ||
| while (--tail2 > candidate.buffer2index) { | ||
| different.buffer2.push(buffer2[tail2]); | ||
| } | ||
| if (different.buffer1.length || different.buffer2.length) { | ||
| processCommon(); | ||
| different.buffer1.reverse(); | ||
| different.buffer2.reverse(); | ||
| result.push(different); | ||
| } | ||
| if (tail1 >= 0) { | ||
| common.common.push(buffer1[tail1]); | ||
| } | ||
| } | ||
| processCommon(); | ||
| result.reverse(); | ||
| return result; | ||
| } | ||
| // We apply the LCS to give a simple representation of the | ||
| // offsets and lengths of mismatched chunks in the input | ||
| // buffers. This is used by diff3MergeRegions. | ||
| function diffIndices(buffer1, buffer2) { | ||
| var lcs = LCS(buffer1, buffer2); | ||
| var result = []; | ||
| var tail1 = buffer1.length; | ||
| var tail2 = buffer2.length; | ||
| for (var candidate = lcs; candidate !== null; candidate = candidate.chain) { | ||
| var mismatchLength1 = tail1 - candidate.buffer1index - 1; | ||
| var mismatchLength2 = tail2 - candidate.buffer2index - 1; | ||
| tail1 = candidate.buffer1index; | ||
| tail2 = candidate.buffer2index; | ||
| if (mismatchLength1 || mismatchLength2) { | ||
| result.push({ | ||
| buffer1: [tail1 + 1, mismatchLength1], | ||
| buffer1Content: buffer1.slice(tail1 + 1, tail1 + 1 + mismatchLength1), | ||
| buffer2: [tail2 + 1, mismatchLength2], | ||
| buffer2Content: buffer2.slice(tail2 + 1, tail2 + 1 + mismatchLength2) | ||
| }); | ||
| } | ||
| } | ||
| result.reverse(); | ||
| return result; | ||
| } | ||
| // We apply the LCS to build a JSON representation of a | ||
| // diff(1)-style patch. | ||
| function diffPatch(buffer1, buffer2) { | ||
| var lcs = LCS(buffer1, buffer2); | ||
| var result = []; | ||
| var tail1 = buffer1.length; | ||
| var tail2 = buffer2.length; | ||
| function chunkDescription(buffer, offset, length) { | ||
| var chunk = []; | ||
| for (var i = 0; i < length; i++) { | ||
| chunk.push(buffer[offset + i]); | ||
| } | ||
| return { | ||
| offset: offset, | ||
| length: length, | ||
| chunk: chunk | ||
| }; | ||
| } | ||
| for (var candidate = lcs; candidate !== null; candidate = candidate.chain) { | ||
| var mismatchLength1 = tail1 - candidate.buffer1index - 1; | ||
| var mismatchLength2 = tail2 - candidate.buffer2index - 1; | ||
| tail1 = candidate.buffer1index; | ||
| tail2 = candidate.buffer2index; | ||
| if (mismatchLength1 || mismatchLength2) { | ||
| result.push({ | ||
| buffer1: chunkDescription(buffer1, candidate.buffer1index + 1, mismatchLength1), | ||
| buffer2: chunkDescription(buffer2, candidate.buffer2index + 1, mismatchLength2) | ||
| }); | ||
| } | ||
| } | ||
| result.reverse(); | ||
| return result; | ||
| } | ||
| // Given three buffers, A, O, and B, where both A and B are | ||
| // independently derived from O, returns a fairly complicated | ||
| // internal representation of merge decisions it's taken. The | ||
| // interested reader may wish to consult | ||
| // | ||
| // Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce. | ||
| // 'A Formal Investigation of ' In Arvind and Prasad, | ||
| // editors, Foundations of Software Technology and Theoretical | ||
| // Computer Science (FSTTCS), December 2007. | ||
| // | ||
| // (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf) | ||
| // | ||
| function diff3MergeRegions(a, o, b) { | ||
| // "hunks" are array subsets where `a` or `b` are different from `o` | ||
| // https://www.gnu.org/software/diffutils/manual/html_node/diff3-Hunks.html | ||
| var hunks = []; | ||
| function addHunk(h, ab) { | ||
| hunks.push({ | ||
| ab: ab, | ||
| oStart: h.buffer1[0], | ||
| oLength: h.buffer1[1], // length of o to remove | ||
| abStart: h.buffer2[0], | ||
| abLength: h.buffer2[1] // length of a/b to insert | ||
| // abContent: (ab === 'a' ? a : b).slice(h.buffer2[0], h.buffer2[0] + h.buffer2[1]) | ||
| }); | ||
| } | ||
| diffIndices(o, a).forEach(function (item) { return addHunk(item, 'a'); }); | ||
| diffIndices(o, b).forEach(function (item) { return addHunk(item, 'b'); }); | ||
| hunks.sort(function (x,y) { return x.oStart - y.oStart; }); | ||
| var results = []; | ||
| var currOffset = 0; | ||
| function advanceTo(endOffset) { | ||
| if (endOffset > currOffset) { | ||
| results.push({ | ||
| stable: true, | ||
| buffer: 'o', | ||
| bufferStart: currOffset, | ||
| bufferLength: endOffset - currOffset, | ||
| bufferContent: o.slice(currOffset, endOffset) | ||
| }); | ||
| currOffset = endOffset; | ||
| } | ||
| } | ||
| while (hunks.length) { | ||
| var hunk = hunks.shift(); | ||
| var regionStart = hunk.oStart; | ||
| var regionEnd = hunk.oStart + hunk.oLength; | ||
| var regionHunks = [hunk]; | ||
| advanceTo(regionStart); | ||
| // Try to pull next overlapping hunk into this region | ||
| while (hunks.length) { | ||
| var nextHunk = hunks[0]; | ||
| var nextHunkStart = nextHunk.oStart; | ||
| if (nextHunkStart > regionEnd) { break; } // no overlap | ||
| regionEnd = Math.max(regionEnd, nextHunkStart + nextHunk.oLength); | ||
| regionHunks.push(hunks.shift()); | ||
| } | ||
| if (regionHunks.length === 1) { | ||
| // Only one hunk touches this region, meaning that there is no conflict here. | ||
| // Either `a` or `b` is inserting into a region of `o` unchanged by the other. | ||
| if (hunk.abLength > 0) { | ||
| var buffer = (hunk.ab === 'a' ? a : b); | ||
| results.push({ | ||
| stable: true, | ||
| buffer: hunk.ab, | ||
| bufferStart: hunk.abStart, | ||
| bufferLength: hunk.abLength, | ||
| bufferContent: buffer.slice(hunk.abStart, hunk.abStart + hunk.abLength) | ||
| }); | ||
| } | ||
| } else { | ||
| // A true a/b conflict. Determine the bounds involved from `a`, `o`, and `b`. | ||
| // Effectively merge all the `a` hunks into one giant hunk, then do the | ||
| // same for the `b` hunks; then, correct for skew in the regions of `o` | ||
| // that each side changed, and report appropriate spans for the three sides. | ||
| var bounds = { | ||
| a: [a.length, -1, o.length, -1], | ||
| b: [b.length, -1, o.length, -1] | ||
| }; | ||
| while (regionHunks.length) { | ||
| hunk = regionHunks.shift(); | ||
| var oStart = hunk.oStart; | ||
| var oEnd = oStart + hunk.oLength; | ||
| var abStart = hunk.abStart; | ||
| var abEnd = abStart + hunk.abLength; | ||
| var b$1 = bounds[hunk.ab]; | ||
| b$1[0] = Math.min(abStart, b$1[0]); | ||
| b$1[1] = Math.max(abEnd, b$1[1]); | ||
| b$1[2] = Math.min(oStart, b$1[2]); | ||
| b$1[3] = Math.max(oEnd, b$1[3]); | ||
| } | ||
| var aStart = bounds.a[0] + (regionStart - bounds.a[2]); | ||
| var aEnd = bounds.a[1] + (regionEnd - bounds.a[3]); | ||
| var bStart = bounds.b[0] + (regionStart - bounds.b[2]); | ||
| var bEnd = bounds.b[1] + (regionEnd - bounds.b[3]); | ||
| var result = { | ||
| stable: false, | ||
| aStart: aStart, | ||
| aLength: aEnd - aStart, | ||
| aContent: a.slice(aStart, aEnd), | ||
| oStart: regionStart, | ||
| oLength: regionEnd - regionStart, | ||
| oContent: o.slice(regionStart, regionEnd), | ||
| bStart: bStart, | ||
| bLength: bEnd - bStart, | ||
| bContent: b.slice(bStart, bEnd) | ||
| }; | ||
| results.push(result); | ||
| } | ||
| currOffset = regionEnd; | ||
| } | ||
| advanceTo(o.length); | ||
| return results; | ||
| } | ||
| // Applies the output of diff3MergeRegions to actually | ||
| // construct the merged buffer; the returned result alternates | ||
| // between 'ok' and 'conflict' blocks. | ||
| // A "false conflict" is where `a` and `b` both change the same from `o` | ||
| function diff3Merge(a, o, b, options) { | ||
| var defaults = { | ||
| excludeFalseConflicts: true, | ||
| stringSeparator: /\s+/ | ||
| }; | ||
| options = Object.assign(defaults, options); | ||
| var aString = (typeof a === 'string'); | ||
| var oString = (typeof o === 'string'); | ||
| var bString = (typeof b === 'string'); | ||
| if (aString) { a = a.split(options.stringSeparator); } | ||
| if (oString) { o = o.split(options.stringSeparator); } | ||
| if (bString) { b = b.split(options.stringSeparator); } | ||
| var results = []; | ||
| var regions = diff3MergeRegions(a, o, b); | ||
| var okBuffer = []; | ||
| function flushOk() { | ||
| if (okBuffer.length) { | ||
| results.push({ ok: okBuffer }); | ||
| } | ||
| okBuffer = []; | ||
| } | ||
| function isFalseConflict(a, b) { | ||
| if (a.length !== b.length) { return false; } | ||
| for (var i = 0; i < a.length; i++) { | ||
| if (a[i] !== b[i]) { return false; } | ||
| } | ||
| return true; | ||
| } | ||
| regions.forEach(function (region) { | ||
| if (region.stable) { | ||
| okBuffer.push.apply(okBuffer, region.bufferContent); | ||
| } else { | ||
| if (options.excludeFalseConflicts && isFalseConflict(region.aContent, region.bContent)) { | ||
| okBuffer.push.apply(okBuffer, region.aContent); | ||
| } else { | ||
| flushOk(); | ||
| results.push({ | ||
| conflict: { | ||
| a: region.aContent, | ||
| aIndex: region.aStart, | ||
| o: region.oContent, | ||
| oIndex: region.oStart, | ||
| b: region.bContent, | ||
| bIndex: region.bStart | ||
| } | ||
| }); | ||
| } | ||
| } | ||
| }); | ||
| flushOk(); | ||
| return results; | ||
| } | ||
| function mergeDiff3(a, o, b, options) { | ||
| var defaults = { | ||
| excludeFalseConflicts: true, | ||
| stringSeparator: /\s+/, | ||
| label: {} | ||
| }; | ||
| options = Object.assign(defaults, options); | ||
| var mergeResult = diff3Merge(a, o, b, options); | ||
| var conflict = false; | ||
| var lines = []; | ||
| mergeResult.forEach(function (result) { | ||
| if (result.ok) { | ||
| lines = lines.concat(result.ok); | ||
| } else if (result.conflict) { | ||
| conflict = true; | ||
| lines.push(("<<<<<<<" + (options.label.a ? (" " + (options.label.a)) : ''))); | ||
| lines = lines.concat(result.conflict.a); | ||
| lines.push(("|||||||" + (options.label.o ? (" " + (options.label.o)) : ''))); | ||
| lines = lines.concat(result.conflict.o); | ||
| lines.push('======='); | ||
| lines = lines.concat(result.conflict.b); | ||
| lines.push((">>>>>>>" + (options.label.b ? (" " + (options.label.b)) : ''))); | ||
| } | ||
| }); | ||
| return { | ||
| conflict: conflict, | ||
| result: lines | ||
| }; | ||
| } | ||
| function merge(a, o, b, options) { | ||
| var defaults = { | ||
| excludeFalseConflicts: true, | ||
| stringSeparator: /\s+/ | ||
| }; | ||
| options = Object.assign(defaults, options); | ||
| var merger = diff3Merge(a, o, b, options); | ||
| var conflict = false; | ||
| var lines = []; | ||
| for (var i = 0; i < merger.length; i++) { | ||
| var item = merger[i]; | ||
| if (item.ok) { | ||
| lines = lines.concat(item.ok); | ||
| } else { | ||
| conflict = true; | ||
| lines = lines.concat( | ||
| ['\n<<<<<<<<<\n'], item.conflict.a, | ||
| ['\n=========\n'], item.conflict.b, | ||
| ['\n>>>>>>>>>\n'] | ||
| ); | ||
| } | ||
| } | ||
| return { | ||
| conflict: conflict, | ||
| result: lines | ||
| }; | ||
| } | ||
| function mergeDigIn(a, o, b, options) { | ||
| var defaults = { | ||
| excludeFalseConflicts: false, | ||
| stringSeparator: /\s+/ | ||
| }; | ||
| options = Object.assign(defaults, options); | ||
| var merger = diff3Merge(a, o, b, options); | ||
| var conflict = false; | ||
| var lines = []; | ||
| for (var i = 0; i < merger.length; i++) { | ||
| var item = merger[i]; | ||
| if (item.ok) { | ||
| lines = lines.concat(item.ok); | ||
| } else { | ||
| var c = diffComm(item.conflict.a, item.conflict.b); | ||
| for (var j = 0; j < c.length; j++) { | ||
| var inner = c[j]; | ||
| if (inner.common) { | ||
| lines = lines.concat(inner.common); | ||
| } else { | ||
| conflict = true; | ||
| lines = lines.concat( | ||
| ['\n<<<<<<<<<\n'], inner.buffer1, | ||
| ['\n=========\n'], inner.buffer2, | ||
| ['\n>>>>>>>>>\n'] | ||
| ); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return { | ||
| conflict: conflict, | ||
| result: lines | ||
| }; | ||
| } | ||
| // Applies a patch to a buffer. | ||
| // Given buffer1 and buffer2, `patch(buffer1, diffPatch(buffer1, buffer2))` should give buffer2. | ||
| function patch(buffer, patch) { | ||
| var result = []; | ||
| var currOffset = 0; | ||
| function advanceTo(targetOffset) { | ||
| while (currOffset < targetOffset) { | ||
| result.push(buffer[currOffset]); | ||
| currOffset++; | ||
| } | ||
| } | ||
| for (var chunkIndex = 0; chunkIndex < patch.length; chunkIndex++) { | ||
| var chunk = patch[chunkIndex]; | ||
| advanceTo(chunk.buffer1.offset); | ||
| for (var itemIndex = 0; itemIndex < chunk.buffer2.chunk.length; itemIndex++) { | ||
| result.push(chunk.buffer2.chunk[itemIndex]); | ||
| } | ||
| currOffset += chunk.buffer1.length; | ||
| } | ||
| advanceTo(buffer.length); | ||
| return result; | ||
| } | ||
| // Takes the output of diffPatch(), and removes extra information from it. | ||
| // It can still be used by patch(), below, but can no longer be inverted. | ||
| function stripPatch(patch) { | ||
| return patch.map(function (chunk) { return ({ | ||
| buffer1: { offset: chunk.buffer1.offset, length: chunk.buffer1.length }, | ||
| buffer2: { chunk: chunk.buffer2.chunk } | ||
| }); }); | ||
| } | ||
| // Takes the output of diffPatch(), and inverts the sense of it, so that it | ||
| // can be applied to buffer2 to give buffer1 rather than the other way around. | ||
| function invertPatch(patch) { | ||
| return patch.map(function (chunk) { return ({ | ||
| buffer1: chunk.buffer2, | ||
| buffer2: chunk.buffer1 | ||
| }); }); | ||
| } | ||
| exports.LCS = LCS; | ||
| exports.diff3Merge = diff3Merge; | ||
| exports.diff3MergeRegions = diff3MergeRegions; | ||
| exports.diffComm = diffComm; | ||
| exports.diffIndices = diffIndices; | ||
| exports.diffPatch = diffPatch; | ||
| exports.invertPatch = invertPatch; | ||
| exports.merge = merge; | ||
| exports.mergeDiff3 = mergeDiff3; | ||
| exports.mergeDigIn = mergeDigIn; | ||
| exports.patch = patch; | ||
| exports.stripPatch = stripPatch; | ||
| Object.defineProperty(exports, '__esModule', { value: true }); | ||
| }))); |
-541
| (function (global, factory) { | ||
| typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | ||
| typeof define === 'function' && define.amd ? define(['exports'], factory) : | ||
| (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Diff3 = {})); | ||
| }(this, (function (exports) { 'use strict'; | ||
| // Text diff algorithm following Hunt and McIlroy 1976. | ||
| // J. W. Hunt and M. D. McIlroy, An algorithm for differential buffer | ||
| // comparison, Bell Telephone Laboratories CSTR #41 (1976) | ||
| // http://www.cs.dartmouth.edu/~doug/ | ||
| // https://en.wikipedia.org/wiki/Longest_common_subsequence_problem | ||
| // | ||
| // Expects two arrays, finds longest common sequence | ||
| function LCS(buffer1, buffer2) { | ||
| let equivalenceClasses = {}; | ||
| for (let j = 0; j < buffer2.length; j++) { | ||
| const item = buffer2[j]; | ||
| if (equivalenceClasses[item]) { | ||
| equivalenceClasses[item].push(j); | ||
| } else { | ||
| equivalenceClasses[item] = [j]; | ||
| } | ||
| } | ||
| const NULLRESULT = { buffer1index: -1, buffer2index: -1, chain: null }; | ||
| let candidates = [NULLRESULT]; | ||
| for (let i = 0; i < buffer1.length; i++) { | ||
| const item = buffer1[i]; | ||
| const buffer2indices = equivalenceClasses[item] || []; | ||
| let r = 0; | ||
| let c = candidates[0]; | ||
| for (let jx = 0; jx < buffer2indices.length; jx++) { | ||
| const j = buffer2indices[jx]; | ||
| let s; | ||
| for (s = r; s < candidates.length; s++) { | ||
| if ((candidates[s].buffer2index < j) && ((s === candidates.length - 1) || (candidates[s + 1].buffer2index > j))) { | ||
| break; | ||
| } | ||
| } | ||
| if (s < candidates.length) { | ||
| const newCandidate = { buffer1index: i, buffer2index: j, chain: candidates[s] }; | ||
| if (r === candidates.length) { | ||
| candidates.push(c); | ||
| } else { | ||
| candidates[r] = c; | ||
| } | ||
| r = s + 1; | ||
| c = newCandidate; | ||
| if (r === candidates.length) { | ||
| break; // no point in examining further (j)s | ||
| } | ||
| } | ||
| } | ||
| candidates[r] = c; | ||
| } | ||
| // At this point, we know the LCS: it's in the reverse of the | ||
| // linked-list through .chain of candidates[candidates.length - 1]. | ||
| return candidates[candidates.length - 1]; | ||
| } | ||
| // We apply the LCS to build a 'comm'-style picture of the | ||
| // differences between buffer1 and buffer2. | ||
| function diffComm(buffer1, buffer2) { | ||
| const lcs = LCS(buffer1, buffer2); | ||
| let result = []; | ||
| let tail1 = buffer1.length; | ||
| let tail2 = buffer2.length; | ||
| let common = {common: []}; | ||
| function processCommon() { | ||
| if (common.common.length) { | ||
| common.common.reverse(); | ||
| result.push(common); | ||
| common = {common: []}; | ||
| } | ||
| } | ||
| for (let candidate = lcs; candidate !== null; candidate = candidate.chain) { | ||
| let different = {buffer1: [], buffer2: []}; | ||
| while (--tail1 > candidate.buffer1index) { | ||
| different.buffer1.push(buffer1[tail1]); | ||
| } | ||
| while (--tail2 > candidate.buffer2index) { | ||
| different.buffer2.push(buffer2[tail2]); | ||
| } | ||
| if (different.buffer1.length || different.buffer2.length) { | ||
| processCommon(); | ||
| different.buffer1.reverse(); | ||
| different.buffer2.reverse(); | ||
| result.push(different); | ||
| } | ||
| if (tail1 >= 0) { | ||
| common.common.push(buffer1[tail1]); | ||
| } | ||
| } | ||
| processCommon(); | ||
| result.reverse(); | ||
| return result; | ||
| } | ||
| // We apply the LCS to give a simple representation of the | ||
| // offsets and lengths of mismatched chunks in the input | ||
| // buffers. This is used by diff3MergeRegions. | ||
| function diffIndices(buffer1, buffer2) { | ||
| const lcs = LCS(buffer1, buffer2); | ||
| let result = []; | ||
| let tail1 = buffer1.length; | ||
| let tail2 = buffer2.length; | ||
| for (let candidate = lcs; candidate !== null; candidate = candidate.chain) { | ||
| const mismatchLength1 = tail1 - candidate.buffer1index - 1; | ||
| const mismatchLength2 = tail2 - candidate.buffer2index - 1; | ||
| tail1 = candidate.buffer1index; | ||
| tail2 = candidate.buffer2index; | ||
| if (mismatchLength1 || mismatchLength2) { | ||
| result.push({ | ||
| buffer1: [tail1 + 1, mismatchLength1], | ||
| buffer1Content: buffer1.slice(tail1 + 1, tail1 + 1 + mismatchLength1), | ||
| buffer2: [tail2 + 1, mismatchLength2], | ||
| buffer2Content: buffer2.slice(tail2 + 1, tail2 + 1 + mismatchLength2) | ||
| }); | ||
| } | ||
| } | ||
| result.reverse(); | ||
| return result; | ||
| } | ||
| // We apply the LCS to build a JSON representation of a | ||
| // diff(1)-style patch. | ||
| function diffPatch(buffer1, buffer2) { | ||
| const lcs = LCS(buffer1, buffer2); | ||
| let result = []; | ||
| let tail1 = buffer1.length; | ||
| let tail2 = buffer2.length; | ||
| function chunkDescription(buffer, offset, length) { | ||
| let chunk = []; | ||
| for (let i = 0; i < length; i++) { | ||
| chunk.push(buffer[offset + i]); | ||
| } | ||
| return { | ||
| offset: offset, | ||
| length: length, | ||
| chunk: chunk | ||
| }; | ||
| } | ||
| for (let candidate = lcs; candidate !== null; candidate = candidate.chain) { | ||
| const mismatchLength1 = tail1 - candidate.buffer1index - 1; | ||
| const mismatchLength2 = tail2 - candidate.buffer2index - 1; | ||
| tail1 = candidate.buffer1index; | ||
| tail2 = candidate.buffer2index; | ||
| if (mismatchLength1 || mismatchLength2) { | ||
| result.push({ | ||
| buffer1: chunkDescription(buffer1, candidate.buffer1index + 1, mismatchLength1), | ||
| buffer2: chunkDescription(buffer2, candidate.buffer2index + 1, mismatchLength2) | ||
| }); | ||
| } | ||
| } | ||
| result.reverse(); | ||
| return result; | ||
| } | ||
| // Given three buffers, A, O, and B, where both A and B are | ||
| // independently derived from O, returns a fairly complicated | ||
| // internal representation of merge decisions it's taken. The | ||
| // interested reader may wish to consult | ||
| // | ||
| // Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce. | ||
| // 'A Formal Investigation of ' In Arvind and Prasad, | ||
| // editors, Foundations of Software Technology and Theoretical | ||
| // Computer Science (FSTTCS), December 2007. | ||
| // | ||
| // (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf) | ||
| // | ||
| function diff3MergeRegions(a, o, b) { | ||
| // "hunks" are array subsets where `a` or `b` are different from `o` | ||
| // https://www.gnu.org/software/diffutils/manual/html_node/diff3-Hunks.html | ||
| let hunks = []; | ||
| function addHunk(h, ab) { | ||
| hunks.push({ | ||
| ab: ab, | ||
| oStart: h.buffer1[0], | ||
| oLength: h.buffer1[1], // length of o to remove | ||
| abStart: h.buffer2[0], | ||
| abLength: h.buffer2[1] // length of a/b to insert | ||
| // abContent: (ab === 'a' ? a : b).slice(h.buffer2[0], h.buffer2[0] + h.buffer2[1]) | ||
| }); | ||
| } | ||
| diffIndices(o, a).forEach(item => addHunk(item, 'a')); | ||
| diffIndices(o, b).forEach(item => addHunk(item, 'b')); | ||
| hunks.sort((x,y) => x.oStart - y.oStart); | ||
| let results = []; | ||
| let currOffset = 0; | ||
| function advanceTo(endOffset) { | ||
| if (endOffset > currOffset) { | ||
| results.push({ | ||
| stable: true, | ||
| buffer: 'o', | ||
| bufferStart: currOffset, | ||
| bufferLength: endOffset - currOffset, | ||
| bufferContent: o.slice(currOffset, endOffset) | ||
| }); | ||
| currOffset = endOffset; | ||
| } | ||
| } | ||
| while (hunks.length) { | ||
| let hunk = hunks.shift(); | ||
| let regionStart = hunk.oStart; | ||
| let regionEnd = hunk.oStart + hunk.oLength; | ||
| let regionHunks = [hunk]; | ||
| advanceTo(regionStart); | ||
| // Try to pull next overlapping hunk into this region | ||
| while (hunks.length) { | ||
| const nextHunk = hunks[0]; | ||
| const nextHunkStart = nextHunk.oStart; | ||
| if (nextHunkStart > regionEnd) break; // no overlap | ||
| regionEnd = Math.max(regionEnd, nextHunkStart + nextHunk.oLength); | ||
| regionHunks.push(hunks.shift()); | ||
| } | ||
| if (regionHunks.length === 1) { | ||
| // Only one hunk touches this region, meaning that there is no conflict here. | ||
| // Either `a` or `b` is inserting into a region of `o` unchanged by the other. | ||
| if (hunk.abLength > 0) { | ||
| const buffer = (hunk.ab === 'a' ? a : b); | ||
| results.push({ | ||
| stable: true, | ||
| buffer: hunk.ab, | ||
| bufferStart: hunk.abStart, | ||
| bufferLength: hunk.abLength, | ||
| bufferContent: buffer.slice(hunk.abStart, hunk.abStart + hunk.abLength) | ||
| }); | ||
| } | ||
| } else { | ||
| // A true a/b conflict. Determine the bounds involved from `a`, `o`, and `b`. | ||
| // Effectively merge all the `a` hunks into one giant hunk, then do the | ||
| // same for the `b` hunks; then, correct for skew in the regions of `o` | ||
| // that each side changed, and report appropriate spans for the three sides. | ||
| let bounds = { | ||
| a: [a.length, -1, o.length, -1], | ||
| b: [b.length, -1, o.length, -1] | ||
| }; | ||
| while (regionHunks.length) { | ||
| hunk = regionHunks.shift(); | ||
| const oStart = hunk.oStart; | ||
| const oEnd = oStart + hunk.oLength; | ||
| const abStart = hunk.abStart; | ||
| const abEnd = abStart + hunk.abLength; | ||
| let b = bounds[hunk.ab]; | ||
| b[0] = Math.min(abStart, b[0]); | ||
| b[1] = Math.max(abEnd, b[1]); | ||
| b[2] = Math.min(oStart, b[2]); | ||
| b[3] = Math.max(oEnd, b[3]); | ||
| } | ||
| const aStart = bounds.a[0] + (regionStart - bounds.a[2]); | ||
| const aEnd = bounds.a[1] + (regionEnd - bounds.a[3]); | ||
| const bStart = bounds.b[0] + (regionStart - bounds.b[2]); | ||
| const bEnd = bounds.b[1] + (regionEnd - bounds.b[3]); | ||
| let result = { | ||
| stable: false, | ||
| aStart: aStart, | ||
| aLength: aEnd - aStart, | ||
| aContent: a.slice(aStart, aEnd), | ||
| oStart: regionStart, | ||
| oLength: regionEnd - regionStart, | ||
| oContent: o.slice(regionStart, regionEnd), | ||
| bStart: bStart, | ||
| bLength: bEnd - bStart, | ||
| bContent: b.slice(bStart, bEnd) | ||
| }; | ||
| results.push(result); | ||
| } | ||
| currOffset = regionEnd; | ||
| } | ||
| advanceTo(o.length); | ||
| return results; | ||
| } | ||
| // Applies the output of diff3MergeRegions to actually | ||
| // construct the merged buffer; the returned result alternates | ||
| // between 'ok' and 'conflict' blocks. | ||
| // A "false conflict" is where `a` and `b` both change the same from `o` | ||
| function diff3Merge(a, o, b, options) { | ||
| let defaults = { | ||
| excludeFalseConflicts: true, | ||
| stringSeparator: /\s+/ | ||
| }; | ||
| options = Object.assign(defaults, options); | ||
| const aString = (typeof a === 'string'); | ||
| const oString = (typeof o === 'string'); | ||
| const bString = (typeof b === 'string'); | ||
| if (aString) a = a.split(options.stringSeparator); | ||
| if (oString) o = o.split(options.stringSeparator); | ||
| if (bString) b = b.split(options.stringSeparator); | ||
| let results = []; | ||
| const regions = diff3MergeRegions(a, o, b); | ||
| let okBuffer = []; | ||
| function flushOk() { | ||
| if (okBuffer.length) { | ||
| results.push({ ok: okBuffer }); | ||
| } | ||
| okBuffer = []; | ||
| } | ||
| function isFalseConflict(a, b) { | ||
| if (a.length !== b.length) return false; | ||
| for (let i = 0; i < a.length; i++) { | ||
| if (a[i] !== b[i]) return false; | ||
| } | ||
| return true; | ||
| } | ||
| regions.forEach(region => { | ||
| if (region.stable) { | ||
| okBuffer.push(...region.bufferContent); | ||
| } else { | ||
| if (options.excludeFalseConflicts && isFalseConflict(region.aContent, region.bContent)) { | ||
| okBuffer.push(...region.aContent); | ||
| } else { | ||
| flushOk(); | ||
| results.push({ | ||
| conflict: { | ||
| a: region.aContent, | ||
| aIndex: region.aStart, | ||
| o: region.oContent, | ||
| oIndex: region.oStart, | ||
| b: region.bContent, | ||
| bIndex: region.bStart | ||
| } | ||
| }); | ||
| } | ||
| } | ||
| }); | ||
| flushOk(); | ||
| return results; | ||
| } | ||
| function mergeDiff3(a, o, b, options) { | ||
| let defaults = { | ||
| excludeFalseConflicts: true, | ||
| stringSeparator: /\s+/, | ||
| label: {} | ||
| }; | ||
| options = Object.assign(defaults, options); | ||
| const mergeResult = diff3Merge(a, o, b, options); | ||
| let conflict = false; | ||
| let lines = []; | ||
| mergeResult.forEach(result => { | ||
| if (result.ok) { | ||
| lines = lines.concat(result.ok); | ||
| } else if (result.conflict) { | ||
| conflict = true; | ||
| lines.push(`<<<<<<<${options.label.a ? ` ${options.label.a}` : ''}`); | ||
| lines = lines.concat(result.conflict.a); | ||
| lines.push(`|||||||${options.label.o ? ` ${options.label.o}` : ''}`); | ||
| lines = lines.concat(result.conflict.o); | ||
| lines.push('======='); | ||
| lines = lines.concat(result.conflict.b); | ||
| lines.push(`>>>>>>>${options.label.b ? ` ${options.label.b}` : ''}`); | ||
| } | ||
| }); | ||
| return { | ||
| conflict: conflict, | ||
| result: lines | ||
| }; | ||
| } | ||
| function merge(a, o, b, options) { | ||
| let defaults = { | ||
| excludeFalseConflicts: true, | ||
| stringSeparator: /\s+/ | ||
| }; | ||
| options = Object.assign(defaults, options); | ||
| const merger = diff3Merge(a, o, b, options); | ||
| let conflict = false; | ||
| let lines = []; | ||
| for (let i = 0; i < merger.length; i++) { | ||
| const item = merger[i]; | ||
| if (item.ok) { | ||
| lines = lines.concat(item.ok); | ||
| } else { | ||
| conflict = true; | ||
| lines = lines.concat( | ||
| ['\n<<<<<<<<<\n'], item.conflict.a, | ||
| ['\n=========\n'], item.conflict.b, | ||
| ['\n>>>>>>>>>\n'] | ||
| ); | ||
| } | ||
| } | ||
| return { | ||
| conflict: conflict, | ||
| result: lines | ||
| }; | ||
| } | ||
| function mergeDigIn(a, o, b, options) { | ||
| let defaults = { | ||
| excludeFalseConflicts: false, | ||
| stringSeparator: /\s+/ | ||
| }; | ||
| options = Object.assign(defaults, options); | ||
| const merger = diff3Merge(a, o, b, options); | ||
| let conflict = false; | ||
| let lines = []; | ||
| for (let i = 0; i < merger.length; i++) { | ||
| const item = merger[i]; | ||
| if (item.ok) { | ||
| lines = lines.concat(item.ok); | ||
| } else { | ||
| const c = diffComm(item.conflict.a, item.conflict.b); | ||
| for (let j = 0; j < c.length; j++) { | ||
| let inner = c[j]; | ||
| if (inner.common) { | ||
| lines = lines.concat(inner.common); | ||
| } else { | ||
| conflict = true; | ||
| lines = lines.concat( | ||
| ['\n<<<<<<<<<\n'], inner.buffer1, | ||
| ['\n=========\n'], inner.buffer2, | ||
| ['\n>>>>>>>>>\n'] | ||
| ); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| return { | ||
| conflict: conflict, | ||
| result: lines | ||
| }; | ||
| } | ||
| // Applies a patch to a buffer. | ||
| // Given buffer1 and buffer2, `patch(buffer1, diffPatch(buffer1, buffer2))` should give buffer2. | ||
| function patch(buffer, patch) { | ||
| let result = []; | ||
| let currOffset = 0; | ||
| function advanceTo(targetOffset) { | ||
| while (currOffset < targetOffset) { | ||
| result.push(buffer[currOffset]); | ||
| currOffset++; | ||
| } | ||
| } | ||
| for (let chunkIndex = 0; chunkIndex < patch.length; chunkIndex++) { | ||
| let chunk = patch[chunkIndex]; | ||
| advanceTo(chunk.buffer1.offset); | ||
| for (let itemIndex = 0; itemIndex < chunk.buffer2.chunk.length; itemIndex++) { | ||
| result.push(chunk.buffer2.chunk[itemIndex]); | ||
| } | ||
| currOffset += chunk.buffer1.length; | ||
| } | ||
| advanceTo(buffer.length); | ||
| return result; | ||
| } | ||
| // Takes the output of diffPatch(), and removes extra information from it. | ||
| // It can still be used by patch(), below, but can no longer be inverted. | ||
| function stripPatch(patch) { | ||
| return patch.map(chunk => ({ | ||
| buffer1: { offset: chunk.buffer1.offset, length: chunk.buffer1.length }, | ||
| buffer2: { chunk: chunk.buffer2.chunk } | ||
| })); | ||
| } | ||
| // Takes the output of diffPatch(), and inverts the sense of it, so that it | ||
| // can be applied to buffer2 to give buffer1 rather than the other way around. | ||
| function invertPatch(patch) { | ||
| return patch.map(chunk => ({ | ||
| buffer1: chunk.buffer2, | ||
| buffer2: chunk.buffer1 | ||
| })); | ||
| } | ||
| exports.LCS = LCS; | ||
| exports.diff3Merge = diff3Merge; | ||
| exports.diff3MergeRegions = diff3MergeRegions; | ||
| exports.diffComm = diffComm; | ||
| exports.diffIndices = diffIndices; | ||
| exports.diffPatch = diffPatch; | ||
| exports.invertPatch = invertPatch; | ||
| exports.merge = merge; | ||
| exports.mergeDiff3 = mergeDiff3; | ||
| exports.mergeDigIn = mergeDigIn; | ||
| exports.patch = patch; | ||
| exports.stripPatch = stripPatch; | ||
| Object.defineProperty(exports, '__esModule', { value: true }); | ||
| }))); |
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.
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
104803
57.2%316
0.32%Yes
NaN1477
-4.77%1
Infinity%