vue-diff-text
Version:
A simple Vue 3 component to display the difference between two blocks of text.
394 lines (393 loc) • 11.2 kB
JavaScript
import { defineComponent as L, computed as $, createElementBlock as p, openBlock as a, Fragment as q, renderList as z, toDisplayString as E, normalizeClass as W } from "vue";
function x() {
}
x.prototype = {
diff: function(e, n) {
var r, s = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {}, o = s.callback;
typeof s == "function" && (o = s, s = {}), this.options = s;
var i = this;
function f(l) {
return o ? (setTimeout(function() {
o(void 0, l);
}, 0), !0) : l;
}
e = this.castInput(e), n = this.castInput(n), e = this.removeEmpty(this.tokenize(e)), n = this.removeEmpty(this.tokenize(n));
var u = n.length, c = e.length, m = 1, d = u + c;
s.maxEditLength && (d = Math.min(d, s.maxEditLength));
var C = (r = s.timeout) !== null && r !== void 0 ? r : 1 / 0, O = Date.now() + C, v = [{
oldPos: -1,
lastComponent: void 0
}], h = this.extractCommon(v[0], n, e, 0);
if (v[0].oldPos + 1 >= c && h + 1 >= u)
return f([{
value: this.join(n),
count: n.length
}]);
var T = -1 / 0, _ = 1 / 0;
function R() {
for (var l = Math.max(T, -m); l <= Math.min(_, m); l += 2) {
var y = void 0, w = v[l - 1], D = v[l + 1];
w && (v[l - 1] = void 0);
var M = !1;
if (D) {
var B = D.oldPos - l;
M = D && 0 <= B && B < u;
}
var S = w && w.oldPos + 1 < c;
if (!M && !S) {
v[l] = void 0;
continue;
}
if (!S || M && w.oldPos + 1 < D.oldPos ? y = i.addToPath(D, !0, void 0, 0) : y = i.addToPath(w, void 0, !0, 1), h = i.extractCommon(y, n, e, l), y.oldPos + 1 >= c && h + 1 >= u)
return f(H(i, y.lastComponent, n, e, i.useLongestToken));
v[l] = y, y.oldPos + 1 >= c && (_ = Math.min(_, l - 1)), h + 1 >= u && (T = Math.max(T, l + 1));
}
m++;
}
if (o)
(function l() {
setTimeout(function() {
if (m > d || Date.now() > O)
return o();
R() || l();
}, 0);
})();
else
for (; m <= d && Date.now() <= O; ) {
var k = R();
if (k)
return k;
}
},
addToPath: function(e, n, r, s) {
var o = e.lastComponent;
return o && o.added === n && o.removed === r ? {
oldPos: e.oldPos + s,
lastComponent: {
count: o.count + 1,
added: n,
removed: r,
previousComponent: o.previousComponent
}
} : {
oldPos: e.oldPos + s,
lastComponent: {
count: 1,
added: n,
removed: r,
previousComponent: o
}
};
},
extractCommon: function(e, n, r, s) {
for (var o = n.length, i = r.length, f = e.oldPos, u = f - s, c = 0; u + 1 < o && f + 1 < i && this.equals(n[u + 1], r[f + 1]); )
u++, f++, c++;
return c && (e.lastComponent = {
count: c,
previousComponent: e.lastComponent
}), e.oldPos = f, u;
},
equals: function(e, n) {
return this.options.comparator ? this.options.comparator(e, n) : e === n || this.options.ignoreCase && e.toLowerCase() === n.toLowerCase();
},
removeEmpty: function(e) {
for (var n = [], r = 0; r < e.length; r++)
e[r] && n.push(e[r]);
return n;
},
castInput: function(e) {
return e;
},
tokenize: function(e) {
return e.split("");
},
join: function(e) {
return e.join("");
}
};
function H(t, e, n, r, s) {
for (var o = [], i; e; )
o.push(e), i = e.previousComponent, delete e.previousComponent, e = i;
o.reverse();
for (var f = 0, u = o.length, c = 0, m = 0; f < u; f++) {
var d = o[f];
if (d.removed) {
if (d.value = t.join(r.slice(m, m + d.count)), m += d.count, f && o[f - 1].added) {
var O = o[f - 1];
o[f - 1] = o[f], o[f] = O;
}
} else {
if (!d.added && s) {
var C = n.slice(c, c + d.count);
C = C.map(function(h, T) {
var _ = r[m + T];
return _.length > h.length ? _ : h;
}), d.value = t.join(C);
} else
d.value = t.join(n.slice(c, c + d.count));
c += d.count, d.added || (m += d.count);
}
}
var v = o[u - 1];
return u > 1 && typeof v.value == "string" && (v.added || v.removed) && t.equals("", v.value) && (o[u - 2].value += v.value, o.pop()), o;
}
var Q = new x();
function U(t, e, n) {
return Q.diff(t, e, n);
}
function X(t, e) {
if (typeof t == "function")
e.callback = t;
else if (t)
for (var n in t)
t.hasOwnProperty(n) && (e[n] = t[n]);
return e;
}
var V = /^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/, Z = /\S/, F = new x();
F.equals = function(t, e) {
return this.options.ignoreCase && (t = t.toLowerCase(), e = e.toLowerCase()), t === e || this.options.ignoreWhitespace && !Z.test(t) && !Z.test(e);
};
F.tokenize = function(t) {
for (var e = t.split(/([^\S\r\n]+|[()[\]{}'"\r\n]|\b)/), n = 0; n < e.length - 1; n++)
!e[n + 1] && e[n + 2] && V.test(e[n]) && V.test(e[n + 2]) && (e[n] += e[n + 2], e.splice(n + 1, 2), n--);
return e;
};
function Y(t, e, n) {
return n = X(n, {
ignoreWhitespace: !0
}), F.diff(t, e, n);
}
function j(t, e, n) {
return F.diff(t, e, n);
}
var N = new x();
N.tokenize = function(t) {
this.options.stripTrailingCr && (t = t.replace(/\r\n/g, `
`));
var e = [], n = t.split(/(\n|\r\n)/);
n[n.length - 1] || n.pop();
for (var r = 0; r < n.length; r++) {
var s = n[r];
r % 2 && !this.options.newlineIsToken ? e[e.length - 1] += s : (this.options.ignoreWhitespace && (s = s.trim()), e.push(s));
}
return e;
};
function P(t, e, n) {
return N.diff(t, e, n);
}
var G = new x();
G.tokenize = function(t) {
return t.split(/(\S.+?[.!?])(?=\s+|$)/);
};
function K(t, e, n) {
return G.diff(t, e, n);
}
var b = new x();
b.tokenize = function(t) {
return t.split(/([{}:;,]|\s+)/);
};
function I(t) {
"@babel/helpers - typeof";
return typeof Symbol == "function" && typeof Symbol.iterator == "symbol" ? I = function(e) {
return typeof e;
} : I = function(e) {
return e && typeof Symbol == "function" && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e;
}, I(t);
}
var ee = Object.prototype.toString, g = new x();
g.useLongestToken = !0;
g.tokenize = N.tokenize;
g.castInput = function(t) {
var e = this.options, n = e.undefinedReplacement, r = e.stringifyReplacer, s = r === void 0 ? function(o, i) {
return typeof i > "u" ? n : i;
} : r;
return typeof t == "string" ? t : JSON.stringify(A(t, null, null, s), s, " ");
};
g.equals = function(t, e) {
return x.prototype.equals.call(g, t.replace(/,([\r\n])/g, "$1"), e.replace(/,([\r\n])/g, "$1"));
};
function A(t, e, n, r, s) {
e = e || [], n = n || [], r && (t = r(s, t));
var o;
for (o = 0; o < e.length; o += 1)
if (e[o] === t)
return n[o];
var i;
if (ee.call(t) === "[object Array]") {
for (e.push(t), i = new Array(t.length), n.push(i), o = 0; o < t.length; o += 1)
i[o] = A(t[o], e, n, r, s);
return e.pop(), n.pop(), i;
}
if (t && t.toJSON && (t = t.toJSON()), I(t) === "object" && t !== null) {
e.push(t), i = {}, n.push(i);
var f = [], u;
for (u in t)
t.hasOwnProperty(u) && f.push(u);
for (f.sort(), o = 0; o < f.length; o += 1)
u = f[o], i[u] = A(t[u], e, n, r, u);
e.pop(), n.pop();
} else
i = t;
return i;
}
var J = new x();
J.tokenize = function(t) {
return t.slice();
};
J.join = J.removeEmpty = function(t) {
return t;
};
const te = { class: "text-diff text-diff-chars" }, ne = ["textContent"], pe = /* @__PURE__ */ L({
__name: "DiffChars",
props: {
oldText: {
type: String,
required: !0
},
newText: {
type: String,
required: !0
},
options: {
type: Object,
default: () => ({})
}
},
setup(t) {
const e = t, n = $(() => U(e.oldText, e.newText, e.options));
return (r, s) => (a(), p("div", te, [
(a(!0), p(q, null, z(n.value, (o, i) => (a(), p("span", {
key: i,
class: W({
"diff-added": o.added,
"diff-removed": o.removed
}),
textContent: E(o.value)
}, null, 10, ne))), 128))
]));
}
}), oe = { class: "text-diff text-diff-words" }, re = ["textContent"], ae = /* @__PURE__ */ L({
__name: "DiffWords",
props: {
oldText: {
type: String,
required: !0
},
newText: {
type: String,
required: !0
},
options: {
type: Object,
default: () => ({})
}
},
setup(t) {
const e = t, n = $(() => Y(e.oldText, e.newText, e.options));
return (r, s) => (a(), p("div", oe, [
(a(!0), p(q, null, z(n.value, (o, i) => (a(), p("span", {
key: i,
class: W({
"diff-added": o.added,
"diff-removed": o.removed
}),
textContent: E(o.value)
}, null, 10, re))), 128))
]));
}
}), ie = { class: "text-diff text-diff-words-with-space" }, se = ["textContent"], ve = /* @__PURE__ */ L({
__name: "DiffWordsWithSpace",
props: {
oldText: {
type: String,
required: !0
},
newText: {
type: String,
required: !0
},
options: {
type: Object,
default: () => ({})
}
},
setup(t) {
const e = t, n = $(() => j(e.oldText, e.newText, e.options));
return (r, s) => (a(), p("div", ie, [
(a(!0), p(q, null, z(n.value, (o, i) => (a(), p("span", {
key: i,
class: W({
"diff-added": o.added,
"diff-removed": o.removed
}),
textContent: E(o.value)
}, null, 10, se))), 128))
]));
}
}), fe = { class: "text-diff text-diff-lines" }, ue = ["textContent"], me = /* @__PURE__ */ L({
__name: "DiffLines",
props: {
oldText: {
type: String,
required: !0
},
newText: {
type: String,
required: !0
},
options: {
type: Object,
default: () => ({})
}
},
setup(t) {
const e = t, n = $(() => P(e.oldText, e.newText, e.options));
return (r, s) => (a(), p("div", fe, [
(a(!0), p(q, null, z(n.value, (o, i) => (a(), p("span", {
key: i,
class: W({
"diff-added": o.added,
"diff-removed": o.removed
}),
textContent: E(o.value)
}, null, 10, ue))), 128))
]));
}
}), de = { class: "text-diff text-diff-sentences" }, le = ["textContent"], xe = /* @__PURE__ */ L({
__name: "DiffSentences",
props: {
oldText: {
type: String,
required: !0
},
newText: {
type: String,
required: !0
},
options: {
type: Object,
default: () => ({})
}
},
setup(t) {
const e = t, n = $(() => K(e.oldText, e.newText, e.options));
return (r, s) => (a(), p("div", de, [
(a(!0), p(q, null, z(n.value, (o, i) => (a(), p("span", {
key: i,
class: W({
"diff-added": o.added,
"diff-removed": o.removed
}),
textContent: E(o.value)
}, null, 10, le))), 128))
]));
}
});
export {
pe as DiffChars,
me as DiffLines,
xe as DiffSentences,
ae as DiffWords,
ve as DiffWordsWithSpace,
ve as TextDiff
};