123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996 |
- (function () {
- 'use strict';
- /**
- * @license
- * Copyright 2019 Google LLC
- * SPDX-License-Identifier: Apache-2.0
- */
- const proxyMarker = Symbol("Comlink.proxy");
- const createEndpoint = Symbol("Comlink.endpoint");
- const releaseProxy = Symbol("Comlink.releaseProxy");
- const finalizer = Symbol("Comlink.finalizer");
- const throwMarker = Symbol("Comlink.thrown");
- const isObject = (val) => (typeof val === "object" && val !== null) || typeof val === "function";
- /**
- * Internal transfer handle to handle objects marked to proxy.
- */
- const proxyTransferHandler = {
- canHandle: (val) => isObject(val) && val[proxyMarker],
- serialize(obj) {
- const { port1, port2 } = new MessageChannel();
- expose(obj, port1);
- return [port2, [port2]];
- },
- deserialize(port) {
- port.start();
- return wrap(port);
- },
- };
- /**
- * Internal transfer handler to handle thrown exceptions.
- */
- const throwTransferHandler = {
- canHandle: (value) => isObject(value) && throwMarker in value,
- serialize({ value }) {
- let serialized;
- if (value instanceof Error) {
- serialized = {
- isError: true,
- value: {
- message: value.message,
- name: value.name,
- stack: value.stack,
- },
- };
- }
- else {
- serialized = { isError: false, value };
- }
- return [serialized, []];
- },
- deserialize(serialized) {
- if (serialized.isError) {
- throw Object.assign(new Error(serialized.value.message), serialized.value);
- }
- throw serialized.value;
- },
- };
- /**
- * Allows customizing the serialization of certain values.
- */
- const transferHandlers = new Map([
- ["proxy", proxyTransferHandler],
- ["throw", throwTransferHandler],
- ]);
- function isAllowedOrigin(allowedOrigins, origin) {
- for (const allowedOrigin of allowedOrigins) {
- if (origin === allowedOrigin || allowedOrigin === "*") {
- return true;
- }
- if (allowedOrigin instanceof RegExp && allowedOrigin.test(origin)) {
- return true;
- }
- }
- return false;
- }
- function expose(obj, ep = globalThis, allowedOrigins = ["*"]) {
- ep.addEventListener("message", function callback(ev) {
- if (!ev || !ev.data) {
- return;
- }
- if (!isAllowedOrigin(allowedOrigins, ev.origin)) {
- console.warn(`Invalid origin '${ev.origin}' for comlink proxy`);
- return;
- }
- const { id, type, path } = Object.assign({ path: [] }, ev.data);
- const argumentList = (ev.data.argumentList || []).map(fromWireValue);
- let returnValue;
- try {
- const parent = path.slice(0, -1).reduce((obj, prop) => obj[prop], obj);
- const rawValue = path.reduce((obj, prop) => obj[prop], obj);
- switch (type) {
- case "GET" /* MessageType.GET */:
- {
- returnValue = rawValue;
- }
- break;
- case "SET" /* MessageType.SET */:
- {
- parent[path.slice(-1)[0]] = fromWireValue(ev.data.value);
- returnValue = true;
- }
- break;
- case "APPLY" /* MessageType.APPLY */:
- {
- returnValue = rawValue.apply(parent, argumentList);
- }
- break;
- case "CONSTRUCT" /* MessageType.CONSTRUCT */:
- {
- const value = new rawValue(...argumentList);
- returnValue = proxy(value);
- }
- break;
- case "ENDPOINT" /* MessageType.ENDPOINT */:
- {
- const { port1, port2 } = new MessageChannel();
- expose(obj, port2);
- returnValue = transfer(port1, [port1]);
- }
- break;
- case "RELEASE" /* MessageType.RELEASE */:
- {
- returnValue = undefined;
- }
- break;
- default:
- return;
- }
- }
- catch (value) {
- returnValue = { value, [throwMarker]: 0 };
- }
- Promise.resolve(returnValue)
- .catch((value) => {
- return { value, [throwMarker]: 0 };
- })
- .then((returnValue) => {
- const [wireValue, transferables] = toWireValue(returnValue);
- ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
- if (type === "RELEASE" /* MessageType.RELEASE */) {
- // detach and deactive after sending release response above.
- ep.removeEventListener("message", callback);
- closeEndPoint(ep);
- if (finalizer in obj && typeof obj[finalizer] === "function") {
- obj[finalizer]();
- }
- }
- })
- .catch((error) => {
- // Send Serialization Error To Caller
- const [wireValue, transferables] = toWireValue({
- value: new TypeError("Unserializable return value"),
- [throwMarker]: 0,
- });
- ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
- });
- });
- if (ep.start) {
- ep.start();
- }
- }
- function isMessagePort(endpoint) {
- return endpoint.constructor.name === "MessagePort";
- }
- function closeEndPoint(endpoint) {
- if (isMessagePort(endpoint))
- endpoint.close();
- }
- function wrap(ep, target) {
- const pendingListeners = new Map();
- ep.addEventListener("message", function handleMessage(ev) {
- const { data } = ev;
- if (!data || !data.id) {
- return;
- }
- const resolver = pendingListeners.get(data.id);
- if (!resolver) {
- return;
- }
- try {
- resolver(data);
- }
- finally {
- pendingListeners.delete(data.id);
- }
- });
- return createProxy(ep, pendingListeners, [], target);
- }
- function throwIfProxyReleased(isReleased) {
- if (isReleased) {
- throw new Error("Proxy has been released and is not useable");
- }
- }
- function releaseEndpoint(ep) {
- return requestResponseMessage(ep, new Map(), {
- type: "RELEASE" /* MessageType.RELEASE */,
- }).then(() => {
- closeEndPoint(ep);
- });
- }
- const proxyCounter = new WeakMap();
- const proxyFinalizers = "FinalizationRegistry" in globalThis &&
- new FinalizationRegistry((ep) => {
- const newCount = (proxyCounter.get(ep) || 0) - 1;
- proxyCounter.set(ep, newCount);
- if (newCount === 0) {
- releaseEndpoint(ep);
- }
- });
- function registerProxy(proxy, ep) {
- const newCount = (proxyCounter.get(ep) || 0) + 1;
- proxyCounter.set(ep, newCount);
- if (proxyFinalizers) {
- proxyFinalizers.register(proxy, ep, proxy);
- }
- }
- function unregisterProxy(proxy) {
- if (proxyFinalizers) {
- proxyFinalizers.unregister(proxy);
- }
- }
- function createProxy(ep, pendingListeners, path = [], target = function () { }) {
- let isProxyReleased = false;
- const proxy = new Proxy(target, {
- get(_target, prop) {
- throwIfProxyReleased(isProxyReleased);
- if (prop === releaseProxy) {
- return () => {
- unregisterProxy(proxy);
- releaseEndpoint(ep);
- pendingListeners.clear();
- isProxyReleased = true;
- };
- }
- if (prop === "then") {
- if (path.length === 0) {
- return { then: () => proxy };
- }
- const r = requestResponseMessage(ep, pendingListeners, {
- type: "GET" /* MessageType.GET */,
- path: path.map((p) => p.toString()),
- }).then(fromWireValue);
- return r.then.bind(r);
- }
- return createProxy(ep, pendingListeners, [...path, prop]);
- },
- set(_target, prop, rawValue) {
- throwIfProxyReleased(isProxyReleased);
- // FIXME: ES6 Proxy Handler `set` methods are supposed to return a
- // boolean. To show good will, we return true asynchronously ¯\_(ツ)_/¯
- const [value, transferables] = toWireValue(rawValue);
- return requestResponseMessage(ep, pendingListeners, {
- type: "SET" /* MessageType.SET */,
- path: [...path, prop].map((p) => p.toString()),
- value,
- }, transferables).then(fromWireValue);
- },
- apply(_target, _thisArg, rawArgumentList) {
- throwIfProxyReleased(isProxyReleased);
- const last = path[path.length - 1];
- if (last === createEndpoint) {
- return requestResponseMessage(ep, pendingListeners, {
- type: "ENDPOINT" /* MessageType.ENDPOINT */,
- }).then(fromWireValue);
- }
- // We just pretend that `bind()` didn’t happen.
- if (last === "bind") {
- return createProxy(ep, pendingListeners, path.slice(0, -1));
- }
- const [argumentList, transferables] = processArguments(rawArgumentList);
- return requestResponseMessage(ep, pendingListeners, {
- type: "APPLY" /* MessageType.APPLY */,
- path: path.map((p) => p.toString()),
- argumentList,
- }, transferables).then(fromWireValue);
- },
- construct(_target, rawArgumentList) {
- throwIfProxyReleased(isProxyReleased);
- const [argumentList, transferables] = processArguments(rawArgumentList);
- return requestResponseMessage(ep, pendingListeners, {
- type: "CONSTRUCT" /* MessageType.CONSTRUCT */,
- path: path.map((p) => p.toString()),
- argumentList,
- }, transferables).then(fromWireValue);
- },
- });
- registerProxy(proxy, ep);
- return proxy;
- }
- function myFlat(arr) {
- return Array.prototype.concat.apply([], arr);
- }
- function processArguments(argumentList) {
- const processed = argumentList.map(toWireValue);
- return [processed.map((v) => v[0]), myFlat(processed.map((v) => v[1]))];
- }
- const transferCache = new WeakMap();
- function transfer(obj, transfers) {
- transferCache.set(obj, transfers);
- return obj;
- }
- function proxy(obj) {
- return Object.assign(obj, { [proxyMarker]: true });
- }
- function toWireValue(value) {
- for (const [name, handler] of transferHandlers) {
- if (handler.canHandle(value)) {
- const [serializedValue, transferables] = handler.serialize(value);
- return [
- {
- type: "HANDLER" /* WireValueType.HANDLER */,
- name,
- value: serializedValue,
- },
- transferables,
- ];
- }
- }
- return [
- {
- type: "RAW" /* WireValueType.RAW */,
- value,
- },
- transferCache.get(value) || [],
- ];
- }
- function fromWireValue(value) {
- switch (value.type) {
- case "HANDLER" /* WireValueType.HANDLER */:
- return transferHandlers.get(value.name).deserialize(value.value);
- case "RAW" /* WireValueType.RAW */:
- return value.value;
- }
- }
- function requestResponseMessage(ep, pendingListeners, msg, transfers) {
- return new Promise((resolve) => {
- const id = generateUUID();
- pendingListeners.set(id, resolve);
- if (ep.start) {
- ep.start();
- }
- ep.postMessage(Object.assign({ id }, msg), transfers);
- });
- }
- function generateUUID() {
- return new Array(4)
- .fill(0)
- .map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16))
- .join("-");
- }
- const defaultOptions = /* @__PURE__ */ Object.freeze({
- diffTimeout: 1,
- diffEditCost: 4,
- matchThreshold: 0.5,
- matchDistance: 1e3,
- patchDeleteThreshold: 0.5,
- patchMargin: 4,
- matchMaxBits: 32
- });
- function resolveOptions(options) {
- if (options?.__resolved)
- return options;
- const resolved = {
- ...defaultOptions,
- ...options
- };
- Object.defineProperty(resolved, "__resolved", { value: true, enumerable: false });
- return resolved;
- }
- const DIFF_DELETE = -1;
- const DIFF_INSERT = 1;
- const DIFF_EQUAL = 0;
- function createDiff(op, text) {
- return [op, text];
- }
- function diffMain(text1, text2, options, opt_checklines = true, opt_deadline) {
- const resolved = resolveOptions(options);
- if (typeof opt_deadline == "undefined") {
- if (resolved.diffTimeout <= 0)
- opt_deadline = Number.MAX_VALUE;
- else
- opt_deadline = (/* @__PURE__ */ new Date()).getTime() + resolved.diffTimeout * 1e3;
- }
- const deadline = opt_deadline;
- if (text1 == null || text2 == null)
- throw new Error("Null input. (diff_main)");
- if (text1 === text2) {
- if (text1)
- return [createDiff(DIFF_EQUAL, text1)];
- return [];
- }
- const checklines = opt_checklines;
- let commonlength = diffCommonPrefix(text1, text2);
- const commonprefix = text1.substring(0, commonlength);
- text1 = text1.substring(commonlength);
- text2 = text2.substring(commonlength);
- commonlength = diffCommonSuffix(text1, text2);
- const commonsuffix = text1.substring(text1.length - commonlength);
- text1 = text1.substring(0, text1.length - commonlength);
- text2 = text2.substring(0, text2.length - commonlength);
- const diffs = diffCompute(text1, text2, resolved, checklines, deadline);
- if (commonprefix)
- diffs.unshift(createDiff(DIFF_EQUAL, commonprefix));
- if (commonsuffix)
- diffs.push(createDiff(DIFF_EQUAL, commonsuffix));
- diffCleanupMerge(diffs);
- return diffs;
- }
- function diffCompute(text1, text2, options, checklines, deadline) {
- let diffs;
- if (!text1) {
- return [createDiff(DIFF_INSERT, text2)];
- }
- if (!text2) {
- return [createDiff(DIFF_DELETE, text1)];
- }
- const longtext = text1.length > text2.length ? text1 : text2;
- const shorttext = text1.length > text2.length ? text2 : text1;
- const i = longtext.indexOf(shorttext);
- if (i !== -1) {
- diffs = [createDiff(DIFF_INSERT, longtext.substring(0, i)), createDiff(DIFF_EQUAL, shorttext), createDiff(DIFF_INSERT, longtext.substring(i + shorttext.length))];
- if (text1.length > text2.length)
- diffs[0][0] = diffs[2][0] = DIFF_DELETE;
- return diffs;
- }
- if (shorttext.length === 1) {
- return [createDiff(DIFF_DELETE, text1), createDiff(DIFF_INSERT, text2)];
- }
- const hm = diffHalfMatch(text1, text2, options);
- if (hm) {
- const text1_a = hm[0];
- const text1_b = hm[1];
- const text2_a = hm[2];
- const text2_b = hm[3];
- const mid_common = hm[4];
- const diffs_a = diffMain(text1_a, text2_a, options, checklines, deadline);
- const diffs_b = diffMain(text1_b, text2_b, options, checklines, deadline);
- return diffs_a.concat([createDiff(DIFF_EQUAL, mid_common)], diffs_b);
- }
- if (checklines && text1.length > 100 && text2.length > 100)
- return diffLineMode(text1, text2, options, deadline);
- return diffBisect(text1, text2, options, deadline);
- }
- function diffLineMode(text1, text2, options, deadline) {
- const a = diffLinesToChars(text1, text2);
- text1 = a.chars1;
- text2 = a.chars2;
- const linearray = a.lineArray;
- const diffs = diffMain(text1, text2, options, false, deadline);
- diffCharsToLines(diffs, linearray);
- diffCleanupSemantic(diffs);
- diffs.push(createDiff(DIFF_EQUAL, ""));
- let pointer = 0;
- let count_delete = 0;
- let count_insert = 0;
- let text_delete = "";
- let text_insert = "";
- while (pointer < diffs.length) {
- switch (diffs[pointer][0]) {
- case DIFF_INSERT:
- count_insert++;
- text_insert += diffs[pointer][1];
- break;
- case DIFF_DELETE:
- count_delete++;
- text_delete += diffs[pointer][1];
- break;
- case DIFF_EQUAL:
- if (count_delete >= 1 && count_insert >= 1) {
- diffs.splice(pointer - count_delete - count_insert, count_delete + count_insert);
- pointer = pointer - count_delete - count_insert;
- const subDiff = diffMain(text_delete, text_insert, options, false, deadline);
- for (let j = subDiff.length - 1; j >= 0; j--)
- diffs.splice(pointer, 0, subDiff[j]);
- pointer = pointer + subDiff.length;
- }
- count_insert = 0;
- count_delete = 0;
- text_delete = "";
- text_insert = "";
- break;
- }
- pointer++;
- }
- diffs.pop();
- return diffs;
- }
- function diffBisect(text1, text2, options, deadline) {
- const text1_length = text1.length;
- const text2_length = text2.length;
- const max_d = Math.ceil((text1_length + text2_length) / 2);
- const v_offset = max_d;
- const v_length = 2 * max_d;
- const v1 = new Array(v_length);
- const v2 = new Array(v_length);
- for (let x = 0; x < v_length; x++) {
- v1[x] = -1;
- v2[x] = -1;
- }
- v1[v_offset + 1] = 0;
- v2[v_offset + 1] = 0;
- const delta = text1_length - text2_length;
- const front = delta % 2 !== 0;
- let k1start = 0;
- let k1end = 0;
- let k2start = 0;
- let k2end = 0;
- for (let d = 0; d < max_d; d++) {
- if ((/* @__PURE__ */ new Date()).getTime() > deadline)
- break;
- for (let k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {
- const k1_offset = v_offset + k1;
- let x1;
- if (k1 === -d || k1 !== d && v1[k1_offset - 1] < v1[k1_offset + 1])
- x1 = v1[k1_offset + 1];
- else
- x1 = v1[k1_offset - 1] + 1;
- let y1 = x1 - k1;
- while (x1 < text1_length && y1 < text2_length && text1.charAt(x1) === text2.charAt(y1)) {
- x1++;
- y1++;
- }
- v1[k1_offset] = x1;
- if (x1 > text1_length) {
- k1end += 2;
- } else if (y1 > text2_length) {
- k1start += 2;
- } else if (front) {
- const k2_offset = v_offset + delta - k1;
- if (k2_offset >= 0 && k2_offset < v_length && v2[k2_offset] !== -1) {
- const x2 = text1_length - v2[k2_offset];
- if (x1 >= x2) {
- return diffBisectSplit(text1, text2, options, x1, y1, deadline);
- }
- }
- }
- }
- for (let k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {
- const k2_offset = v_offset + k2;
- let x2;
- if (k2 === -d || k2 !== d && v2[k2_offset - 1] < v2[k2_offset + 1])
- x2 = v2[k2_offset + 1];
- else
- x2 = v2[k2_offset - 1] + 1;
- let y2 = x2 - k2;
- while (x2 < text1_length && y2 < text2_length && text1.charAt(text1_length - x2 - 1) === text2.charAt(text2_length - y2 - 1)) {
- x2++;
- y2++;
- }
- v2[k2_offset] = x2;
- if (x2 > text1_length) {
- k2end += 2;
- } else if (y2 > text2_length) {
- k2start += 2;
- } else if (!front) {
- const k1_offset = v_offset + delta - k2;
- if (k1_offset >= 0 && k1_offset < v_length && v1[k1_offset] !== -1) {
- const x1 = v1[k1_offset];
- const y1 = v_offset + x1 - k1_offset;
- x2 = text1_length - x2;
- if (x1 >= x2) {
- return diffBisectSplit(text1, text2, options, x1, y1, deadline);
- }
- }
- }
- }
- }
- return [createDiff(DIFF_DELETE, text1), createDiff(DIFF_INSERT, text2)];
- }
- function diffBisectSplit(text1, text2, options, x, y, deadline) {
- const text1a = text1.substring(0, x);
- const text2a = text2.substring(0, y);
- const text1b = text1.substring(x);
- const text2b = text2.substring(y);
- const diffs = diffMain(text1a, text2a, options, false, deadline);
- const diffsb = diffMain(text1b, text2b, options, false, deadline);
- return diffs.concat(diffsb);
- }
- function diffLinesToChars(text1, text2) {
- const lineArray = [];
- const lineHash = {};
- let maxLines = 4e4;
- lineArray[0] = "";
- function diffLinesToCharsMunge(text) {
- let chars = "";
- let lineStart = 0;
- let lineEnd = -1;
- let lineArrayLength = lineArray.length;
- while (lineEnd < text.length - 1) {
- lineEnd = text.indexOf("\n", lineStart);
- if (lineEnd === -1)
- lineEnd = text.length - 1;
- let line = text.substring(lineStart, lineEnd + 1);
- if (lineHash.hasOwnProperty ? Object.prototype.hasOwnProperty.call(lineHash, line) : lineHash[line] !== void 0) {
- chars += String.fromCharCode(lineHash[line]);
- } else {
- if (lineArrayLength === maxLines) {
- line = text.substring(lineStart);
- lineEnd = text.length;
- }
- chars += String.fromCharCode(lineArrayLength);
- lineHash[line] = lineArrayLength;
- lineArray[lineArrayLength++] = line;
- }
- lineStart = lineEnd + 1;
- }
- return chars;
- }
- const chars1 = diffLinesToCharsMunge(text1);
- maxLines = 65535;
- const chars2 = diffLinesToCharsMunge(text2);
- return { chars1, chars2, lineArray };
- }
- function diffCharsToLines(diffs, lineArray) {
- for (let i = 0; i < diffs.length; i++) {
- const chars = diffs[i][1];
- const text = [];
- for (let j = 0; j < chars.length; j++)
- text[j] = lineArray[chars.charCodeAt(j)];
- diffs[i][1] = text.join("");
- }
- }
- function diffCommonPrefix(text1, text2) {
- if (!text1 || !text2 || text1.charAt(0) !== text2.charAt(0))
- return 0;
- let pointermin = 0;
- let pointermax = Math.min(text1.length, text2.length);
- let pointermid = pointermax;
- let pointerstart = 0;
- while (pointermin < pointermid) {
- if (text1.substring(pointerstart, pointermid) === text2.substring(pointerstart, pointermid)) {
- pointermin = pointermid;
- pointerstart = pointermin;
- } else {
- pointermax = pointermid;
- }
- pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
- }
- return pointermid;
- }
- function diffCommonSuffix(text1, text2) {
- if (!text1 || !text2 || text1.charAt(text1.length - 1) !== text2.charAt(text2.length - 1)) {
- return 0;
- }
- let pointermin = 0;
- let pointermax = Math.min(text1.length, text2.length);
- let pointermid = pointermax;
- let pointerend = 0;
- while (pointermin < pointermid) {
- if (text1.substring(text1.length - pointermid, text1.length - pointerend) === text2.substring(text2.length - pointermid, text2.length - pointerend)) {
- pointermin = pointermid;
- pointerend = pointermin;
- } else {
- pointermax = pointermid;
- }
- pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
- }
- return pointermid;
- }
- function diffCommonOverlap(text1, text2) {
- const text1_length = text1.length;
- const text2_length = text2.length;
- if (text1_length === 0 || text2_length === 0)
- return 0;
- if (text1_length > text2_length)
- text1 = text1.substring(text1_length - text2_length);
- else if (text1_length < text2_length)
- text2 = text2.substring(0, text1_length);
- const text_length = Math.min(text1_length, text2_length);
- if (text1 === text2)
- return text_length;
- let best = 0;
- let length = 1;
- while (true) {
- const pattern = text1.substring(text_length - length);
- const found = text2.indexOf(pattern);
- if (found === -1)
- return best;
- length += found;
- if (found === 0 || text1.substring(text_length - length) === text2.substring(0, length)) {
- best = length;
- length++;
- }
- }
- }
- function diffHalfMatch(text1, text2, options) {
- if (options.diffTimeout <= 0) {
- return null;
- }
- const longtext = text1.length > text2.length ? text1 : text2;
- const shorttext = text1.length > text2.length ? text2 : text1;
- if (longtext.length < 4 || shorttext.length * 2 < longtext.length)
- return null;
- function diffHalfMatchI(longtext2, shorttext2, i) {
- const seed = longtext2.substring(i, i + Math.floor(longtext2.length / 4));
- let j = -1;
- let best_common = "";
- let best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b;
- while ((j = shorttext2.indexOf(seed, j + 1)) !== -1) {
- const prefixLength = diffCommonPrefix(longtext2.substring(i), shorttext2.substring(j));
- const suffixLength = diffCommonSuffix(longtext2.substring(0, i), shorttext2.substring(0, j));
- if (best_common.length < suffixLength + prefixLength) {
- best_common = shorttext2.substring(j - suffixLength, j) + shorttext2.substring(j, j + prefixLength);
- best_longtext_a = longtext2.substring(0, i - suffixLength);
- best_longtext_b = longtext2.substring(i + prefixLength);
- best_shorttext_a = shorttext2.substring(0, j - suffixLength);
- best_shorttext_b = shorttext2.substring(j + prefixLength);
- }
- }
- if (best_common.length * 2 >= longtext2.length)
- return [best_longtext_a, best_longtext_b, best_shorttext_a, best_shorttext_b, best_common];
- else
- return null;
- }
- const hm1 = diffHalfMatchI(longtext, shorttext, Math.ceil(longtext.length / 4));
- const hm2 = diffHalfMatchI(longtext, shorttext, Math.ceil(longtext.length / 2));
- let hm;
- if (!hm1 && !hm2) {
- return null;
- } else if (!hm2) {
- hm = hm1;
- } else if (!hm1) {
- hm = hm2;
- } else {
- hm = hm1[4].length > hm2[4].length ? hm1 : hm2;
- }
- let text1_a, text1_b, text2_a, text2_b;
- if (text1.length > text2.length) {
- text1_a = hm[0];
- text1_b = hm[1];
- text2_a = hm[2];
- text2_b = hm[3];
- } else {
- text2_a = hm[0];
- text2_b = hm[1];
- text1_a = hm[2];
- text1_b = hm[3];
- }
- const mid_common = hm[4];
- return [text1_a, text1_b, text2_a, text2_b, mid_common];
- }
- function diffCleanupSemantic(diffs) {
- let changes = false;
- const equalities = [];
- let equalitiesLength = 0;
- let lastEquality = null;
- let pointer = 0;
- let length_insertions1 = 0;
- let length_deletions1 = 0;
- let length_insertions2 = 0;
- let length_deletions2 = 0;
- while (pointer < diffs.length) {
- if (diffs[pointer][0] === DIFF_EQUAL) {
- equalities[equalitiesLength++] = pointer;
- length_insertions1 = length_insertions2;
- length_deletions1 = length_deletions2;
- length_insertions2 = 0;
- length_deletions2 = 0;
- lastEquality = diffs[pointer][1];
- } else {
- if (diffs[pointer][0] === DIFF_INSERT)
- length_insertions2 += diffs[pointer][1].length;
- else
- length_deletions2 += diffs[pointer][1].length;
- if (lastEquality && lastEquality.length <= Math.max(length_insertions1, length_deletions1) && lastEquality.length <= Math.max(length_insertions2, length_deletions2)) {
- diffs.splice(equalities[equalitiesLength - 1], 0, createDiff(DIFF_DELETE, lastEquality));
- diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;
- equalitiesLength--;
- equalitiesLength--;
- pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1;
- length_insertions1 = 0;
- length_deletions1 = 0;
- length_insertions2 = 0;
- length_deletions2 = 0;
- lastEquality = null;
- changes = true;
- }
- }
- pointer++;
- }
- if (changes)
- diffCleanupMerge(diffs);
- diffCleanupSemanticLossless(diffs);
- pointer = 1;
- while (pointer < diffs.length) {
- if (diffs[pointer - 1][0] === DIFF_DELETE && diffs[pointer][0] === DIFF_INSERT) {
- const deletion = diffs[pointer - 1][1];
- const insertion = diffs[pointer][1];
- const overlap_length1 = diffCommonOverlap(deletion, insertion);
- const overlap_length2 = diffCommonOverlap(insertion, deletion);
- if (overlap_length1 >= overlap_length2) {
- if (overlap_length1 >= deletion.length / 2 || overlap_length1 >= insertion.length / 2) {
- diffs.splice(pointer, 0, createDiff(DIFF_EQUAL, insertion.substring(0, overlap_length1)));
- diffs[pointer - 1][1] = deletion.substring(0, deletion.length - overlap_length1);
- diffs[pointer + 1][1] = insertion.substring(overlap_length1);
- pointer++;
- }
- } else {
- if (overlap_length2 >= deletion.length / 2 || overlap_length2 >= insertion.length / 2) {
- diffs.splice(pointer, 0, createDiff(DIFF_EQUAL, deletion.substring(0, overlap_length2)));
- diffs[pointer - 1][0] = DIFF_INSERT;
- diffs[pointer - 1][1] = insertion.substring(0, insertion.length - overlap_length2);
- diffs[pointer + 1][0] = DIFF_DELETE;
- diffs[pointer + 1][1] = deletion.substring(overlap_length2);
- pointer++;
- }
- }
- pointer++;
- }
- pointer++;
- }
- }
- const nonAlphaNumericRegex_ = /[^a-z0-9]/i;
- const whitespaceRegex_ = /\s/;
- const linebreakRegex_ = /[\r\n]/;
- const blanklineEndRegex_ = /\n\r?\n$/;
- const blanklineStartRegex_ = /^\r?\n\r?\n/;
- function diffCleanupSemanticLossless(diffs) {
- function diffCleanupSemanticScore(one, two) {
- if (!one || !two) {
- return 6;
- }
- const char1 = one.charAt(one.length - 1);
- const char2 = two.charAt(0);
- const nonAlphaNumeric1 = char1.match(nonAlphaNumericRegex_);
- const nonAlphaNumeric2 = char2.match(nonAlphaNumericRegex_);
- const whitespace1 = nonAlphaNumeric1 && char1.match(whitespaceRegex_);
- const whitespace2 = nonAlphaNumeric2 && char2.match(whitespaceRegex_);
- const lineBreak1 = whitespace1 && char1.match(linebreakRegex_);
- const lineBreak2 = whitespace2 && char2.match(linebreakRegex_);
- const blankLine1 = lineBreak1 && one.match(blanklineEndRegex_);
- const blankLine2 = lineBreak2 && two.match(blanklineStartRegex_);
- if (blankLine1 || blankLine2) {
- return 5;
- } else if (lineBreak1 || lineBreak2) {
- return 4;
- } else if (nonAlphaNumeric1 && !whitespace1 && whitespace2) {
- return 3;
- } else if (whitespace1 || whitespace2) {
- return 2;
- } else if (nonAlphaNumeric1 || nonAlphaNumeric2) {
- return 1;
- }
- return 0;
- }
- let pointer = 1;
- while (pointer < diffs.length - 1) {
- if (diffs[pointer - 1][0] === DIFF_EQUAL && diffs[pointer + 1][0] === DIFF_EQUAL) {
- let equality1 = diffs[pointer - 1][1];
- let edit = diffs[pointer][1];
- let equality2 = diffs[pointer + 1][1];
- const commonOffset = diffCommonSuffix(equality1, edit);
- if (commonOffset) {
- const commonString = edit.substring(edit.length - commonOffset);
- equality1 = equality1.substring(0, equality1.length - commonOffset);
- edit = commonString + edit.substring(0, edit.length - commonOffset);
- equality2 = commonString + equality2;
- }
- let bestEquality1 = equality1;
- let bestEdit = edit;
- let bestEquality2 = equality2;
- let bestScore = diffCleanupSemanticScore(equality1, edit) + diffCleanupSemanticScore(edit, equality2);
- while (edit.charAt(0) === equality2.charAt(0)) {
- equality1 += edit.charAt(0);
- edit = edit.substring(1) + equality2.charAt(0);
- equality2 = equality2.substring(1);
- const score = diffCleanupSemanticScore(equality1, edit) + diffCleanupSemanticScore(edit, equality2);
- if (score >= bestScore) {
- bestScore = score;
- bestEquality1 = equality1;
- bestEdit = edit;
- bestEquality2 = equality2;
- }
- }
- if (diffs[pointer - 1][1] !== bestEquality1) {
- if (bestEquality1) {
- diffs[pointer - 1][1] = bestEquality1;
- } else {
- diffs.splice(pointer - 1, 1);
- pointer--;
- }
- diffs[pointer][1] = bestEdit;
- if (bestEquality2) {
- diffs[pointer + 1][1] = bestEquality2;
- } else {
- diffs.splice(pointer + 1, 1);
- pointer--;
- }
- }
- }
- pointer++;
- }
- }
- function diffCleanupMerge(diffs) {
- diffs.push(createDiff(DIFF_EQUAL, ""));
- let pointer = 0;
- let count_delete = 0;
- let count_insert = 0;
- let text_delete = "";
- let text_insert = "";
- let commonlength;
- while (pointer < diffs.length) {
- switch (diffs[pointer][0]) {
- case DIFF_INSERT:
- count_insert++;
- text_insert += diffs[pointer][1];
- pointer++;
- break;
- case DIFF_DELETE:
- count_delete++;
- text_delete += diffs[pointer][1];
- pointer++;
- break;
- case DIFF_EQUAL:
- if (count_delete + count_insert > 1) {
- if (count_delete !== 0 && count_insert !== 0) {
- commonlength = diffCommonPrefix(text_insert, text_delete);
- if (commonlength !== 0) {
- if (pointer - count_delete - count_insert > 0 && diffs[pointer - count_delete - count_insert - 1][0] === DIFF_EQUAL) {
- diffs[pointer - count_delete - count_insert - 1][1] += text_insert.substring(0, commonlength);
- } else {
- diffs.splice(0, 0, createDiff(DIFF_EQUAL, text_insert.substring(0, commonlength)));
- pointer++;
- }
- text_insert = text_insert.substring(commonlength);
- text_delete = text_delete.substring(commonlength);
- }
- commonlength = diffCommonSuffix(text_insert, text_delete);
- if (commonlength !== 0) {
- diffs[pointer][1] = text_insert.substring(text_insert.length - commonlength) + diffs[pointer][1];
- text_insert = text_insert.substring(0, text_insert.length - commonlength);
- text_delete = text_delete.substring(0, text_delete.length - commonlength);
- }
- }
- pointer -= count_delete + count_insert;
- diffs.splice(pointer, count_delete + count_insert);
- if (text_delete.length) {
- diffs.splice(pointer, 0, createDiff(DIFF_DELETE, text_delete));
- pointer++;
- }
- if (text_insert.length) {
- diffs.splice(pointer, 0, createDiff(DIFF_INSERT, text_insert));
- pointer++;
- }
- pointer++;
- } else if (pointer !== 0 && diffs[pointer - 1][0] === DIFF_EQUAL) {
- diffs[pointer - 1][1] += diffs[pointer][1];
- diffs.splice(pointer, 1);
- } else {
- pointer++;
- }
- count_insert = 0;
- count_delete = 0;
- text_delete = "";
- text_insert = "";
- break;
- }
- }
- if (diffs[diffs.length - 1][1] === "")
- diffs.pop();
- let changes = false;
- pointer = 1;
- while (pointer < diffs.length - 1) {
- if (diffs[pointer - 1][0] === DIFF_EQUAL && diffs[pointer + 1][0] === DIFF_EQUAL) {
- if (diffs[pointer][1].substring(diffs[pointer][1].length - diffs[pointer - 1][1].length) === diffs[pointer - 1][1]) {
- diffs[pointer][1] = diffs[pointer - 1][1] + diffs[pointer][1].substring(0, diffs[pointer][1].length - diffs[pointer - 1][1].length);
- diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1];
- diffs.splice(pointer - 1, 1);
- changes = true;
- } else if (diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) === diffs[pointer + 1][1]) {
- diffs[pointer - 1][1] += diffs[pointer + 1][1];
- diffs[pointer][1] = diffs[pointer][1].substring(diffs[pointer + 1][1].length) + diffs[pointer + 1][1];
- diffs.splice(pointer + 1, 1);
- changes = true;
- }
- }
- pointer++;
- }
- if (changes)
- diffCleanupMerge(diffs);
- }
- function calculateDiff(left, right) {
- const changes = diffMain(left, right);
- diffCleanupSemantic(changes);
- return changes;
- }
- const exports$1 = {
- calculateDiff
- };
- expose(exports$1);
- })();
|