mirror of
https://github.com/thiloho/archtika.git
synced 2025-11-22 02:41:35 +01:00
Use js-diff instead of diff-match-patch for word level diffs
This commit is contained in:
@@ -10,7 +10,7 @@ let
|
|||||||
web = buildNpmPackage {
|
web = buildNpmPackage {
|
||||||
name = "web-app";
|
name = "web-app";
|
||||||
src = ../web-app;
|
src = ../web-app;
|
||||||
npmDepsHash = "sha256-J58LwSEQa0p6J6h/wPhpGY/60n9a7TOV5WfNm4K1NH0=";
|
npmDepsHash = "sha256-ab7MJ5vl6XNaAHTyzRxj/Zpk1nEKQLzGmPGJdDrdemg=";
|
||||||
npmFlags = [ "--legacy-peer-deps" ];
|
npmFlags = [ "--legacy-peer-deps" ];
|
||||||
installPhase = ''
|
installPhase = ''
|
||||||
mkdir -p $out/web-app
|
mkdir -p $out/web-app
|
||||||
|
|||||||
25
web-app/package-lock.json
generated
25
web-app/package-lock.json
generated
@@ -8,7 +8,7 @@
|
|||||||
"name": "web-app",
|
"name": "web-app",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"diff-match-patch": "1.0.5",
|
"diff": "7.0.0",
|
||||||
"highlight.js": "11.11.1",
|
"highlight.js": "11.11.1",
|
||||||
"isomorphic-dompurify": "2.22.0",
|
"isomorphic-dompurify": "2.22.0",
|
||||||
"marked": "15.0.7",
|
"marked": "15.0.7",
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
"@sveltejs/adapter-node": "5.2.12",
|
"@sveltejs/adapter-node": "5.2.12",
|
||||||
"@sveltejs/kit": "2.20.2",
|
"@sveltejs/kit": "2.20.2",
|
||||||
"@sveltejs/vite-plugin-svelte": "5.0.3",
|
"@sveltejs/vite-plugin-svelte": "5.0.3",
|
||||||
"@types/diff-match-patch": "1.0.36",
|
"@types/diff": "7.0.2",
|
||||||
"@types/eslint": "9.6.1",
|
"@types/eslint": "9.6.1",
|
||||||
"@types/eslint__js": "9.14.0",
|
"@types/eslint__js": "9.14.0",
|
||||||
"@types/eslint-config-prettier": "6.11.3",
|
"@types/eslint-config-prettier": "6.11.3",
|
||||||
@@ -1425,10 +1425,10 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/diff-match-patch": {
|
"node_modules/@types/diff": {
|
||||||
"version": "1.0.36",
|
"version": "7.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/diff-match-patch/-/diff-match-patch-1.0.36.tgz",
|
"resolved": "https://registry.npmjs.org/@types/diff/-/diff-7.0.2.tgz",
|
||||||
"integrity": "sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg==",
|
"integrity": "sha512-JSWRMozjFKsGlEjiiKajUjIJVKuKdE3oVy2DNtK+fUo8q82nhFZ2CPQwicAIkXrofahDXrWJ7mjelvZphMS98Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
@@ -2125,11 +2125,14 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/diff-match-patch": {
|
"node_modules/diff": {
|
||||||
"version": "1.0.5",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz",
|
||||||
"integrity": "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==",
|
"integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==",
|
||||||
"license": "Apache-2.0"
|
"license": "BSD-3-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.3.1"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/dompurify": {
|
"node_modules/dompurify": {
|
||||||
"version": "3.2.4",
|
"version": "3.2.4",
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
"@sveltejs/adapter-node": "5.2.12",
|
"@sveltejs/adapter-node": "5.2.12",
|
||||||
"@sveltejs/kit": "2.20.2",
|
"@sveltejs/kit": "2.20.2",
|
||||||
"@sveltejs/vite-plugin-svelte": "5.0.3",
|
"@sveltejs/vite-plugin-svelte": "5.0.3",
|
||||||
"@types/diff-match-patch": "1.0.36",
|
"@types/diff": "7.0.2",
|
||||||
"@types/eslint": "9.6.1",
|
"@types/eslint": "9.6.1",
|
||||||
"@types/eslint__js": "9.14.0",
|
"@types/eslint__js": "9.14.0",
|
||||||
"@types/eslint-config-prettier": "6.11.3",
|
"@types/eslint-config-prettier": "6.11.3",
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
"vite": "6.2.5"
|
"vite": "6.2.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"diff-match-patch": "1.0.5",
|
"diff": "7.0.0",
|
||||||
"highlight.js": "11.11.1",
|
"highlight.js": "11.11.1",
|
||||||
"isomorphic-dompurify": "2.22.0",
|
"isomorphic-dompurify": "2.22.0",
|
||||||
"marked": "15.0.7",
|
"marked": "15.0.7",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { API_BASE_PREFIX, apiRequest } from "$lib/server/utils";
|
|||||||
import type { ChangeLog, User, Collab } from "$lib/db-schema";
|
import type { ChangeLog, User, Collab } from "$lib/db-schema";
|
||||||
import DiffMatchPatch from "diff-match-patch";
|
import DiffMatchPatch from "diff-match-patch";
|
||||||
import { PAGINATION_MAX_ITEMS } from "$lib/utils";
|
import { PAGINATION_MAX_ITEMS } from "$lib/utils";
|
||||||
|
import * as Diff from "diff";
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ parent, fetch, params, url }) => {
|
export const load: PageServerLoad = async ({ parent, fetch, params, url }) => {
|
||||||
const userFilter = url.searchParams.get("user");
|
const userFilter = url.searchParams.get("user");
|
||||||
@@ -76,22 +77,19 @@ export const actions: Actions = {
|
|||||||
computeDiff: async ({ request, fetch }) => {
|
computeDiff: async ({ request, fetch }) => {
|
||||||
const data = await request.formData();
|
const data = await request.formData();
|
||||||
|
|
||||||
const dmp = new DiffMatchPatch();
|
|
||||||
|
|
||||||
const htmlDiff = (oldValue: string, newValue: string) => {
|
const htmlDiff = (oldValue: string, newValue: string) => {
|
||||||
const diff = dmp.diff_main(oldValue, newValue);
|
const diff = Diff.diffWordsWithSpace(oldValue, newValue);
|
||||||
|
|
||||||
return diff
|
return diff
|
||||||
.map(([op, text]) => {
|
.map((part) => {
|
||||||
const escapedText = text.replace(/</g, "<").replace(/>/g, ">");
|
const escapedText = part.value.replace(/</g, "<").replace(/>/g, ">");
|
||||||
|
|
||||||
switch (op) {
|
if (part.added) {
|
||||||
case 1:
|
return `<ins>${escapedText}</ins>`;
|
||||||
return `<ins>${escapedText}</ins>`;
|
} else if (part.removed) {
|
||||||
case -1:
|
return `<del>${escapedText}</del>`;
|
||||||
return `<del>${escapedText}</del>`;
|
} else {
|
||||||
default:
|
return escapedText;
|
||||||
return escapedText;
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.join("");
|
.join("");
|
||||||
@@ -112,8 +110,12 @@ export const actions: Actions = {
|
|||||||
return {
|
return {
|
||||||
logId: data.get("id"),
|
logId: data.get("id"),
|
||||||
currentDiff: htmlDiff(
|
currentDiff: htmlDiff(
|
||||||
JSON.stringify(log.old_value, null, 2),
|
JSON.stringify(log.old_value, null, 2)
|
||||||
|
.replace(/\\r\\n|\\n|\\r/g, "\n")
|
||||||
|
.replace(/\\\"/g, '"'),
|
||||||
JSON.stringify(log.new_value, null, 2)
|
JSON.stringify(log.new_value, null, 2)
|
||||||
|
.replace(/\\r\\n|\\n|\\r/g, "\n")
|
||||||
|
.replace(/\\\"/g, '"')
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,9 +141,7 @@
|
|||||||
<button type="submit">Compute diff</button>
|
<button type="submit">Compute diff</button>
|
||||||
</form>
|
</form>
|
||||||
{#if form?.logId === id && form?.currentDiff}
|
{#if form?.logId === id && form?.currentDiff}
|
||||||
<pre>{@html form.currentDiff
|
<pre>{@html form.currentDiff}</pre>
|
||||||
.replace(/\\\"/g, '"')
|
|
||||||
.replace(/\\r\\n|\\n|\\r/g, "\n")}</pre>
|
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user