hereby 1.13.0 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/formatTasks.js +29 -7
- package/dist/cli/index.js +15 -22
- package/dist/cli/loadHerebyfile.js +19 -25
- package/dist/cli/parseArgs.js +44 -25
- package/dist/cli/runner.js +4 -4
- package/dist/cli/style.js +25 -0
- package/dist/cli/utils.js +32 -15
- package/package.json +13 -60
package/dist/cli/formatTasks.js
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
import
|
|
2
|
-
import Wordwrap from "wordwrapjs";
|
|
1
|
+
import * as style from "./style.js";
|
|
3
2
|
import { compareTaskNames } from "./utils.js";
|
|
4
3
|
export function formatTasks(format, tasks, defaultTask, columns) {
|
|
5
4
|
const visibleTasks = [...tasks].filter(isTaskVisible).sort(compareTaskNames);
|
|
6
5
|
if (format === "simple") {
|
|
7
6
|
return visibleTasks.map((task) => task.options.name).join("\n");
|
|
8
7
|
}
|
|
9
|
-
const names = visibleTasks.map((task) => task === defaultTask ? `${
|
|
8
|
+
const names = visibleTasks.map((task) => task === defaultTask ? `${style.green(task.options.name)} (default)` : style.blue(task.options.name));
|
|
10
9
|
const descriptions = visibleTasks.map((task) => {
|
|
11
10
|
var _a, _b;
|
|
12
11
|
let parts = task.options.description ? [task.options.description] : undefined;
|
|
13
12
|
const deps = (_a = task.options.dependencies) === null || _a === void 0 ? void 0 : _a.filter(isTaskVisible).sort(compareTaskNames);
|
|
14
13
|
if (deps === null || deps === void 0 ? void 0 : deps.length) {
|
|
15
|
-
const depNames = deps.map((task) =>
|
|
14
|
+
const depNames = deps.map((task) => style.blue(task.options.name));
|
|
16
15
|
(parts !== null && parts !== void 0 ? parts : (parts = [])).push(`Depends on: ${depNames.join(", ")}`);
|
|
17
16
|
}
|
|
18
17
|
return (_b = parts === null || parts === void 0 ? void 0 : parts.join("\n")) !== null && _b !== void 0 ? _b : "";
|
|
@@ -26,7 +25,7 @@ export function formatTasks(format, tasks, defaultTask, columns) {
|
|
|
26
25
|
const descriptionWidth = maxTotalWidth - nameWidth;
|
|
27
26
|
const formatted = names.map((name, i) => formatAsColumns(" ", name, nameWidth, descriptions[i], descriptionWidth));
|
|
28
27
|
return `
|
|
29
|
-
${
|
|
28
|
+
${style.bold(style.underline("Available tasks"))}
|
|
30
29
|
|
|
31
30
|
${formatted.join("")}`;
|
|
32
31
|
}
|
|
@@ -41,7 +40,7 @@ function formatAsColumns(indent, leftText, leftWidth, rightText, rightWidth) {
|
|
|
41
40
|
for (let i = 0; i < maxLines; i++) {
|
|
42
41
|
const leftPart = leftLines[i] || "";
|
|
43
42
|
const rightPart = rightLines[i] || "";
|
|
44
|
-
const paddedLeft = leftPart.
|
|
43
|
+
const paddedLeft = leftPart + " ".repeat(Math.max(0, leftWidth - visibleLength(leftPart)));
|
|
45
44
|
result += `${indent}${paddedLeft} ${rightPart}\n`;
|
|
46
45
|
}
|
|
47
46
|
return result;
|
|
@@ -51,7 +50,30 @@ const ANSI_REGEX = /\u001B\[([0-9]{1,2})m/g;
|
|
|
51
50
|
function visibleLength(str) {
|
|
52
51
|
return str.replace(ANSI_REGEX, "").length;
|
|
53
52
|
}
|
|
53
|
+
const TOKEN_REGEX = /[^\s-]+?-\b|\S+|\s+/g;
|
|
54
54
|
function wrapText(text, maxWidth) {
|
|
55
|
-
|
|
55
|
+
var _a;
|
|
56
|
+
const result = [];
|
|
57
|
+
for (const line of text.split(/\r?\n/)) {
|
|
58
|
+
let current = "";
|
|
59
|
+
for (const token of (_a = line.match(TOKEN_REGEX)) !== null && _a !== void 0 ? _a : []) {
|
|
60
|
+
if (visibleLength(current) + visibleLength(token) > maxWidth && current.trim()) {
|
|
61
|
+
result.push(current.trim());
|
|
62
|
+
current = "";
|
|
63
|
+
}
|
|
64
|
+
if (visibleLength(token) > maxWidth) {
|
|
65
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-spread
|
|
66
|
+
const chars = [...token];
|
|
67
|
+
while (chars.length > 0)
|
|
68
|
+
result.push(chars.splice(0, maxWidth).join(""));
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
current += /^\s/.test(token) && !current ? "" : token;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (current.trim())
|
|
75
|
+
result.push(current.trim());
|
|
76
|
+
}
|
|
77
|
+
return result.length > 0 ? result : [""];
|
|
56
78
|
}
|
|
57
79
|
//# sourceMappingURL=formatTasks.js.map
|
package/dist/cli/index.js
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import { performance } from "node:perf_hooks";
|
|
3
3
|
import { types } from "node:util";
|
|
4
|
-
import pc from "picocolors";
|
|
5
|
-
import { formatTasks } from "./formatTasks.js";
|
|
6
4
|
import { findHerebyfile, loadHerebyfile } from "./loadHerebyfile.js";
|
|
7
5
|
import { getUsage, parseArgs } from "./parseArgs.js";
|
|
8
6
|
import { reexec } from "./reexec.js";
|
|
9
7
|
import { Runner } from "./runner.js";
|
|
10
|
-
import
|
|
8
|
+
import * as style from "./style.js";
|
|
9
|
+
import { findSimilar, prettyMilliseconds, UserError } from "./utils.js";
|
|
11
10
|
export async function main(d) {
|
|
12
11
|
try {
|
|
13
12
|
await mainWorker(d);
|
|
14
13
|
}
|
|
15
14
|
catch (e) {
|
|
16
15
|
if (e instanceof UserError) {
|
|
17
|
-
d.error(`${
|
|
16
|
+
d.error(`${style.red("Error")}: ${e.message}`);
|
|
18
17
|
}
|
|
19
18
|
else if (types.isNativeError(e) && e.stack) { // eslint-disable-line @typescript-eslint/no-deprecated
|
|
20
19
|
d.error(e.stack);
|
|
@@ -42,12 +41,13 @@ async function mainWorker(d) {
|
|
|
42
41
|
d.chdir(path.dirname(herebyfilePath));
|
|
43
42
|
const herebyfile = await loadHerebyfile(herebyfilePath);
|
|
44
43
|
if (args.printTasks) {
|
|
44
|
+
const { formatTasks } = await import("./formatTasks.js");
|
|
45
45
|
d.log(formatTasks(args.printTasks, herebyfile.tasks.values(), herebyfile.defaultTask, d.columns()));
|
|
46
46
|
return;
|
|
47
47
|
}
|
|
48
48
|
const tasks = await selectTasks(d, herebyfile, herebyfilePath, args.run);
|
|
49
|
-
const taskNames = tasks.map((task) =>
|
|
50
|
-
d.log(`Using ${
|
|
49
|
+
const taskNames = tasks.map((task) => style.blue(task.options.name)).join(", ");
|
|
50
|
+
d.log(`Using ${style.yellow(d.simplifyPath(herebyfilePath))} to run ${taskNames}`);
|
|
51
51
|
const start = performance.now();
|
|
52
52
|
const runner = new Runner(d);
|
|
53
53
|
try {
|
|
@@ -62,9 +62,9 @@ async function mainWorker(d) {
|
|
|
62
62
|
finally {
|
|
63
63
|
const took = performance.now() - start;
|
|
64
64
|
const failed = runner.failedTasks.length > 0;
|
|
65
|
-
d.log(`Completed ${taskNames}${failed ?
|
|
65
|
+
d.log(`Completed ${taskNames}${failed ? style.red(" with errors") : ""} in ${prettyMilliseconds(took)}`);
|
|
66
66
|
if (failed) {
|
|
67
|
-
const names = runner.failedTasks.sort().map((task) =>
|
|
67
|
+
const names = runner.failedTasks.sort().map((task) => style.red(task)).join(", ");
|
|
68
68
|
d.log(`Failed tasks: ${names}`);
|
|
69
69
|
}
|
|
70
70
|
}
|
|
@@ -76,20 +76,13 @@ export async function selectTasks(d, herebyfile, herebyfilePath, taskNames) {
|
|
|
76
76
|
return [herebyfile.defaultTask];
|
|
77
77
|
throw new UserError(`No default task has been exported from ${d.simplifyPath(herebyfilePath)}; please specify a task name.`);
|
|
78
78
|
}
|
|
79
|
-
|
|
80
|
-
for (const name of taskNames) {
|
|
79
|
+
return taskNames.map((name) => {
|
|
81
80
|
const task = herebyfile.tasks.get(name);
|
|
82
|
-
if (
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
throw new UserError(message);
|
|
90
|
-
}
|
|
91
|
-
tasks.push(task);
|
|
92
|
-
}
|
|
93
|
-
return tasks;
|
|
81
|
+
if (task)
|
|
82
|
+
return task;
|
|
83
|
+
const suggestion = findSimilar(name, herebyfile.tasks.keys());
|
|
84
|
+
throw new UserError(`Task "${name}" does not exist or is not exported from ${d.simplifyPath(herebyfilePath)}.`
|
|
85
|
+
+ (suggestion ? ` Did you mean "${suggestion}"?` : ""));
|
|
86
|
+
});
|
|
94
87
|
}
|
|
95
88
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { pathToFileURL } from "node:url";
|
|
4
|
-
import pc from "picocolors";
|
|
5
4
|
import { Task } from "../index.js";
|
|
5
|
+
import * as style from "./style.js";
|
|
6
6
|
import { findUp, UserError } from "./utils.js";
|
|
7
7
|
const herebyfileRegExp = /^herebyfile\.m?[jt]s$/i;
|
|
8
8
|
export function findHerebyfile(dir) {
|
|
@@ -42,7 +42,7 @@ export async function loadHerebyfile(herebyfilePath) {
|
|
|
42
42
|
defaultTask = value;
|
|
43
43
|
}
|
|
44
44
|
else if (exportedTasks.has(value)) {
|
|
45
|
-
throw new UserError(`Task "${
|
|
45
|
+
throw new UserError(`Task "${style.blue(value.options.name)}" has been exported twice.`);
|
|
46
46
|
}
|
|
47
47
|
else {
|
|
48
48
|
exportedTasks.add(value);
|
|
@@ -60,30 +60,24 @@ export async function loadHerebyfile(herebyfilePath) {
|
|
|
60
60
|
const tasks = new Map([...exportedTasks].map((task) => [task.options.name, task]));
|
|
61
61
|
return { tasks, defaultTask };
|
|
62
62
|
}
|
|
63
|
-
function checkTaskInvariants(tasks) {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
seenNames.add(name);
|
|
80
|
-
if (task.options.dependencies) {
|
|
81
|
-
taskStack.add(task);
|
|
82
|
-
checkTaskInvariantsWorker(task.options.dependencies);
|
|
83
|
-
taskStack.delete(task);
|
|
84
|
-
}
|
|
85
|
-
checkedTasks.add(task);
|
|
63
|
+
function checkTaskInvariants(tasks, checkedTasks = new Set(), taskStack = new Set(), seenNames = new Set()) {
|
|
64
|
+
for (const task of tasks) {
|
|
65
|
+
if (checkedTasks.has(task))
|
|
66
|
+
continue;
|
|
67
|
+
if (taskStack.has(task)) {
|
|
68
|
+
throw new UserError(`Task "${style.blue(task.options.name)}" references itself.`);
|
|
69
|
+
}
|
|
70
|
+
const name = task.options.name;
|
|
71
|
+
if (seenNames.has(name)) {
|
|
72
|
+
throw new UserError(`Task "${style.blue(name)}" was declared twice.`);
|
|
73
|
+
}
|
|
74
|
+
seenNames.add(name);
|
|
75
|
+
if (task.options.dependencies) {
|
|
76
|
+
taskStack.add(task);
|
|
77
|
+
checkTaskInvariants(task.options.dependencies, checkedTasks, taskStack, seenNames);
|
|
78
|
+
taskStack.delete(task);
|
|
86
79
|
}
|
|
80
|
+
checkedTasks.add(task);
|
|
87
81
|
}
|
|
88
82
|
}
|
|
89
83
|
//# sourceMappingURL=loadHerebyfile.js.map
|
package/dist/cli/parseArgs.js
CHANGED
|
@@ -1,27 +1,46 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import * as style from "./style.js";
|
|
2
|
+
import { UserError } from "./utils.js";
|
|
3
3
|
export function parseArgs(argv) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
4
|
+
const run = [];
|
|
5
|
+
let help = false, version = false, collect = true, tasks = false, tasksSimple = false;
|
|
6
|
+
let herebyfile;
|
|
7
|
+
for (let i = 0; i < argv.length; i++) {
|
|
8
|
+
const arg = argv[i];
|
|
9
|
+
if (arg === "--")
|
|
10
|
+
break;
|
|
11
|
+
if (!arg.startsWith("-") || arg === "-") {
|
|
12
|
+
if (collect)
|
|
13
|
+
run.push(arg);
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
const eq = arg.indexOf("=");
|
|
17
|
+
const name = (eq === -1 ? arg : arg.slice(0, eq)).replace(/^--?/, "");
|
|
18
|
+
const peek = eq !== -1 ? arg.slice(eq + 1) : argv[i + 1];
|
|
19
|
+
const consume = (pred) => eq !== -1 || (pred(peek) && ++i) ? peek : undefined;
|
|
20
|
+
const bool = () => consume((s) => s === "true" || s === "false") !== "false";
|
|
21
|
+
const str = () => {
|
|
22
|
+
const v = consume((s) => s !== undefined && !s.startsWith("-"));
|
|
23
|
+
if (!v)
|
|
24
|
+
throw new UserError(`Option --${name} requires a value.`);
|
|
25
|
+
return v;
|
|
26
|
+
};
|
|
27
|
+
if (name === "h" || name === "help")
|
|
28
|
+
help = bool();
|
|
29
|
+
else if (name === "T" || name === "tasks")
|
|
30
|
+
tasks = bool();
|
|
31
|
+
else if (name === "tasks-simple")
|
|
32
|
+
tasksSimple = bool();
|
|
33
|
+
else if (name === "version")
|
|
34
|
+
version = bool();
|
|
35
|
+
else if (name === "herebyfile")
|
|
36
|
+
herebyfile = str();
|
|
37
|
+
else
|
|
38
|
+
collect = false;
|
|
39
|
+
}
|
|
40
|
+
return { help, run, herebyfile, printTasks: tasks ? "normal" : tasksSimple ? "simple" : undefined, version };
|
|
22
41
|
}
|
|
23
42
|
export function getUsage() {
|
|
24
|
-
const header = (text) =>
|
|
43
|
+
const header = (text) => style.bold(style.underline(text));
|
|
25
44
|
return `
|
|
26
45
|
${header("hereby")}
|
|
27
46
|
|
|
@@ -33,10 +52,10 @@ ${header("Synopsis")}
|
|
|
33
52
|
|
|
34
53
|
${header("Options")}
|
|
35
54
|
|
|
36
|
-
${
|
|
37
|
-
${
|
|
38
|
-
${
|
|
39
|
-
${
|
|
55
|
+
${style.bold("-h, --help")} Display this usage guide.
|
|
56
|
+
${style.bold("--herebyfile")} ${style.underline("path")} A path to a Herebyfile. Optional.
|
|
57
|
+
${style.bold("-T, --tasks")} Print a listing of the available tasks.
|
|
58
|
+
${style.bold("--version")} Print the current hereby version.
|
|
40
59
|
|
|
41
60
|
${header("Example usage")}
|
|
42
61
|
|
package/dist/cli/runner.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { performance } from "node:perf_hooks";
|
|
2
|
-
import
|
|
2
|
+
import * as style from "./style.js";
|
|
3
3
|
import { prettyMilliseconds } from "./utils.js";
|
|
4
4
|
export class Runner {
|
|
5
5
|
constructor(_d) {
|
|
@@ -35,19 +35,19 @@ export class Runner {
|
|
|
35
35
|
const start = performance.now();
|
|
36
36
|
try {
|
|
37
37
|
if (this.failedTasks.length === 0) {
|
|
38
|
-
this._d.log(`Starting ${
|
|
38
|
+
this._d.log(`Starting ${style.blue(task.options.name)}`);
|
|
39
39
|
}
|
|
40
40
|
await run();
|
|
41
41
|
if (this.failedTasks.length === 0) {
|
|
42
42
|
const took = performance.now() - start;
|
|
43
|
-
this._d.log(`Finished ${
|
|
43
|
+
this._d.log(`Finished ${style.green(task.options.name)} in ${prettyMilliseconds(took)}`);
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
catch (e) {
|
|
47
47
|
this.failedTasks.push(task.options.name);
|
|
48
48
|
if (this.failedTasks.length === 1) {
|
|
49
49
|
const took = performance.now() - start;
|
|
50
|
-
this._d.error(`Error in ${
|
|
50
|
+
this._d.error(`Error in ${style.red(task.options.name)} in ${prettyMilliseconds(took)}\n${e}`);
|
|
51
51
|
}
|
|
52
52
|
throw e;
|
|
53
53
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/* eslint-disable no-restricted-globals, @typescript-eslint/prefer-nullish-coalescing */
|
|
2
|
+
// NO_COLOR (https://no-color.org) takes precedence over everything when set
|
|
3
|
+
// to any non-empty value. FORCE_COLOR=0/false explicitly disables; any other
|
|
4
|
+
// truthy value forces colors on. Otherwise we enable colors for TTY stdout
|
|
5
|
+
// (excluding TERM=dumb) or when running in CI.
|
|
6
|
+
export function isColorEnabled(env, isTTY, platform) {
|
|
7
|
+
if (env["NO_COLOR"])
|
|
8
|
+
return false;
|
|
9
|
+
const forceColor = env["FORCE_COLOR"];
|
|
10
|
+
if (forceColor === "0" || forceColor === "false")
|
|
11
|
+
return false;
|
|
12
|
+
return !!(forceColor || platform === "win32" || (isTTY && env["TERM"] !== "dumb") || env["CI"]);
|
|
13
|
+
}
|
|
14
|
+
export const enabled = isColorEnabled(process.env, process.stdout.isTTY, process.platform);
|
|
15
|
+
/* eslint-enable no-restricted-globals, @typescript-eslint/prefer-nullish-coalescing */
|
|
16
|
+
export function wrap(enabled, open, close) {
|
|
17
|
+
return enabled ? (s) => open + s + close : (s) => s;
|
|
18
|
+
}
|
|
19
|
+
export const red = wrap(enabled, "\u001B[31m", "\u001B[39m");
|
|
20
|
+
export const green = wrap(enabled, "\u001B[32m", "\u001B[39m");
|
|
21
|
+
export const yellow = wrap(enabled, "\u001B[33m", "\u001B[39m");
|
|
22
|
+
export const blue = wrap(enabled, "\u001B[34m", "\u001B[39m");
|
|
23
|
+
export const bold = wrap(enabled, "\u001B[1m", "\u001B[22m");
|
|
24
|
+
export const underline = wrap(enabled, "\u001B[4m", "\u001B[24m");
|
|
25
|
+
//# sourceMappingURL=style.js.map
|
package/dist/cli/utils.js
CHANGED
|
@@ -8,13 +8,9 @@ export function compareTaskNames(a, b) {
|
|
|
8
8
|
const compareStrings = new Intl.Collator(undefined, { numeric: true }).compare;
|
|
9
9
|
// Exported for testing.
|
|
10
10
|
export function simplifyPath(p) {
|
|
11
|
-
|
|
11
|
+
const normalized = path.normalize(p);
|
|
12
12
|
const homedir = path.normalize(os.homedir() + path.sep);
|
|
13
|
-
|
|
14
|
-
p = p.slice(homedir.length);
|
|
15
|
-
return `~${path.sep}${p}`;
|
|
16
|
-
}
|
|
17
|
-
return p;
|
|
13
|
+
return normalized.startsWith(homedir) ? `~${path.sep}${normalized.slice(homedir.length)}` : normalized;
|
|
18
14
|
}
|
|
19
15
|
export function findUp(dir, predicate) {
|
|
20
16
|
const root = path.parse(dir).root;
|
|
@@ -36,15 +32,11 @@ export function prettyMilliseconds(ms) {
|
|
|
36
32
|
const hours = Math.floor(ms / 3600000);
|
|
37
33
|
// Round to one decimal, with an epsilon to avoid floating point errors (e.g. 5.0000001 -> 5).
|
|
38
34
|
const roundedSeconds = Math.floor(seconds * 10 + 1e-7) / 10;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (roundedSeconds > 0) {
|
|
45
|
-
parts.push(roundedSeconds % 1 === 0 ? `${roundedSeconds}s` : `${roundedSeconds.toFixed(1)}s`);
|
|
46
|
-
}
|
|
47
|
-
return parts.join(" ");
|
|
35
|
+
return [
|
|
36
|
+
hours > 0 && `${hours}h`,
|
|
37
|
+
minutes > 0 && `${minutes}m`,
|
|
38
|
+
roundedSeconds > 0 && (roundedSeconds % 1 === 0 ? `${roundedSeconds}s` : `${roundedSeconds.toFixed(1)}s`),
|
|
39
|
+
].filter(Boolean).join(" ");
|
|
48
40
|
}
|
|
49
41
|
/**
|
|
50
42
|
* UserError is a special error that, when caught in the CLI will be printed
|
|
@@ -52,6 +44,31 @@ export function prettyMilliseconds(ms) {
|
|
|
52
44
|
*/
|
|
53
45
|
export class UserError extends Error {
|
|
54
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Returns the candidate most similar to `target`, if any is close enough
|
|
49
|
+
* to be a plausible typo correction.
|
|
50
|
+
*/
|
|
51
|
+
export function findSimilar(target, candidates) {
|
|
52
|
+
let best;
|
|
53
|
+
let bestDistance = Math.ceil(target.length * 0.4);
|
|
54
|
+
for (const candidate of candidates) {
|
|
55
|
+
const row = Array.from({ length: candidate.length + 1 }, (_, j) => j);
|
|
56
|
+
for (let i = 1; i <= target.length; i++) {
|
|
57
|
+
let diag = row[0];
|
|
58
|
+
row[0] = i;
|
|
59
|
+
for (let j = 1; j <= candidate.length; j++) {
|
|
60
|
+
const tmp = row[j];
|
|
61
|
+
row[j] = Math.min(row[j - 1] + 1, tmp + 1, diag + (target[i - 1] === candidate[j - 1] ? 0 : 1));
|
|
62
|
+
diag = tmp;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (row[candidate.length] < bestDistance) {
|
|
66
|
+
best = candidate;
|
|
67
|
+
bestDistance = row[candidate.length];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return best;
|
|
71
|
+
}
|
|
55
72
|
export function real() {
|
|
56
73
|
/* eslint-disable no-restricted-globals */
|
|
57
74
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hereby",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.0",
|
|
4
4
|
"description": "A simple task runner",
|
|
5
5
|
"repository": "github:jakebailey/hereby",
|
|
6
6
|
"type": "module",
|
|
@@ -38,73 +38,26 @@
|
|
|
38
38
|
"!**/__tests__/**",
|
|
39
39
|
"./dist/index.d.ts"
|
|
40
40
|
],
|
|
41
|
-
"dependencies": {
|
|
42
|
-
"fastest-levenshtein": "^1.0.16",
|
|
43
|
-
"minimist": "^1.2.8",
|
|
44
|
-
"picocolors": "^1.1.0",
|
|
45
|
-
"wordwrapjs": "^5.1.1"
|
|
46
|
-
},
|
|
47
41
|
"devDependencies": {
|
|
48
|
-
"@
|
|
49
|
-
"@changesets/cli": "^2.30.0",
|
|
42
|
+
"@changesets/cli": "^2.31.0",
|
|
50
43
|
"@eslint/js": "^10.0.1",
|
|
51
|
-
"@
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"eslint": "^10.0.2",
|
|
60
|
-
"eslint-plugin-ava": "^16.0.0",
|
|
61
|
-
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
62
|
-
"eslint-plugin-unicorn": "^63.0.0",
|
|
63
|
-
"execa": "^6.1.0",
|
|
64
|
-
"globals": "^17.4.0",
|
|
65
|
-
"monocart-coverage-reports": "^2.12.9",
|
|
66
|
-
"moq.ts": "^10.1.0",
|
|
67
|
-
"rimraf": "^5.0.10",
|
|
68
|
-
"tmp": "0.2.1",
|
|
69
|
-
"typescript": "^5.9.3",
|
|
70
|
-
"typescript-eslint": "^8.56.1"
|
|
71
|
-
},
|
|
72
|
-
"overrides": {
|
|
73
|
-
"ava": {
|
|
74
|
-
"emittery": "1.0.0"
|
|
75
|
-
}
|
|
44
|
+
"@types/node": "^25.6.0",
|
|
45
|
+
"dprint": "^0.54.0",
|
|
46
|
+
"eslint": "^10.2.1",
|
|
47
|
+
"eslint-plugin-simple-import-sort": "^13.0.0",
|
|
48
|
+
"globals": "^17.5.0",
|
|
49
|
+
"monocart-coverage-reports": "^2.12.11",
|
|
50
|
+
"typescript": "^6.0.3",
|
|
51
|
+
"typescript-eslint": "^8.59.0"
|
|
76
52
|
},
|
|
77
53
|
"packageManager": "npm@8.19.4",
|
|
78
54
|
"scripts": {
|
|
79
55
|
"ci": "npm ci",
|
|
80
56
|
"build": "tsc",
|
|
81
57
|
"watch": "tsc --watch",
|
|
82
|
-
"test": "
|
|
83
|
-
"coverage": "
|
|
84
|
-
"prepack": "
|
|
58
|
+
"test": "node dist/__tests__/runTests.js",
|
|
59
|
+
"coverage": "mcr node dist/__tests__/runTests.js",
|
|
60
|
+
"prepack": "node -e \"fs.rmSync('dist', { recursive: true, force: true })\" && npm run build",
|
|
85
61
|
"version": "changeset version && npm install"
|
|
86
|
-
},
|
|
87
|
-
"ava": {
|
|
88
|
-
"files": [
|
|
89
|
-
"**/*.test.ts"
|
|
90
|
-
],
|
|
91
|
-
"typescript": {
|
|
92
|
-
"rewritePaths": {
|
|
93
|
-
"src/": "dist/"
|
|
94
|
-
},
|
|
95
|
-
"compile": false
|
|
96
|
-
},
|
|
97
|
-
"environmentVariables": {
|
|
98
|
-
"NO_COLOR": "1"
|
|
99
|
-
}
|
|
100
|
-
},
|
|
101
|
-
"c8": {
|
|
102
|
-
"all": true,
|
|
103
|
-
"include": "dist",
|
|
104
|
-
"reporter": [
|
|
105
|
-
"text",
|
|
106
|
-
"html",
|
|
107
|
-
"lcov"
|
|
108
|
-
]
|
|
109
62
|
}
|
|
110
63
|
}
|