@zgeoff/format-codemod 0.1.1 → 0.2.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.js +74 -80
- package/package.json +3 -3
package/dist/cli.js
CHANGED
|
@@ -546,8 +546,8 @@ import fs4 from "node:fs";
|
|
|
546
546
|
|
|
547
547
|
// src/cli/build-unified-diff.ts
|
|
548
548
|
function buildUnifiedDiff(before, after, label) {
|
|
549
|
-
const
|
|
550
|
-
const hunks = buildHunks(
|
|
549
|
+
const operations = buildDiffOps({ before: splitLines(before), after: splitLines(after) });
|
|
550
|
+
const hunks = buildHunks(operations);
|
|
551
551
|
if (hunks.length === 0) {
|
|
552
552
|
return "";
|
|
553
553
|
}
|
|
@@ -563,88 +563,82 @@ function splitLines(s) {
|
|
|
563
563
|
}
|
|
564
564
|
return lines;
|
|
565
565
|
}
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
trace = [];
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
buildOps() {
|
|
577
|
-
this.updateTrace();
|
|
578
|
-
return this.backtrack();
|
|
579
|
-
}
|
|
580
|
-
updateTrace() {
|
|
581
|
-
for (let d = 0;d <= this.a.length + this.b.length; d++) {
|
|
582
|
-
this.trace.push(new Map(this.v));
|
|
583
|
-
if (this.stepRound(d)) {
|
|
584
|
-
return;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
stepRound(d) {
|
|
589
|
-
for (let k = -d;k <= d; k += 2) {
|
|
590
|
-
const x = this.slideDiagonal(this.pickX(k, d), k);
|
|
591
|
-
this.v.set(k, x);
|
|
592
|
-
if (x >= this.a.length && x - k >= this.b.length) {
|
|
593
|
-
return true;
|
|
594
|
-
}
|
|
566
|
+
function buildDiffOps(lines) {
|
|
567
|
+
return backtrack(lines, buildTrace(lines));
|
|
568
|
+
}
|
|
569
|
+
function buildTrace(lines) {
|
|
570
|
+
const furthestX = new Map([[1, 0]]);
|
|
571
|
+
const trace = [];
|
|
572
|
+
for (let depth = 0;depth <= lines.before.length + lines.after.length; depth++) {
|
|
573
|
+
trace.push(new Map(furthestX));
|
|
574
|
+
if (stepRound(lines, furthestX, depth)) {
|
|
575
|
+
break;
|
|
595
576
|
}
|
|
596
|
-
return false;
|
|
597
577
|
}
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
}
|
|
607
|
-
return nx;
|
|
608
|
-
}
|
|
609
|
-
backtrack() {
|
|
610
|
-
const ops = [];
|
|
611
|
-
let pos = { x: this.a.length, y: this.b.length };
|
|
612
|
-
for (let d = this.trace.length - 1;d >= 0; d--) {
|
|
613
|
-
const round = this.unwindRound(pos, d);
|
|
614
|
-
ops.push(...round.ops);
|
|
615
|
-
pos = round.pos;
|
|
616
|
-
}
|
|
617
|
-
return ops.toReversed();
|
|
618
|
-
}
|
|
619
|
-
unwindRound(pos, d) {
|
|
620
|
-
const previous = this.findPrevious(pos, d);
|
|
621
|
-
const prev = previous.prev;
|
|
622
|
-
const ops = this.buildEqualOps(pos, prev);
|
|
623
|
-
if (d > 0) {
|
|
624
|
-
const changeOp = previous.moveDown ? { kind: "+", text: this.b[prev.y] ?? "" } : { kind: "-", text: this.a[prev.x] ?? "" };
|
|
625
|
-
ops.push(changeOp);
|
|
626
|
-
}
|
|
627
|
-
return { ops, pos: prev };
|
|
628
|
-
}
|
|
629
|
-
findPrevious(pos, d) {
|
|
630
|
-
const v = this.trace[d] ?? new Map;
|
|
631
|
-
const k = pos.x - pos.y;
|
|
632
|
-
const moveDown = k === -d || k !== d && (v.get(k - 1) ?? 0) < (v.get(k + 1) ?? 0);
|
|
633
|
-
const prevK = moveDown ? k + 1 : k - 1;
|
|
634
|
-
const prevX = v.get(prevK) ?? 0;
|
|
635
|
-
return { prev: { x: prevX, y: prevX - prevK }, moveDown };
|
|
636
|
-
}
|
|
637
|
-
buildEqualOps(pos, prev) {
|
|
638
|
-
const ops = [];
|
|
639
|
-
let x = pos.x;
|
|
640
|
-
let y = pos.y;
|
|
641
|
-
while (x > prev.x && y > prev.y) {
|
|
642
|
-
ops.push({ kind: " ", text: this.a[x - 1] ?? "" });
|
|
643
|
-
x--;
|
|
644
|
-
y--;
|
|
578
|
+
return trace;
|
|
579
|
+
}
|
|
580
|
+
function stepRound(lines, furthestX, depth) {
|
|
581
|
+
for (let diagonal = -depth;diagonal <= depth; diagonal += 2) {
|
|
582
|
+
const x = slideDiagonal(lines, pickX(furthestX, diagonal, depth), diagonal);
|
|
583
|
+
furthestX.set(diagonal, x);
|
|
584
|
+
if (x >= lines.before.length && x - diagonal >= lines.after.length) {
|
|
585
|
+
return true;
|
|
645
586
|
}
|
|
646
|
-
return ops;
|
|
647
587
|
}
|
|
588
|
+
return false;
|
|
589
|
+
}
|
|
590
|
+
function pickX(furthestX, diagonal, depth) {
|
|
591
|
+
const below = furthestX.get(diagonal - 1) ?? 0;
|
|
592
|
+
const above = furthestX.get(diagonal + 1) ?? 0;
|
|
593
|
+
const moveDown = diagonal === -depth || diagonal !== depth && below < above;
|
|
594
|
+
return moveDown ? above : below + 1;
|
|
595
|
+
}
|
|
596
|
+
function slideDiagonal(lines, x, diagonal) {
|
|
597
|
+
let endX = x;
|
|
598
|
+
while (endX < lines.before.length && endX - diagonal < lines.after.length && lines.before[endX] === lines.after[endX - diagonal]) {
|
|
599
|
+
endX++;
|
|
600
|
+
}
|
|
601
|
+
return endX;
|
|
602
|
+
}
|
|
603
|
+
function backtrack(lines, trace) {
|
|
604
|
+
const operations = [];
|
|
605
|
+
let position = { x: lines.before.length, y: lines.after.length };
|
|
606
|
+
for (let depth = trace.length - 1;depth >= 0; depth--) {
|
|
607
|
+
const round = unwindRound(lines, trace, position, depth);
|
|
608
|
+
operations.push(...round.operations);
|
|
609
|
+
position = round.position;
|
|
610
|
+
}
|
|
611
|
+
return operations.toReversed();
|
|
612
|
+
}
|
|
613
|
+
function unwindRound(lines, trace, position, depth) {
|
|
614
|
+
const step = findPreviousStep(trace, position, depth);
|
|
615
|
+
const operations = buildEqualOps(lines, position, step.position);
|
|
616
|
+
if (depth > 0) {
|
|
617
|
+
const changeOp = step.moveDown ? { kind: "+", text: lines.after[step.position.y] ?? "" } : { kind: "-", text: lines.before[step.position.x] ?? "" };
|
|
618
|
+
operations.push(changeOp);
|
|
619
|
+
}
|
|
620
|
+
return { operations, position: step.position };
|
|
621
|
+
}
|
|
622
|
+
function findPreviousStep(trace, position, depth) {
|
|
623
|
+
const furthestX = trace[depth] ?? new Map;
|
|
624
|
+
const diagonal = position.x - position.y;
|
|
625
|
+
const below = furthestX.get(diagonal - 1) ?? 0;
|
|
626
|
+
const above = furthestX.get(diagonal + 1) ?? 0;
|
|
627
|
+
const moveDown = diagonal === -depth || diagonal !== depth && below < above;
|
|
628
|
+
const previousDiagonal = moveDown ? diagonal + 1 : diagonal - 1;
|
|
629
|
+
const previousX = furthestX.get(previousDiagonal) ?? 0;
|
|
630
|
+
return { position: { x: previousX, y: previousX - previousDiagonal }, moveDown };
|
|
631
|
+
}
|
|
632
|
+
function buildEqualOps(lines, position, previous) {
|
|
633
|
+
const operations = [];
|
|
634
|
+
let x = position.x;
|
|
635
|
+
let y = position.y;
|
|
636
|
+
while (x > previous.x && y > previous.y) {
|
|
637
|
+
operations.push({ kind: " ", text: lines.before[x - 1] ?? "" });
|
|
638
|
+
x--;
|
|
639
|
+
y--;
|
|
640
|
+
}
|
|
641
|
+
return operations;
|
|
648
642
|
}
|
|
649
643
|
function buildHunks(ops) {
|
|
650
644
|
return buildWindows(ops).map((w) => buildHunk(ops, w));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zgeoff/format-codemod",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Enforce blank-line padding conventions in TypeScript via a fast text-splice codemod",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"oxc-parser": "0.153.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@types/bun": "1.
|
|
38
|
-
"typescript": "7.0.
|
|
37
|
+
"@types/bun": "1.4.2",
|
|
38
|
+
"typescript": "7.0.2"
|
|
39
39
|
},
|
|
40
40
|
"engines": {
|
|
41
41
|
"bun": ">=1.3",
|