mirror of
https://github.com/denoland/std.git
synced 2024-11-21 20:50:22 +00:00
refactor(internal): cleanup and restructure (#4698)
* refactor(internal): cleanup * revert * work * fix * fix * fix * tweaks * fix
This commit is contained in:
parent
f24ac87982
commit
a63a439c11
8
internal/_types.ts
Normal file
8
internal/_types.ts
Normal file
@ -0,0 +1,8 @@
|
||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
export type DiffType = "removed" | "common" | "added";
|
||||
|
||||
export interface DiffResult<T> {
|
||||
type: DiffType;
|
||||
value: T;
|
||||
details?: Array<DiffResult<T>>;
|
||||
}
|
73
internal/build_message.ts
Normal file
73
internal/build_message.ts
Normal file
@ -0,0 +1,73 @@
|
||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
// This module is browser compatible.
|
||||
|
||||
import { bgGreen, bgRed, bold, gray, green, red, white } from "@std/fmt/colors";
|
||||
import type { DiffResult, DiffType } from "./_types.ts";
|
||||
|
||||
/**
|
||||
* Colors the output of assertion diffs
|
||||
* @param diffType Difference type, either added or removed
|
||||
*/
|
||||
function createColor(
|
||||
diffType: DiffType,
|
||||
{ background = false } = {},
|
||||
): (s: string) => string {
|
||||
// TODO(@littledivy): Remove this when we can detect
|
||||
// true color terminals.
|
||||
// https://github.com/denoland/deno_std/issues/2575
|
||||
background = false;
|
||||
switch (diffType) {
|
||||
case "added":
|
||||
return (s: string): string =>
|
||||
background ? bgGreen(white(s)) : green(bold(s));
|
||||
case "removed":
|
||||
return (s: string): string => background ? bgRed(white(s)) : red(bold(s));
|
||||
default:
|
||||
return white;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefixes `+` or `-` in diff output
|
||||
* @param diffType Difference type, either added or removed
|
||||
*/
|
||||
function createSign(diffType: DiffType): string {
|
||||
switch (diffType) {
|
||||
case "added":
|
||||
return "+ ";
|
||||
case "removed":
|
||||
return "- ";
|
||||
default:
|
||||
return " ";
|
||||
}
|
||||
}
|
||||
|
||||
export function buildMessage(
|
||||
diffResult: ReadonlyArray<DiffResult<string>>,
|
||||
{ stringDiff = false } = {},
|
||||
): string[] {
|
||||
const messages: string[] = [];
|
||||
const diffMessages: string[] = [];
|
||||
messages.push("");
|
||||
messages.push("");
|
||||
messages.push(
|
||||
` ${gray(bold("[Diff]"))} ${red(bold("Actual"))} / ${
|
||||
green(bold("Expected"))
|
||||
}`,
|
||||
);
|
||||
messages.push("");
|
||||
messages.push("");
|
||||
diffResult.forEach((result) => {
|
||||
const c = createColor(result.type);
|
||||
const line = result.details?.map((detail) =>
|
||||
detail.type !== "common"
|
||||
? createColor(detail.type, { background: true })(detail.value)
|
||||
: detail.value
|
||||
).join("") ?? result.value;
|
||||
diffMessages.push(c(`${createSign(result.type)}${line}`));
|
||||
});
|
||||
messages.push(...(stringDiff ? [diffMessages.join("")] : diffMessages));
|
||||
messages.push("");
|
||||
|
||||
return messages;
|
||||
}
|
@ -3,6 +3,8 @@
|
||||
"version": "0.225.0",
|
||||
"exports": {
|
||||
".": "./mod.ts",
|
||||
"./build-message": "./build_message.ts",
|
||||
"./diff-str": "./diff_str.ts",
|
||||
"./diff": "./diff.ts",
|
||||
"./format": "./format.ts"
|
||||
}
|
||||
|
244
internal/diff.ts
244
internal/diff.ts
@ -1,27 +1,13 @@
|
||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
// This module is browser compatible.
|
||||
|
||||
import { bgGreen, bgRed, bold, gray, green, red, white } from "@std/fmt/colors";
|
||||
import type { DiffResult, DiffType } from "./_types.ts";
|
||||
|
||||
interface FarthestPoint {
|
||||
y: number;
|
||||
id: number;
|
||||
}
|
||||
|
||||
export const DiffType = {
|
||||
removed: "removed",
|
||||
common: "common",
|
||||
added: "added",
|
||||
} as const;
|
||||
|
||||
export type DiffType = keyof typeof DiffType;
|
||||
|
||||
export interface DiffResult<T> {
|
||||
type: DiffType;
|
||||
value: T;
|
||||
details?: Array<DiffResult<T>>;
|
||||
}
|
||||
|
||||
const REMOVED = 1;
|
||||
const COMMON = 2;
|
||||
const ADDED = 3;
|
||||
@ -74,16 +60,16 @@ export function diff<T>(A: T[], B: T[]): Array<DiffResult<T>> {
|
||||
if (!N) {
|
||||
return [
|
||||
...prefixCommon.map(
|
||||
(c): DiffResult<typeof c> => ({ type: DiffType.common, value: c }),
|
||||
(c): DiffResult<typeof c> => ({ type: "common", value: c }),
|
||||
),
|
||||
...A.map(
|
||||
(a): DiffResult<typeof a> => ({
|
||||
type: swapped ? DiffType.added : DiffType.removed,
|
||||
type: swapped ? "added" : "removed",
|
||||
value: a,
|
||||
}),
|
||||
),
|
||||
...suffixCommon.map(
|
||||
(c): DiffResult<typeof c> => ({ type: DiffType.common, value: c }),
|
||||
(c): DiffResult<typeof c> => ({ type: "common", value: c }),
|
||||
),
|
||||
];
|
||||
}
|
||||
@ -129,18 +115,18 @@ export function diff<T>(A: T[], B: T[]): Array<DiffResult<T>> {
|
||||
const prev = j!;
|
||||
if (type === REMOVED) {
|
||||
result.unshift({
|
||||
type: swapped ? DiffType.removed : DiffType.added,
|
||||
type: swapped ? "removed" : "added",
|
||||
value: B[b]!,
|
||||
});
|
||||
b -= 1;
|
||||
} else if (type === ADDED) {
|
||||
result.unshift({
|
||||
type: swapped ? DiffType.added : DiffType.removed,
|
||||
type: swapped ? "added" : "removed",
|
||||
value: A[a]!,
|
||||
});
|
||||
a -= 1;
|
||||
} else {
|
||||
result.unshift({ type: DiffType.common, value: A[a]! });
|
||||
result.unshift({ type: "common", value: A[a]! });
|
||||
a -= 1;
|
||||
b -= 1;
|
||||
}
|
||||
@ -237,223 +223,13 @@ export function diff<T>(A: T[], B: T[]): Array<DiffResult<T>> {
|
||||
}
|
||||
return [
|
||||
...prefixCommon.map(
|
||||
(c): DiffResult<typeof c> => ({ type: DiffType.common, value: c }),
|
||||
(c): DiffResult<typeof c> => ({ type: "common", value: c }),
|
||||
),
|
||||
...backTrace(A, B, currentFP, swapped),
|
||||
...suffixCommon.map(
|
||||
(c): DiffResult<typeof c> => ({ type: DiffType.common, value: c }),
|
||||
(c): DiffResult<typeof c> => ({ type: "common", value: c }),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the differences between the actual and expected strings
|
||||
* Partially inspired from https://github.com/kpdecker/jsdiff
|
||||
* @param A Actual string
|
||||
* @param B Expected string
|
||||
*/
|
||||
export function diffstr(A: string, B: string): DiffResult<string>[] {
|
||||
function unescape(string: string): string {
|
||||
// unescape invisible characters.
|
||||
// ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#escape_sequences
|
||||
return string
|
||||
.replaceAll("\b", "\\b")
|
||||
.replaceAll("\f", "\\f")
|
||||
.replaceAll("\t", "\\t")
|
||||
.replaceAll("\v", "\\v")
|
||||
.replaceAll( // does not remove line breaks
|
||||
/\r\n|\r|\n/g,
|
||||
(str) => str === "\r" ? "\\r" : str === "\n" ? "\\n\n" : "\\r\\n\r\n",
|
||||
);
|
||||
}
|
||||
|
||||
function tokenize(string: string, { wordDiff = false } = {}): string[] {
|
||||
if (wordDiff) {
|
||||
// Split string on whitespace symbols
|
||||
const tokens = string.split(/([^\S\r\n]+|[()[\]{}'"\r\n]|\b)/);
|
||||
// Extended Latin character set
|
||||
const words =
|
||||
/^[a-zA-Z\u{C0}-\u{FF}\u{D8}-\u{F6}\u{F8}-\u{2C6}\u{2C8}-\u{2D7}\u{2DE}-\u{2FF}\u{1E00}-\u{1EFF}]+$/u;
|
||||
|
||||
// Join boundary splits that we do not consider to be boundaries and merge empty strings surrounded by word chars
|
||||
for (let i = 0; i < tokens.length - 1; i++) {
|
||||
const token = tokens[i];
|
||||
const tokenPlusTwo = tokens[i + 2];
|
||||
if (
|
||||
!tokens[i + 1] &&
|
||||
token &&
|
||||
tokenPlusTwo &&
|
||||
words.test(token) &&
|
||||
words.test(tokenPlusTwo)
|
||||
) {
|
||||
tokens[i] += tokenPlusTwo;
|
||||
tokens.splice(i + 1, 2);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return tokens.filter((token) => token);
|
||||
} else {
|
||||
// Split string on new lines symbols
|
||||
const tokens: string[] = [];
|
||||
const lines = string.split(/(\n|\r\n)/);
|
||||
|
||||
// Ignore final empty token when text ends with a newline
|
||||
if (!lines[lines.length - 1]) {
|
||||
lines.pop();
|
||||
}
|
||||
|
||||
// Merge the content and line separators into single tokens
|
||||
for (const [i, line] of lines.entries()) {
|
||||
if (i % 2) {
|
||||
tokens[tokens.length - 1] += line;
|
||||
} else {
|
||||
tokens.push(line);
|
||||
}
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
}
|
||||
|
||||
// Create details by filtering relevant word-diff for current line
|
||||
// and merge "space-diff" if surrounded by word-diff for cleaner displays
|
||||
function createDetails(
|
||||
line: DiffResult<string>,
|
||||
tokens: Array<DiffResult<string>>,
|
||||
) {
|
||||
return tokens.filter(({ type }) =>
|
||||
type === line.type || type === DiffType.common
|
||||
).map((result, i, t) => {
|
||||
const token = t[i - 1];
|
||||
if (
|
||||
(result.type === DiffType.common) && token &&
|
||||
(token.type === t[i + 1]?.type) && /\s+/.test(result.value)
|
||||
) {
|
||||
return {
|
||||
...result,
|
||||
type: token.type,
|
||||
};
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
// Compute multi-line diff
|
||||
const diffResult = _internals.diff(
|
||||
tokenize(`${unescape(A)}\n`),
|
||||
tokenize(`${unescape(B)}\n`),
|
||||
);
|
||||
|
||||
const added = [];
|
||||
const removed = [];
|
||||
for (const result of diffResult) {
|
||||
if (result.type === DiffType.added) {
|
||||
added.push(result);
|
||||
}
|
||||
if (result.type === DiffType.removed) {
|
||||
removed.push(result);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute word-diff
|
||||
const hasMoreRemovedLines = added.length < removed.length;
|
||||
const aLines = hasMoreRemovedLines ? added : removed;
|
||||
const bLines = hasMoreRemovedLines ? removed : added;
|
||||
for (const a of aLines) {
|
||||
let tokens = [] as Array<DiffResult<string>>;
|
||||
let b: undefined | DiffResult<string>;
|
||||
// Search another diff line with at least one common token
|
||||
while (bLines.length) {
|
||||
b = bLines.shift();
|
||||
const tokenized = [
|
||||
tokenize(a.value, { wordDiff: true }),
|
||||
tokenize(b?.value ?? "", { wordDiff: true }),
|
||||
] as [string[], string[]];
|
||||
if (hasMoreRemovedLines) tokenized.reverse();
|
||||
tokens = _internals.diff(tokenized[0], tokenized[1]);
|
||||
if (
|
||||
tokens.some(({ type, value }) =>
|
||||
type === DiffType.common && value.trim().length
|
||||
)
|
||||
) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Register word-diff details
|
||||
a.details = createDetails(a, tokens);
|
||||
if (b) {
|
||||
b.details = createDetails(b, tokens);
|
||||
}
|
||||
}
|
||||
|
||||
return diffResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Colors the output of assertion diffs
|
||||
* @param diffType Difference type, either added or removed
|
||||
*/
|
||||
function createColor(
|
||||
diffType: DiffType,
|
||||
{ background = false } = {},
|
||||
): (s: string) => string {
|
||||
// TODO(@littledivy): Remove this when we can detect
|
||||
// true color terminals.
|
||||
// https://github.com/denoland/deno_std/issues/2575
|
||||
background = false;
|
||||
switch (diffType) {
|
||||
case DiffType.added:
|
||||
return (s: string): string =>
|
||||
background ? bgGreen(white(s)) : green(bold(s));
|
||||
case DiffType.removed:
|
||||
return (s: string): string => background ? bgRed(white(s)) : red(bold(s));
|
||||
default:
|
||||
return white;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefixes `+` or `-` in diff output
|
||||
* @param diffType Difference type, either added or removed
|
||||
*/
|
||||
function createSign(diffType: DiffType): string {
|
||||
switch (diffType) {
|
||||
case DiffType.added:
|
||||
return "+ ";
|
||||
case DiffType.removed:
|
||||
return "- ";
|
||||
default:
|
||||
return " ";
|
||||
}
|
||||
}
|
||||
|
||||
export function buildMessage(
|
||||
diffResult: ReadonlyArray<DiffResult<string>>,
|
||||
{ stringDiff = false } = {},
|
||||
): string[] {
|
||||
const messages: string[] = [];
|
||||
const diffMessages: string[] = [];
|
||||
messages.push("");
|
||||
messages.push("");
|
||||
messages.push(
|
||||
` ${gray(bold("[Diff]"))} ${red(bold("Actual"))} / ${
|
||||
green(bold("Expected"))
|
||||
}`,
|
||||
);
|
||||
messages.push("");
|
||||
messages.push("");
|
||||
diffResult.forEach((result: DiffResult<string>) => {
|
||||
const c = createColor(result.type);
|
||||
const line = result.details?.map((detail) =>
|
||||
detail.type !== DiffType.common
|
||||
? createColor(detail.type, { background: true })(detail.value)
|
||||
: detail.value
|
||||
).join("") ?? result.value;
|
||||
diffMessages.push(c(`${createSign(result.type)}${line}`));
|
||||
});
|
||||
messages.push(...(stringDiff ? [diffMessages.join("")] : diffMessages));
|
||||
messages.push("");
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
export const _internals = { diff, diffstr };
|
||||
export const _internals = { diff };
|
||||
|
144
internal/diff_str.ts
Normal file
144
internal/diff_str.ts
Normal file
@ -0,0 +1,144 @@
|
||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
import type { DiffResult } from "./_types.ts";
|
||||
import { _internals } from "./diff.ts";
|
||||
|
||||
/**
|
||||
* Renders the differences between the actual and expected strings
|
||||
* Partially inspired from https://github.com/kpdecker/jsdiff
|
||||
* @param A Actual string
|
||||
* @param B Expected string
|
||||
*/
|
||||
export function diffstr(A: string, B: string): DiffResult<string>[] {
|
||||
function unescape(string: string): string {
|
||||
// unescape invisible characters.
|
||||
// ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#escape_sequences
|
||||
return string
|
||||
.replaceAll("\b", "\\b")
|
||||
.replaceAll("\f", "\\f")
|
||||
.replaceAll("\t", "\\t")
|
||||
.replaceAll("\v", "\\v")
|
||||
.replaceAll( // does not remove line breaks
|
||||
/\r\n|\r|\n/g,
|
||||
(str) => str === "\r" ? "\\r" : str === "\n" ? "\\n\n" : "\\r\\n\r\n",
|
||||
);
|
||||
}
|
||||
|
||||
function tokenize(string: string, { wordDiff = false } = {}): string[] {
|
||||
if (wordDiff) {
|
||||
// Split string on whitespace symbols
|
||||
const tokens = string.split(/([^\S\r\n]+|[()[\]{}'"\r\n]|\b)/);
|
||||
// Extended Latin character set
|
||||
const words =
|
||||
/^[a-zA-Z\u{C0}-\u{FF}\u{D8}-\u{F6}\u{F8}-\u{2C6}\u{2C8}-\u{2D7}\u{2DE}-\u{2FF}\u{1E00}-\u{1EFF}]+$/u;
|
||||
|
||||
// Join boundary splits that we do not consider to be boundaries and merge empty strings surrounded by word chars
|
||||
for (let i = 0; i < tokens.length - 1; i++) {
|
||||
const token = tokens[i];
|
||||
const tokenPlusTwo = tokens[i + 2];
|
||||
if (
|
||||
!tokens[i + 1] &&
|
||||
token &&
|
||||
tokenPlusTwo &&
|
||||
words.test(token) &&
|
||||
words.test(tokenPlusTwo)
|
||||
) {
|
||||
tokens[i] += tokenPlusTwo;
|
||||
tokens.splice(i + 1, 2);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return tokens.filter((token) => token);
|
||||
} else {
|
||||
// Split string on new lines symbols
|
||||
const tokens: string[] = [];
|
||||
const lines = string.split(/(\n|\r\n)/);
|
||||
|
||||
// Ignore final empty token when text ends with a newline
|
||||
if (!lines[lines.length - 1]) {
|
||||
lines.pop();
|
||||
}
|
||||
|
||||
// Merge the content and line separators into single tokens
|
||||
for (const [i, line] of lines.entries()) {
|
||||
if (i % 2) {
|
||||
tokens[tokens.length - 1] += line;
|
||||
} else {
|
||||
tokens.push(line);
|
||||
}
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
}
|
||||
|
||||
// Create details by filtering relevant word-diff for current line
|
||||
// and merge "space-diff" if surrounded by word-diff for cleaner displays
|
||||
function createDetails(
|
||||
line: DiffResult<string>,
|
||||
tokens: Array<DiffResult<string>>,
|
||||
) {
|
||||
return tokens.filter(({ type }) => type === line.type || type === "common")
|
||||
.map((result, i, t) => {
|
||||
const token = t[i - 1];
|
||||
if (
|
||||
(result.type === "common") && token &&
|
||||
(token.type === t[i + 1]?.type) && /\s+/.test(result.value)
|
||||
) {
|
||||
return {
|
||||
...result,
|
||||
type: token.type,
|
||||
};
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
// Compute multi-line diff
|
||||
const diffResult = _internals.diff(
|
||||
tokenize(`${unescape(A)}\n`),
|
||||
tokenize(`${unescape(B)}\n`),
|
||||
);
|
||||
|
||||
const added = [];
|
||||
const removed = [];
|
||||
for (const result of diffResult) {
|
||||
if (result.type === "added") {
|
||||
added.push(result);
|
||||
}
|
||||
if (result.type === "removed") {
|
||||
removed.push(result);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute word-diff
|
||||
const hasMoreRemovedLines = added.length < removed.length;
|
||||
const aLines = hasMoreRemovedLines ? added : removed;
|
||||
const bLines = hasMoreRemovedLines ? removed : added;
|
||||
for (const a of aLines) {
|
||||
let tokens = [] as Array<DiffResult<string>>;
|
||||
let b: undefined | DiffResult<string>;
|
||||
// Search another diff line with at least one common token
|
||||
while (bLines.length) {
|
||||
b = bLines.shift();
|
||||
const tokenized = [
|
||||
tokenize(a.value, { wordDiff: true }),
|
||||
tokenize(b?.value ?? "", { wordDiff: true }),
|
||||
] as [string[], string[]];
|
||||
if (hasMoreRemovedLines) tokenized.reverse();
|
||||
tokens = _internals.diff(tokenized[0], tokenized[1]);
|
||||
if (
|
||||
tokens.some(({ type, value }) =>
|
||||
type === "common" && value.trim().length
|
||||
)
|
||||
) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Register word-diff details
|
||||
a.details = createDetails(a, tokens);
|
||||
if (b) {
|
||||
b.details = createDetails(b, tokens);
|
||||
}
|
||||
}
|
||||
|
||||
return diffResult;
|
||||
}
|
238
internal/diff_str_test.ts
Normal file
238
internal/diff_str_test.ts
Normal file
@ -0,0 +1,238 @@
|
||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
import { diffstr } from "./diff_str.ts";
|
||||
import { assertEquals } from "@std/assert/assert-equals";
|
||||
|
||||
Deno.test({
|
||||
name: 'diff() "a b c d" vs "a b x d e" (diffstr)',
|
||||
fn() {
|
||||
const diffResult = diffstr(
|
||||
[..."abcd"].join("\n"),
|
||||
[..."abxde"].join("\n"),
|
||||
);
|
||||
assertEquals(diffResult, [
|
||||
{ type: "common", value: "a\\n\n" },
|
||||
{ type: "common", value: "b\\n\n" },
|
||||
{
|
||||
type: "added",
|
||||
value: "x\\n\n",
|
||||
details: [
|
||||
{ type: "added", value: "x" },
|
||||
{ type: "common", value: "\\" },
|
||||
{ type: "common", value: "n" },
|
||||
{ type: "common", value: "\n" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "added",
|
||||
value: "d\\n\n",
|
||||
details: [
|
||||
{ type: "common", value: "d" },
|
||||
{ type: "added", value: "\\" },
|
||||
{ type: "added", value: "n" },
|
||||
{ type: "common", value: "\n" },
|
||||
],
|
||||
},
|
||||
{ type: "added", value: "e\n" },
|
||||
{
|
||||
type: "removed",
|
||||
value: "c\\n\n",
|
||||
details: [
|
||||
{ type: "removed", value: "c" },
|
||||
{ type: "common", value: "\\" },
|
||||
{ type: "common", value: "n" },
|
||||
{ type: "common", value: "\n" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "removed",
|
||||
value: "d\n",
|
||||
details: [
|
||||
{ type: "common", value: "d" },
|
||||
{ type: "common", value: "\n" },
|
||||
],
|
||||
},
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: `diff() "3.14" vs "2.71" (diffstr)`,
|
||||
fn() {
|
||||
const diffResult = diffstr("3.14", "2.71");
|
||||
assertEquals(diffResult, [
|
||||
{
|
||||
type: "removed",
|
||||
value: "3.14\n",
|
||||
details: [
|
||||
{
|
||||
type: "removed",
|
||||
value: "3",
|
||||
},
|
||||
{
|
||||
type: "common",
|
||||
value: ".",
|
||||
},
|
||||
{
|
||||
type: "removed",
|
||||
value: "14",
|
||||
},
|
||||
{
|
||||
type: "common",
|
||||
value: "\n",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "added",
|
||||
value: "2.71\n",
|
||||
details: [
|
||||
{
|
||||
type: "added",
|
||||
value: "2",
|
||||
},
|
||||
{
|
||||
type: "common",
|
||||
value: ".",
|
||||
},
|
||||
{
|
||||
type: "added",
|
||||
value: "71",
|
||||
},
|
||||
{
|
||||
type: "common",
|
||||
value: "\n",
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: `diff() single line "a b" vs "c d" (diffstr)`,
|
||||
fn() {
|
||||
const diffResult = diffstr("a b", "c d");
|
||||
assertEquals(diffResult, [
|
||||
{
|
||||
type: "removed",
|
||||
value: "a b\n",
|
||||
details: [
|
||||
{ type: "removed", value: "a" },
|
||||
{ type: "removed", value: " " },
|
||||
{ type: "removed", value: "b" },
|
||||
{ type: "common", value: "\n" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "added",
|
||||
value: "c d\n",
|
||||
details: [
|
||||
{ type: "added", value: "c" },
|
||||
{ type: "added", value: " " },
|
||||
{ type: "added", value: "d" },
|
||||
{ type: "common", value: "\n" },
|
||||
],
|
||||
},
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: `diff() single line, different word length "a bc" vs "cd e" (diffstr)`,
|
||||
fn() {
|
||||
const diffResult = diffstr("a bc", "cd e");
|
||||
assertEquals(diffResult, [
|
||||
{
|
||||
type: "removed",
|
||||
value: "a bc\n",
|
||||
details: [
|
||||
{ type: "removed", value: "a" },
|
||||
{ type: "removed", value: " " },
|
||||
{ type: "removed", value: "bc" },
|
||||
{ type: "common", value: "\n" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "added",
|
||||
value: "cd e\n",
|
||||
details: [
|
||||
{ type: "added", value: "cd" },
|
||||
{ type: "added", value: " " },
|
||||
{ type: "added", value: "e" },
|
||||
{ type: "common", value: "\n" },
|
||||
],
|
||||
},
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: `diff() "\\b\\f\\r\\t\\v\\n" vs "\\r\\n" (diffstr)`,
|
||||
fn() {
|
||||
const diffResult = diffstr("\b\f\r\t\v\n", "\r\n");
|
||||
assertEquals(diffResult, [
|
||||
{
|
||||
type: "removed",
|
||||
value: "\\b\\f\\r\\t\\v\\n\n",
|
||||
details: [
|
||||
{ type: "common", value: "\\" },
|
||||
{ type: "removed", value: "b" },
|
||||
{ type: "removed", value: "\\" },
|
||||
{ type: "removed", value: "f" },
|
||||
{ type: "removed", value: "\\" },
|
||||
{ type: "common", value: "r" },
|
||||
{ type: "common", value: "\\" },
|
||||
{ type: "removed", value: "t" },
|
||||
{ type: "removed", value: "\\" },
|
||||
{ type: "removed", value: "v" },
|
||||
{ type: "removed", value: "\\" },
|
||||
{ type: "common", value: "n" },
|
||||
{ type: "common", value: "\n" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "added",
|
||||
value: "\\r\\n\r\n",
|
||||
details: [
|
||||
{ type: "common", value: "\\" },
|
||||
{ type: "common", value: "r" },
|
||||
{ type: "common", value: "\\" },
|
||||
{ type: "common", value: "n" },
|
||||
{ type: "added", value: "\r" },
|
||||
{ type: "common", value: "\n" },
|
||||
],
|
||||
},
|
||||
{ type: "common", value: "\n" },
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: "diff() multiline with more removed lines",
|
||||
fn() {
|
||||
const diffResult = diffstr("a\na", "e");
|
||||
assertEquals(diffResult, [
|
||||
{
|
||||
type: "removed",
|
||||
value: "a\\n\n",
|
||||
},
|
||||
{
|
||||
type: "removed",
|
||||
value: "a\n",
|
||||
details: [
|
||||
{ type: "removed", value: "a" },
|
||||
{ type: "common", value: "\n" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "added",
|
||||
value: "e\n",
|
||||
details: [
|
||||
{ type: "added", value: "e" },
|
||||
{ type: "common", value: "\n" },
|
||||
],
|
||||
},
|
||||
]);
|
||||
},
|
||||
});
|
@ -1,6 +1,6 @@
|
||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
import { diff, diffstr, DiffType } from "./diff.ts";
|
||||
import { diff } from "./diff.ts";
|
||||
import { assertEquals } from "@std/assert/assert-equals";
|
||||
|
||||
Deno.test({
|
||||
@ -14,8 +14,8 @@ Deno.test({
|
||||
name: 'diff() "a" vs "b"',
|
||||
fn() {
|
||||
assertEquals(diff(["a"], ["b"]), [
|
||||
{ type: DiffType.removed, value: "a" },
|
||||
{ type: DiffType.added, value: "b" },
|
||||
{ type: "removed", value: "a" },
|
||||
{ type: "added", value: "b" },
|
||||
]);
|
||||
},
|
||||
});
|
||||
@ -23,21 +23,21 @@ Deno.test({
|
||||
Deno.test({
|
||||
name: 'diff() "a" vs "a"',
|
||||
fn() {
|
||||
assertEquals(diff(["a"], ["a"]), [{ type: DiffType.common, value: "a" }]);
|
||||
assertEquals(diff(["a"], ["a"]), [{ type: "common", value: "a" }]);
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: 'diff() "a" vs ""',
|
||||
fn() {
|
||||
assertEquals(diff(["a"], []), [{ type: DiffType.removed, value: "a" }]);
|
||||
assertEquals(diff(["a"], []), [{ type: "removed", value: "a" }]);
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: 'diff() "" vs "a"',
|
||||
fn() {
|
||||
assertEquals(diff([], ["a"]), [{ type: DiffType.added, value: "a" }]);
|
||||
assertEquals(diff([], ["a"]), [{ type: "added", value: "a" }]);
|
||||
},
|
||||
});
|
||||
|
||||
@ -45,8 +45,8 @@ Deno.test({
|
||||
name: 'diff() "a" vs "a, b"',
|
||||
fn() {
|
||||
assertEquals(diff(["a"], ["a", "b"]), [
|
||||
{ type: DiffType.common, value: "a" },
|
||||
{ type: DiffType.added, value: "b" },
|
||||
{ type: "common", value: "a" },
|
||||
{ type: "added", value: "b" },
|
||||
]);
|
||||
},
|
||||
});
|
||||
@ -55,15 +55,15 @@ Deno.test({
|
||||
name: 'diff() "strength" vs "string"',
|
||||
fn() {
|
||||
assertEquals(diff(Array.from("strength"), Array.from("string")), [
|
||||
{ type: DiffType.common, value: "s" },
|
||||
{ type: DiffType.common, value: "t" },
|
||||
{ type: DiffType.common, value: "r" },
|
||||
{ type: DiffType.removed, value: "e" },
|
||||
{ type: DiffType.added, value: "i" },
|
||||
{ type: DiffType.common, value: "n" },
|
||||
{ type: DiffType.common, value: "g" },
|
||||
{ type: DiffType.removed, value: "t" },
|
||||
{ type: DiffType.removed, value: "h" },
|
||||
{ type: "common", value: "s" },
|
||||
{ type: "common", value: "t" },
|
||||
{ type: "common", value: "r" },
|
||||
{ type: "removed", value: "e" },
|
||||
{ type: "added", value: "i" },
|
||||
{ type: "common", value: "n" },
|
||||
{ type: "common", value: "g" },
|
||||
{ type: "removed", value: "t" },
|
||||
{ type: "removed", value: "h" },
|
||||
]);
|
||||
},
|
||||
});
|
||||
@ -72,14 +72,14 @@ Deno.test({
|
||||
name: 'diff() "strength" vs ""',
|
||||
fn() {
|
||||
assertEquals(diff(Array.from("strength"), Array.from("")), [
|
||||
{ type: DiffType.removed, value: "s" },
|
||||
{ type: DiffType.removed, value: "t" },
|
||||
{ type: DiffType.removed, value: "r" },
|
||||
{ type: DiffType.removed, value: "e" },
|
||||
{ type: DiffType.removed, value: "n" },
|
||||
{ type: DiffType.removed, value: "g" },
|
||||
{ type: DiffType.removed, value: "t" },
|
||||
{ type: DiffType.removed, value: "h" },
|
||||
{ type: "removed", value: "s" },
|
||||
{ type: "removed", value: "t" },
|
||||
{ type: "removed", value: "r" },
|
||||
{ type: "removed", value: "e" },
|
||||
{ type: "removed", value: "n" },
|
||||
{ type: "removed", value: "g" },
|
||||
{ type: "removed", value: "t" },
|
||||
{ type: "removed", value: "h" },
|
||||
]);
|
||||
},
|
||||
});
|
||||
@ -88,14 +88,14 @@ Deno.test({
|
||||
name: 'diff() "" vs "strength"',
|
||||
fn() {
|
||||
assertEquals(diff(Array.from(""), Array.from("strength")), [
|
||||
{ type: DiffType.added, value: "s" },
|
||||
{ type: DiffType.added, value: "t" },
|
||||
{ type: DiffType.added, value: "r" },
|
||||
{ type: DiffType.added, value: "e" },
|
||||
{ type: DiffType.added, value: "n" },
|
||||
{ type: DiffType.added, value: "g" },
|
||||
{ type: DiffType.added, value: "t" },
|
||||
{ type: DiffType.added, value: "h" },
|
||||
{ type: "added", value: "s" },
|
||||
{ type: "added", value: "t" },
|
||||
{ type: "added", value: "r" },
|
||||
{ type: "added", value: "e" },
|
||||
{ type: "added", value: "n" },
|
||||
{ type: "added", value: "g" },
|
||||
{ type: "added", value: "t" },
|
||||
{ type: "added", value: "h" },
|
||||
]);
|
||||
},
|
||||
});
|
||||
@ -104,243 +104,9 @@ Deno.test({
|
||||
name: 'diff() "abc", "c" vs "abc", "bcd", "c"',
|
||||
fn() {
|
||||
assertEquals(diff(["abc", "c"], ["abc", "bcd", "c"]), [
|
||||
{ type: DiffType.common, value: "abc" },
|
||||
{ type: DiffType.added, value: "bcd" },
|
||||
{ type: DiffType.common, value: "c" },
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: 'diff() "a b c d" vs "a b x d e" (diffstr)',
|
||||
fn() {
|
||||
const diffResult = diffstr(
|
||||
[..."abcd"].join("\n"),
|
||||
[..."abxde"].join("\n"),
|
||||
);
|
||||
assertEquals(diffResult, [
|
||||
{ type: DiffType.common, value: "a\\n\n" },
|
||||
{ type: DiffType.common, value: "b\\n\n" },
|
||||
{
|
||||
type: DiffType.added,
|
||||
value: "x\\n\n",
|
||||
details: [
|
||||
{ type: DiffType.added, value: "x" },
|
||||
{ type: DiffType.common, value: "\\" },
|
||||
{ type: DiffType.common, value: "n" },
|
||||
{ type: DiffType.common, value: "\n" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: DiffType.added,
|
||||
value: "d\\n\n",
|
||||
details: [
|
||||
{ type: DiffType.common, value: "d" },
|
||||
{ type: DiffType.added, value: "\\" },
|
||||
{ type: DiffType.added, value: "n" },
|
||||
{ type: DiffType.common, value: "\n" },
|
||||
],
|
||||
},
|
||||
{ type: DiffType.added, value: "e\n" },
|
||||
{
|
||||
type: DiffType.removed,
|
||||
value: "c\\n\n",
|
||||
details: [
|
||||
{ type: DiffType.removed, value: "c" },
|
||||
{ type: DiffType.common, value: "\\" },
|
||||
{ type: DiffType.common, value: "n" },
|
||||
{ type: DiffType.common, value: "\n" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: DiffType.removed,
|
||||
value: "d\n",
|
||||
details: [
|
||||
{ type: DiffType.common, value: "d" },
|
||||
{ type: DiffType.common, value: "\n" },
|
||||
],
|
||||
},
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: `diff() "3.14" vs "2.71" (diffstr)`,
|
||||
fn() {
|
||||
const diffResult = diffstr("3.14", "2.71");
|
||||
assertEquals(diffResult, [
|
||||
{
|
||||
type: DiffType.removed,
|
||||
value: "3.14\n",
|
||||
details: [
|
||||
{
|
||||
type: DiffType.removed,
|
||||
value: "3",
|
||||
},
|
||||
{
|
||||
type: DiffType.common,
|
||||
value: ".",
|
||||
},
|
||||
{
|
||||
type: DiffType.removed,
|
||||
value: "14",
|
||||
},
|
||||
{
|
||||
type: DiffType.common,
|
||||
value: "\n",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: DiffType.added,
|
||||
value: "2.71\n",
|
||||
details: [
|
||||
{
|
||||
type: DiffType.added,
|
||||
value: "2",
|
||||
},
|
||||
{
|
||||
type: DiffType.common,
|
||||
value: ".",
|
||||
},
|
||||
{
|
||||
type: DiffType.added,
|
||||
value: "71",
|
||||
},
|
||||
{
|
||||
type: DiffType.common,
|
||||
value: "\n",
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: `diff() single line "a b" vs "c d" (diffstr)`,
|
||||
fn() {
|
||||
const diffResult = diffstr("a b", "c d");
|
||||
assertEquals(diffResult, [
|
||||
{
|
||||
type: DiffType.removed,
|
||||
value: "a b\n",
|
||||
details: [
|
||||
{ type: DiffType.removed, value: "a" },
|
||||
{ type: DiffType.removed, value: " " },
|
||||
{ type: DiffType.removed, value: "b" },
|
||||
{ type: DiffType.common, value: "\n" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: DiffType.added,
|
||||
value: "c d\n",
|
||||
details: [
|
||||
{ type: DiffType.added, value: "c" },
|
||||
{ type: DiffType.added, value: " " },
|
||||
{ type: DiffType.added, value: "d" },
|
||||
{ type: DiffType.common, value: "\n" },
|
||||
],
|
||||
},
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: `diff() single line, different word length "a bc" vs "cd e" (diffstr)`,
|
||||
fn() {
|
||||
const diffResult = diffstr("a bc", "cd e");
|
||||
assertEquals(diffResult, [
|
||||
{
|
||||
type: DiffType.removed,
|
||||
value: "a bc\n",
|
||||
details: [
|
||||
{ type: DiffType.removed, value: "a" },
|
||||
{ type: DiffType.removed, value: " " },
|
||||
{ type: DiffType.removed, value: "bc" },
|
||||
{ type: DiffType.common, value: "\n" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: DiffType.added,
|
||||
value: "cd e\n",
|
||||
details: [
|
||||
{ type: DiffType.added, value: "cd" },
|
||||
{ type: DiffType.added, value: " " },
|
||||
{ type: DiffType.added, value: "e" },
|
||||
{ type: DiffType.common, value: "\n" },
|
||||
],
|
||||
},
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: `diff() "\\b\\f\\r\\t\\v\\n" vs "\\r\\n" (diffstr)`,
|
||||
fn() {
|
||||
const diffResult = diffstr("\b\f\r\t\v\n", "\r\n");
|
||||
assertEquals(diffResult, [
|
||||
{
|
||||
type: DiffType.removed,
|
||||
value: "\\b\\f\\r\\t\\v\\n\n",
|
||||
details: [
|
||||
{ type: DiffType.common, value: "\\" },
|
||||
{ type: DiffType.removed, value: "b" },
|
||||
{ type: DiffType.removed, value: "\\" },
|
||||
{ type: DiffType.removed, value: "f" },
|
||||
{ type: DiffType.removed, value: "\\" },
|
||||
{ type: DiffType.common, value: "r" },
|
||||
{ type: DiffType.common, value: "\\" },
|
||||
{ type: DiffType.removed, value: "t" },
|
||||
{ type: DiffType.removed, value: "\\" },
|
||||
{ type: DiffType.removed, value: "v" },
|
||||
{ type: DiffType.removed, value: "\\" },
|
||||
{ type: DiffType.common, value: "n" },
|
||||
{ type: DiffType.common, value: "\n" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: DiffType.added,
|
||||
value: "\\r\\n\r\n",
|
||||
details: [
|
||||
{ type: DiffType.common, value: "\\" },
|
||||
{ type: DiffType.common, value: "r" },
|
||||
{ type: DiffType.common, value: "\\" },
|
||||
{ type: DiffType.common, value: "n" },
|
||||
{ type: DiffType.added, value: "\r" },
|
||||
{ type: DiffType.common, value: "\n" },
|
||||
],
|
||||
},
|
||||
{ type: DiffType.common, value: "\n" },
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
Deno.test({
|
||||
name: "diff() multiline with more removed lines",
|
||||
fn() {
|
||||
const diffResult = diffstr("a\na", "e");
|
||||
assertEquals(diffResult, [
|
||||
{
|
||||
type: DiffType.removed,
|
||||
value: "a\\n\n",
|
||||
},
|
||||
{
|
||||
type: DiffType.removed,
|
||||
value: "a\n",
|
||||
details: [
|
||||
{ type: DiffType.removed, value: "a" },
|
||||
{ type: DiffType.common, value: "\n" },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: DiffType.added,
|
||||
value: "e\n",
|
||||
details: [
|
||||
{ type: DiffType.added, value: "e" },
|
||||
{ type: DiffType.common, value: "\n" },
|
||||
],
|
||||
},
|
||||
{ type: "common", value: "abc" },
|
||||
{ type: "added", value: "bcd" },
|
||||
{ type: "common", value: "c" },
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
@ -7,5 +7,7 @@
|
||||
*
|
||||
* @module
|
||||
*/
|
||||
export * from "./format.ts";
|
||||
export * from "./build_message.ts";
|
||||
export * from "./diff.ts";
|
||||
export * from "./diff_str.ts";
|
||||
export * from "./format.ts";
|
||||
|
Loading…
Reference in New Issue
Block a user