difit 4.0.6 → 5.0.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/README.ja.md +1 -2
- package/README.ko.md +1 -2
- package/README.md +6 -2
- package/README.zh.md +1 -2
- package/dist/cli/index.js +0 -35
- package/dist/cli/index.test.js +0 -264
- package/dist/cli/utils.d.ts +0 -2
- package/dist/cli/utils.js +1 -18
- package/dist/cli/utils.test.js +0 -16
- package/dist/client/assets/{arc-1g1LrDb3.js → arc-DbOd2jxV.js} +1 -1
- package/dist/client/assets/architecture-YZFGNWBL-0n2ZLuLj.js +1 -0
- package/dist/client/assets/{architectureDiagram-Q4EWVU46-D87-Rmwy.js → architectureDiagram-Q4EWVU46-BFXI_tUS.js} +1 -1
- package/dist/client/assets/{blockDiagram-DXYQGD6D-Cep-MIFv.js → blockDiagram-DXYQGD6D-BOEZDsFe.js} +1 -1
- package/dist/client/assets/{c4Diagram-AHTNJAMY-BQuH9Txx.js → c4Diagram-AHTNJAMY-BdIoPSTS.js} +1 -1
- package/dist/client/assets/channel-DPag0OPA.js +1 -0
- package/dist/client/assets/{chunk-2KRD3SAO-CpQQpmvx.js → chunk-2KRD3SAO-BaHSMZbk.js} +1 -1
- package/dist/client/assets/{chunk-336JU56O-Ddk9EzgO.js → chunk-336JU56O-BGfMTguc.js} +2 -2
- package/dist/client/assets/chunk-426QAEUC-Ct2OJ1s3.js +1 -0
- package/dist/client/assets/{chunk-4BX2VUAB-Ca-N0Wd9.js → chunk-4BX2VUAB-CNkIhTNe.js} +1 -1
- package/dist/client/assets/{chunk-4TB4RGXK-ZTWP_Onw.js → chunk-4TB4RGXK-wFMAN-Ug.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-Dub40zHG.js → chunk-55IACEB6-J_10GkPG.js} +1 -1
- package/dist/client/assets/{chunk-5FUZZQ4R-Cgda0gtZ.js → chunk-5FUZZQ4R-0NY9W0kL.js} +1 -1
- package/dist/client/assets/{chunk-5PVQY5BW-D8JPH_tm.js → chunk-5PVQY5BW-nUEO-vub.js} +1 -1
- package/dist/client/assets/{chunk-67CJDMHE-U1KyLHzG.js → chunk-67CJDMHE-CpK_DCjw.js} +1 -1
- package/dist/client/assets/{chunk-7N4EOEYR-WzOy51nD.js → chunk-7N4EOEYR-CJfX2SRB.js} +1 -1
- package/dist/client/assets/{chunk-AA7GKIK3-DlWOj4lr.js → chunk-AA7GKIK3-DGHjDQX4.js} +1 -1
- package/dist/client/assets/{chunk-BSJP7CBP-CcZ0op08.js → chunk-BSJP7CBP-DiXS795w.js} +1 -1
- package/dist/client/assets/{chunk-CIAEETIT-qVSphnw5.js → chunk-CIAEETIT-DaOGL_z8.js} +1 -1
- package/dist/client/assets/{chunk-EDXVE4YY-76SPH4sf.js → chunk-EDXVE4YY-EPdmphYw.js} +1 -1
- package/dist/client/assets/{chunk-ENJZ2VHE-CKULNIzL.js → chunk-ENJZ2VHE-9x7-Qpzy.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-CvDPP3mb.js → chunk-FMBD7UC4-Dgx4um1Q.js} +1 -1
- package/dist/client/assets/{chunk-FOC6F5B3-DceW0hWA.js → chunk-FOC6F5B3-BaVe0aqm.js} +1 -1
- package/dist/client/assets/{chunk-ICPOFSXX-ChGBNZMk.js → chunk-ICPOFSXX-C9l3r2YR.js} +1 -1
- package/dist/client/assets/{chunk-K5T4RW27-DBHdC4ln.js → chunk-K5T4RW27-Bv0dnd8C.js} +1 -1
- package/dist/client/assets/{chunk-KGLVRYIC-DRS7yiGQ.js → chunk-KGLVRYIC-BdTDi9hU.js} +1 -1
- package/dist/client/assets/{chunk-LIHQZDEY-KsE8dyJP.js → chunk-LIHQZDEY-BEYvjNoB.js} +1 -1
- package/dist/client/assets/{chunk-ORNJ4GCN-Dnp4oHRD.js → chunk-ORNJ4GCN-CHeeoEx_.js} +1 -1
- package/dist/client/assets/{chunk-OYMX7WX6-CciaotDu.js → chunk-OYMX7WX6-Bapbqtyc.js} +1 -1
- package/dist/client/assets/chunk-QZHKN3VN-CNqVW4m2.js +1 -0
- package/dist/client/assets/{chunk-U2HBQHQK-nbp7CjBP.js → chunk-U2HBQHQK-CpVfEbNc.js} +1 -1
- package/dist/client/assets/{chunk-X2U36JSP-Chs85loT.js → chunk-X2U36JSP-BAcfna0L.js} +1 -1
- package/dist/client/assets/{chunk-XPW4576I-VtI9b561.js → chunk-XPW4576I-D0wrDPCQ.js} +1 -1
- package/dist/client/assets/{chunk-YZCP3GAM-sBsewSoO.js → chunk-YZCP3GAM-D_AeoI3D.js} +1 -1
- package/dist/client/assets/{chunk-ZZ45TVLE-TMgeW_px.js → chunk-ZZ45TVLE-CwpZ5yb7.js} +1 -1
- package/dist/client/assets/classDiagram-6PBFFD2Q-aX3PLX0y.js +1 -0
- package/dist/client/assets/classDiagram-v2-HSJHXN6E-CshAcrwe.js +1 -0
- package/dist/client/assets/clone-J5cJUwR3.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-5TzM3w9g.js → cose-bilkent-S5V4N54A-DJvkrscF.js} +1 -1
- package/dist/client/assets/{dagre-sb6WtN4K.js → dagre-BADyoi72.js} +1 -1
- package/dist/client/assets/{dagre-KV5264BT-xvyFOxd3.js → dagre-KV5264BT-BDTirpEd.js} +1 -1
- package/dist/client/assets/{diagram-5BDNPKRD-ChRpAe5p.js → diagram-5BDNPKRD-CJSn8eie.js} +1 -1
- package/dist/client/assets/{diagram-G4DWMVQ6-C_8BED4A.js → diagram-G4DWMVQ6-COzN0wAe.js} +1 -1
- package/dist/client/assets/{diagram-MMDJMWI5-BMwXEou2.js → diagram-MMDJMWI5-Bau__Yfk.js} +1 -1
- package/dist/client/assets/{diagram-TYMM5635-CeAkx82D.js → diagram-TYMM5635-DKIgp_-m.js} +1 -1
- package/dist/client/assets/{dist-CwC9dd2Z.js → dist-CL_sSZWx.js} +1 -1
- package/dist/client/assets/{erDiagram-SMLLAGMA-yGCTeXGt.js → erDiagram-SMLLAGMA-Iw0m0edr.js} +1 -1
- package/dist/client/assets/{flowDiagram-DWJPFMVM-CugkvbmM.js → flowDiagram-DWJPFMVM-CtXQs1rX.js} +1 -1
- package/dist/client/assets/{ganttDiagram-T4ZO3ILL-BXnlBFgK.js → ganttDiagram-T4ZO3ILL-B0341I_2.js} +1 -1
- package/dist/client/assets/gitGraph-7Q5UKJZL-NWgYXB7y.js +1 -0
- package/dist/client/assets/{gitGraphDiagram-UUTBAWPF-B61aCwwu.js → gitGraphDiagram-UUTBAWPF-Yv3oicIa.js} +1 -1
- package/dist/client/assets/{graphlib-BMWKz3zT.js → graphlib-BLiSTux3.js} +1 -1
- package/dist/client/assets/index-C2jd9xpN.js +79 -0
- package/dist/client/assets/index-v-PY_jQI.css +2 -0
- package/dist/client/assets/info-OMHHGYJF-Bvc7BWzq.js +1 -0
- package/dist/client/assets/{infoDiagram-42DDH7IO-Bkh6nTL2.js → infoDiagram-42DDH7IO-Cfjrwz2v.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-UXIWVN3A-D_fdVT6_.js → ishikawaDiagram-UXIWVN3A-Cc-jozqB.js} +1 -1
- package/dist/client/assets/{journeyDiagram-VCZTEJTY-DkXVokNF.js → journeyDiagram-VCZTEJTY-Bjx1sC-s.js} +1 -1
- package/dist/client/assets/{kanban-definition-6JOO6SKY-y8qq7qvL.js → kanban-definition-6JOO6SKY-CIkJYslO.js} +1 -1
- package/dist/client/assets/{line-B0LcTqNY.js → line-yxqmb99x.js} +1 -1
- package/dist/client/assets/{linear-CqIjr2qp.js → linear-DCAQGlgU.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-Du6QzpZO.js → mermaid-parser.core-B5ufZrv2.js} +2 -2
- package/dist/client/assets/{mermaid.core-CZBu-oKJ.js → mermaid.core-BFOnV1aK.js} +3 -3
- package/dist/client/assets/{mindmap-definition-QFDTVHPH-BJrRxSkM.js → mindmap-definition-QFDTVHPH-CPflWkUN.js} +1 -1
- package/dist/client/assets/packet-4T2RLAQJ-DNpLsp8v.js +1 -0
- package/dist/client/assets/pie-ZZUOXDRM-D8uToFEL.js +1 -0
- package/dist/client/assets/{pieDiagram-DEJITSTG-Debmhc0u.js → pieDiagram-DEJITSTG-Dl3gScVb.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-34T5L4WZ-SE3g2BC9.js → quadrantDiagram-34T5L4WZ-38YyGeXU.js} +1 -1
- package/dist/client/assets/radar-PYXPWWZC-VrpLp1jL.js +1 -0
- package/dist/client/assets/{requirementDiagram-MS252O5E-1mv41puC.js → requirementDiagram-MS252O5E-CZW6zJs_.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-XADWPNL6-CLjPRtOP.js → sankeyDiagram-XADWPNL6-D4r0GNlW.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-FGHM5R23-Cs-P3AtR.js → sequenceDiagram-FGHM5R23-2xItvAxs.js} +1 -1
- package/dist/client/assets/{src-5XpQHeIJ.js → src-YK4ClFOB.js} +1 -1
- package/dist/client/assets/{stateDiagram-FHFEXIEX-CmB1fohY.js → stateDiagram-FHFEXIEX-lBViG7kM.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-BcU-AM4S.js +1 -0
- package/dist/client/assets/{timeline-definition-GMOUNBTQ-BMUafJOI.js → timeline-definition-GMOUNBTQ-DmlaOXs4.js} +1 -1
- package/dist/client/assets/treeView-SZITEDCU-B1qc9ijP.js +1 -0
- package/dist/client/assets/treemap-W4RFUUIX-Dl7yWWae.js +1 -0
- package/dist/client/assets/{vennDiagram-DHZGUBPP-CpZ1Qhjz.js → vennDiagram-DHZGUBPP-BOLv0A8q.js} +1 -1
- package/dist/client/assets/wardley-RL74JXVD-CEXd-1Ht.js +1 -0
- package/dist/client/assets/{wardleyDiagram-NUSXRM2D-C-zH0lsd.js → wardleyDiagram-NUSXRM2D-B5lHUuTU.js} +1 -1
- package/dist/client/assets/{xychartDiagram-5P7HB3ND-SkLFuEHZ.js → xychartDiagram-5P7HB3ND-D8nLdJo8.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/client/site-data/manifest.json +1 -0
- package/dist/client/site-data/snapshots/55f23a1...080c0e6.json +1 -0
- package/dist/client/site-data/snapshots/66ff7c6...e6977fe.json +1 -0
- package/dist/client/site-data/snapshots/7d40fd4...a72112f-comments.json +1 -0
- package/dist/client/site-data/snapshots/7d40fd4...a72112f.json +1 -0
- package/dist/types/diff.d.ts +11 -10
- package/dist/utils/commentFormatting.test.js +0 -52
- package/package.json +5 -6
- package/dist/cli/tuiDeprecation.d.ts +0 -3
- package/dist/cli/tuiDeprecation.js +0 -16
- package/dist/cli/tuiDeprecation.test.d.ts +0 -1
- package/dist/cli/tuiDeprecation.test.js +0 -16
- package/dist/client/assets/architecture-YZFGNWBL-MZfdAdY6.js +0 -1
- package/dist/client/assets/channel-CJqLEVLU.js +0 -1
- package/dist/client/assets/chunk-426QAEUC-2xhUznDE.js +0 -1
- package/dist/client/assets/chunk-QZHKN3VN-BiVE5u_E.js +0 -1
- package/dist/client/assets/classDiagram-6PBFFD2Q-CfyHazmg.js +0 -1
- package/dist/client/assets/classDiagram-v2-HSJHXN6E-D7Rb-bnu.js +0 -1
- package/dist/client/assets/clone-8xC1huEg.js +0 -1
- package/dist/client/assets/gitGraph-7Q5UKJZL-BeTWkPrd.js +0 -1
- package/dist/client/assets/index-D2Y8-unG.css +0 -2
- package/dist/client/assets/index-D9v_eYzS.js +0 -79
- package/dist/client/assets/info-OMHHGYJF-MUNR2tTt.js +0 -1
- package/dist/client/assets/packet-4T2RLAQJ-Ci-Uu57s.js +0 -1
- package/dist/client/assets/pie-ZZUOXDRM-pm57XGIg.js +0 -1
- package/dist/client/assets/radar-PYXPWWZC-CH-AuSDw.js +0 -1
- package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-D6jsrR-f.js +0 -1
- package/dist/client/assets/treeView-SZITEDCU-BGsVMAdJ.js +0 -1
- package/dist/client/assets/treemap-W4RFUUIX-DXnhegXy.js +0 -1
- package/dist/client/assets/wardley-RL74JXVD-COd5nWj-.js +0 -1
- package/dist/server/git-diff-tui.d.ts +0 -2
- package/dist/server/git-diff-tui.js +0 -100
- package/dist/server/git-diff-tui.test.d.ts +0 -1
- package/dist/server/git-diff-tui.test.js +0 -76
- package/dist/tui/App.d.ts +0 -10
- package/dist/tui/App.js +0 -92
- package/dist/tui/components/DiffViewer.d.ts +0 -8
- package/dist/tui/components/DiffViewer.js +0 -88
- package/dist/tui/components/FileList.d.ts +0 -8
- package/dist/tui/components/FileList.js +0 -48
- package/dist/tui/components/SideBySideDiffViewer.d.ts +0 -9
- package/dist/tui/components/SideBySideDiffViewer.js +0 -240
- package/dist/tui/components/StatusBar.d.ts +0 -8
- package/dist/tui/components/StatusBar.js +0 -19
- package/dist/tui/utils/parseDiff.d.ts +0 -2
- package/dist/tui/utils/parseDiff.js +0 -67
- package/dist/utils/createId.test.d.ts +0 -1
- package/dist/utils/createId.test.js +0 -48
|
@@ -1,240 +0,0 @@
|
|
|
1
|
-
import { Box, Text, useInput, useApp } from 'ink';
|
|
2
|
-
import React, { useState } from 'react';
|
|
3
|
-
import { parseDiff } from '../utils/parseDiff.js';
|
|
4
|
-
const SideBySideDiffViewer = ({ files, initialFileIndex, onBack, }) => {
|
|
5
|
-
const [currentFileIndex, setCurrentFileIndex] = useState(initialFileIndex);
|
|
6
|
-
const [scrollOffset, setScrollOffset] = useState(0);
|
|
7
|
-
const { exit } = useApp();
|
|
8
|
-
const viewportHeight = Math.max(10, (process.stdout.rows || 24) - 10);
|
|
9
|
-
const currentFile = files[currentFileIndex];
|
|
10
|
-
useInput((input, key) => {
|
|
11
|
-
if (input === 'q' || (key.ctrl && input === 'c')) {
|
|
12
|
-
exit();
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
if (key.escape || input === 'b') {
|
|
16
|
-
onBack();
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
if (!currentFile)
|
|
20
|
-
return;
|
|
21
|
-
// Scroll within file
|
|
22
|
-
if (key.upArrow || input === 'k') {
|
|
23
|
-
setScrollOffset((prev) => Math.max(0, prev - 1));
|
|
24
|
-
}
|
|
25
|
-
if (key.downArrow || input === 'j') {
|
|
26
|
-
setScrollOffset((prev) => prev + 1);
|
|
27
|
-
}
|
|
28
|
-
if (key.pageUp) {
|
|
29
|
-
setScrollOffset((prev) => Math.max(0, prev - viewportHeight));
|
|
30
|
-
}
|
|
31
|
-
if (key.pageDown) {
|
|
32
|
-
setScrollOffset((prev) => prev + viewportHeight);
|
|
33
|
-
}
|
|
34
|
-
// Navigate between files
|
|
35
|
-
if (key.tab && !key.shift) {
|
|
36
|
-
// Next file (loop to first when at end)
|
|
37
|
-
setCurrentFileIndex((currentFileIndex + 1) % files.length);
|
|
38
|
-
setScrollOffset(0);
|
|
39
|
-
}
|
|
40
|
-
if (key.tab && key.shift) {
|
|
41
|
-
// Previous file (loop to last when at start)
|
|
42
|
-
setCurrentFileIndex((currentFileIndex - 1 + files.length) % files.length);
|
|
43
|
-
setScrollOffset(0);
|
|
44
|
-
}
|
|
45
|
-
}, { isActive: true });
|
|
46
|
-
if (!currentFile || files.length === 0) {
|
|
47
|
-
return (React.createElement(Box, { flexDirection: "column", flexGrow: 1 },
|
|
48
|
-
React.createElement(Text, { color: "yellow" }, "No files to display"),
|
|
49
|
-
React.createElement(Box, { marginTop: 1 },
|
|
50
|
-
React.createElement(Text, { dimColor: true }, "Press ESC or 'b' to go back"))));
|
|
51
|
-
}
|
|
52
|
-
const parsedDiff = parseDiff(currentFile.diff);
|
|
53
|
-
// Calculate total lines for current file
|
|
54
|
-
const allLines = [];
|
|
55
|
-
parsedDiff.chunks.forEach((chunk) => {
|
|
56
|
-
// Add chunk header
|
|
57
|
-
allLines.push({
|
|
58
|
-
old: chunk.header,
|
|
59
|
-
new: chunk.header,
|
|
60
|
-
type: 'header',
|
|
61
|
-
});
|
|
62
|
-
let oldIdx = 0;
|
|
63
|
-
let newIdx = 0;
|
|
64
|
-
while (oldIdx < chunk.lines.length || newIdx < chunk.lines.length) {
|
|
65
|
-
const oldLine = chunk.lines[oldIdx];
|
|
66
|
-
const newLine = chunk.lines[newIdx];
|
|
67
|
-
if (oldLine?.type === 'remove' && newLine?.type === 'add') {
|
|
68
|
-
// Same line modified - show side by side
|
|
69
|
-
allLines.push({
|
|
70
|
-
old: oldLine.content,
|
|
71
|
-
new: newLine.content,
|
|
72
|
-
oldNum: oldLine.oldLineNumber,
|
|
73
|
-
newNum: newLine.newLineNumber,
|
|
74
|
-
type: 'modified',
|
|
75
|
-
});
|
|
76
|
-
oldIdx++;
|
|
77
|
-
newIdx++;
|
|
78
|
-
}
|
|
79
|
-
else if (oldLine?.type === 'remove') {
|
|
80
|
-
// Line removed
|
|
81
|
-
allLines.push({
|
|
82
|
-
old: oldLine.content,
|
|
83
|
-
oldNum: oldLine.oldLineNumber,
|
|
84
|
-
type: 'remove',
|
|
85
|
-
});
|
|
86
|
-
oldIdx++;
|
|
87
|
-
}
|
|
88
|
-
else if (newLine?.type === 'add') {
|
|
89
|
-
// Line added
|
|
90
|
-
allLines.push({
|
|
91
|
-
new: newLine.content,
|
|
92
|
-
newNum: newLine.newLineNumber,
|
|
93
|
-
type: 'add',
|
|
94
|
-
});
|
|
95
|
-
newIdx++;
|
|
96
|
-
}
|
|
97
|
-
else if (oldLine?.type === 'context') {
|
|
98
|
-
// Unchanged line
|
|
99
|
-
allLines.push({
|
|
100
|
-
old: oldLine.content,
|
|
101
|
-
new: oldLine.content,
|
|
102
|
-
oldNum: oldLine.oldLineNumber,
|
|
103
|
-
newNum: oldLine.newLineNumber,
|
|
104
|
-
type: 'context',
|
|
105
|
-
});
|
|
106
|
-
oldIdx++;
|
|
107
|
-
newIdx++;
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
oldIdx++;
|
|
111
|
-
newIdx++;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
const actualMaxScroll = Math.max(0, allLines.length - viewportHeight);
|
|
116
|
-
const clampedScrollOffset = Math.max(0, Math.min(actualMaxScroll, scrollOffset));
|
|
117
|
-
const visibleLines = allLines.slice(clampedScrollOffset, clampedScrollOffset + viewportHeight);
|
|
118
|
-
const terminalWidth = process.stdout.columns || 80;
|
|
119
|
-
const columnWidth = Math.floor((terminalWidth - 6) / 2); // 6 for borders and separators
|
|
120
|
-
const getLineColor = (type) => {
|
|
121
|
-
switch (type) {
|
|
122
|
-
case 'add':
|
|
123
|
-
return 'green';
|
|
124
|
-
case 'remove':
|
|
125
|
-
return 'red';
|
|
126
|
-
case 'modified':
|
|
127
|
-
return undefined; // Will be handled separately for each side
|
|
128
|
-
case 'header':
|
|
129
|
-
return 'cyan';
|
|
130
|
-
default:
|
|
131
|
-
return undefined;
|
|
132
|
-
}
|
|
133
|
-
};
|
|
134
|
-
const truncateLine = (line, width) => {
|
|
135
|
-
if (line.length <= width)
|
|
136
|
-
return line.padEnd(width);
|
|
137
|
-
return line.substring(0, width - 1) + '…';
|
|
138
|
-
};
|
|
139
|
-
return (React.createElement(Box, { flexDirection: "column", flexGrow: 1 },
|
|
140
|
-
React.createElement(Box, { marginBottom: 1, flexDirection: "column" },
|
|
141
|
-
React.createElement(Box, null,
|
|
142
|
-
React.createElement(Text, { bold: true },
|
|
143
|
-
currentFile.path,
|
|
144
|
-
" (",
|
|
145
|
-
currentFileIndex + 1,
|
|
146
|
-
"/",
|
|
147
|
-
files.length,
|
|
148
|
-
")"),
|
|
149
|
-
React.createElement(Text, { dimColor: true },
|
|
150
|
-
' ',
|
|
151
|
-
"- ",
|
|
152
|
-
currentFile.additions,
|
|
153
|
-
" additions, ",
|
|
154
|
-
currentFile.deletions,
|
|
155
|
-
" deletions")),
|
|
156
|
-
React.createElement(Box, { height: 2, overflow: "hidden", flexDirection: "column" }, (() => {
|
|
157
|
-
const terminalWidth = process.stdout.columns || 80;
|
|
158
|
-
const maxWidth = terminalWidth - 4; // Leave some margin
|
|
159
|
-
// Generate file list with current file highlighted
|
|
160
|
-
const fileItems = [];
|
|
161
|
-
// Add files before current
|
|
162
|
-
for (let i = Math.max(0, currentFileIndex - 2); i < currentFileIndex; i++) {
|
|
163
|
-
fileItems.push({
|
|
164
|
-
text: files[i].path,
|
|
165
|
-
isActive: false,
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
// Add current file
|
|
169
|
-
fileItems.push({
|
|
170
|
-
text: `[${files[currentFileIndex].path}]`,
|
|
171
|
-
isActive: true,
|
|
172
|
-
});
|
|
173
|
-
// Add files after current
|
|
174
|
-
for (let i = currentFileIndex + 1; i < Math.min(files.length, currentFileIndex + 3); i++) {
|
|
175
|
-
fileItems.push({
|
|
176
|
-
text: files[i].path,
|
|
177
|
-
isActive: false,
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
// Build lines (max 2 lines)
|
|
181
|
-
const lines = [[]];
|
|
182
|
-
let currentLineWidth = 0;
|
|
183
|
-
for (const item of fileItems) {
|
|
184
|
-
const itemWidth = item.text.length + 3; // Include separator
|
|
185
|
-
if (currentLineWidth + itemWidth > maxWidth && lines.length < 2) {
|
|
186
|
-
lines.push([]);
|
|
187
|
-
currentLineWidth = 0;
|
|
188
|
-
}
|
|
189
|
-
if (lines.length <= 2) {
|
|
190
|
-
lines[lines.length - 1].push(item);
|
|
191
|
-
currentLineWidth += itemWidth;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
return lines.map((line, lineIndex) => (React.createElement(Box, { key: lineIndex }, line.map((item, itemIndex) => (React.createElement(React.Fragment, { key: itemIndex },
|
|
195
|
-
itemIndex > 0 && React.createElement(Text, { dimColor: true }, " | "),
|
|
196
|
-
React.createElement(Text, { color: item.isActive ? 'cyan' : undefined, dimColor: !item.isActive }, item.text)))))));
|
|
197
|
-
})())),
|
|
198
|
-
React.createElement(Box, { borderStyle: "single", flexDirection: "column", flexGrow: 1 },
|
|
199
|
-
React.createElement(Box, { borderStyle: "single", borderTop: false, borderLeft: false, borderRight: false },
|
|
200
|
-
React.createElement(Box, { width: columnWidth },
|
|
201
|
-
React.createElement(Text, { dimColor: true }, " \u2502 "),
|
|
202
|
-
React.createElement(Text, { bold: true }, "Old")),
|
|
203
|
-
React.createElement(Text, { dimColor: true }, " \u2503 "),
|
|
204
|
-
React.createElement(Box, { width: columnWidth },
|
|
205
|
-
React.createElement(Text, { dimColor: true }, " \u2502 "),
|
|
206
|
-
React.createElement(Text, { bold: true }, "New"))),
|
|
207
|
-
React.createElement(Box, { flexDirection: "column", flexGrow: 1 }, visibleLines.map((line, index) => (React.createElement(Box, { key: `line-${scrollOffset + index}` },
|
|
208
|
-
React.createElement(Box, { width: columnWidth },
|
|
209
|
-
React.createElement(Text, { dimColor: true }, line.oldNum ? String(line.oldNum).padStart(4) : ' '),
|
|
210
|
-
React.createElement(Text, { dimColor: true }, " \u2502 "),
|
|
211
|
-
React.createElement(Text, { color: line.type === 'remove' || line.type === 'modified' ? 'red' : undefined, dimColor: line.type === 'header' }, line.type === 'remove' || line.type === 'modified' ? '- ' : ' '),
|
|
212
|
-
React.createElement(Text, { color: line.type === 'remove' || line.type === 'modified'
|
|
213
|
-
? 'red'
|
|
214
|
-
: getLineColor(line.type) }, line.old
|
|
215
|
-
? truncateLine(line.old, columnWidth - 10)
|
|
216
|
-
: ' '.repeat(columnWidth - 10))),
|
|
217
|
-
React.createElement(Text, { dimColor: true }, " \u2503 "),
|
|
218
|
-
React.createElement(Box, { width: columnWidth },
|
|
219
|
-
React.createElement(Text, { dimColor: true }, line.newNum ? String(line.newNum).padStart(4) : ' '),
|
|
220
|
-
React.createElement(Text, { dimColor: true }, " \u2502 "),
|
|
221
|
-
React.createElement(Text, { color: line.type === 'add' || line.type === 'modified' ? 'green' : undefined, dimColor: line.type === 'header' }, line.type === 'add' || line.type === 'modified' ? '+ ' : ' '),
|
|
222
|
-
React.createElement(Text, { color: line.type === 'add' || line.type === 'modified'
|
|
223
|
-
? 'green'
|
|
224
|
-
: getLineColor(line.type) }, line.new
|
|
225
|
-
? truncateLine(line.new, columnWidth - 10)
|
|
226
|
-
: ' '.repeat(columnWidth - 10)))))))),
|
|
227
|
-
React.createElement(Box, { marginTop: 1, justifyContent: "space-between" },
|
|
228
|
-
React.createElement(Text, { dimColor: true },
|
|
229
|
-
"Lines ",
|
|
230
|
-
scrollOffset + 1,
|
|
231
|
-
"-",
|
|
232
|
-
Math.min(scrollOffset + viewportHeight, allLines.length),
|
|
233
|
-
" of",
|
|
234
|
-
' ',
|
|
235
|
-
allLines.length,
|
|
236
|
-
scrollOffset + viewportHeight < allLines.length &&
|
|
237
|
-
` (${allLines.length - scrollOffset - viewportHeight} more)`),
|
|
238
|
-
React.createElement(Text, { dimColor: true }, "Tab: next file | Shift+Tab: prev file | \u2191\u2193/jk: scroll | ESC/b: back"))));
|
|
239
|
-
};
|
|
240
|
-
export default SideBySideDiffViewer;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { Box, Text } from 'ink';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
const StatusBar = ({ commitish, totalFiles, currentMode }) => {
|
|
4
|
-
return (React.createElement(Box, { borderStyle: "round", paddingX: 1, marginBottom: 1 },
|
|
5
|
-
React.createElement(Box, { flexGrow: 1 },
|
|
6
|
-
React.createElement(Text, { bold: true, color: "cyan" }, "\uD83D\uDCCB difit TUI"),
|
|
7
|
-
React.createElement(Text, null, " | "),
|
|
8
|
-
React.createElement(Text, { color: "yellow" }, commitish),
|
|
9
|
-
React.createElement(Text, null, " | "),
|
|
10
|
-
React.createElement(Text, null,
|
|
11
|
-
totalFiles,
|
|
12
|
-
" files changed")),
|
|
13
|
-
React.createElement(Box, null,
|
|
14
|
-
React.createElement(Text, { dimColor: true },
|
|
15
|
-
"[",
|
|
16
|
-
currentMode === 'list' ? 'File List' : currentMode === 'split' ? 'Split' : 'Unified',
|
|
17
|
-
"]"))));
|
|
18
|
-
};
|
|
19
|
-
export default StatusBar;
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
export function parseDiff(diffText) {
|
|
2
|
-
const lines = diffText.split('\n');
|
|
3
|
-
const chunks = [];
|
|
4
|
-
let currentChunk = null;
|
|
5
|
-
let oldLineNumber = 0;
|
|
6
|
-
let newLineNumber = 0;
|
|
7
|
-
for (const line of lines) {
|
|
8
|
-
// Skip file headers
|
|
9
|
-
if (line.startsWith('diff --git') ||
|
|
10
|
-
line.startsWith('index ') ||
|
|
11
|
-
line.startsWith('---') ||
|
|
12
|
-
line.startsWith('+++')) {
|
|
13
|
-
continue;
|
|
14
|
-
}
|
|
15
|
-
// Chunk header
|
|
16
|
-
if (line.startsWith('@@')) {
|
|
17
|
-
const match = line.match(/@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@/);
|
|
18
|
-
if (match) {
|
|
19
|
-
const [, oldStart, oldLinesStr, newStart, newLinesStr] = match;
|
|
20
|
-
currentChunk = {
|
|
21
|
-
header: line,
|
|
22
|
-
oldStart: parseInt(oldStart),
|
|
23
|
-
oldLines: parseInt(oldLinesStr || '1'),
|
|
24
|
-
newStart: parseInt(newStart),
|
|
25
|
-
newLines: parseInt(newLinesStr || '1'),
|
|
26
|
-
lines: [],
|
|
27
|
-
};
|
|
28
|
-
chunks.push(currentChunk);
|
|
29
|
-
oldLineNumber = currentChunk.oldStart - 1;
|
|
30
|
-
newLineNumber = currentChunk.newStart - 1;
|
|
31
|
-
}
|
|
32
|
-
continue;
|
|
33
|
-
}
|
|
34
|
-
// Skip if no current chunk
|
|
35
|
-
if (!currentChunk)
|
|
36
|
-
continue;
|
|
37
|
-
// Parse diff lines
|
|
38
|
-
if (line.startsWith('+')) {
|
|
39
|
-
newLineNumber++;
|
|
40
|
-
currentChunk.lines.push({
|
|
41
|
-
type: 'add',
|
|
42
|
-
content: line.substring(1),
|
|
43
|
-
newLineNumber: newLineNumber,
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
else if (line.startsWith('-')) {
|
|
47
|
-
oldLineNumber++;
|
|
48
|
-
currentChunk.lines.push({
|
|
49
|
-
type: 'remove',
|
|
50
|
-
content: line.substring(1),
|
|
51
|
-
oldLineNumber: oldLineNumber,
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
// Context line
|
|
56
|
-
oldLineNumber++;
|
|
57
|
-
newLineNumber++;
|
|
58
|
-
currentChunk.lines.push({
|
|
59
|
-
type: 'context',
|
|
60
|
-
content: line.substring(1),
|
|
61
|
-
oldLineNumber: oldLineNumber,
|
|
62
|
-
newLineNumber: newLineNumber,
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
return { chunks };
|
|
67
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import { createId } from './createId';
|
|
3
|
-
describe('createId', () => {
|
|
4
|
-
it('creates a 16-character lowercase alphanumeric id', () => {
|
|
5
|
-
const randomSpy = vi.spyOn(Math, 'random').mockReturnValue(0);
|
|
6
|
-
expect(createId()).toBe('aaaaaaaaaaaaaaaa');
|
|
7
|
-
randomSpy.mockRestore();
|
|
8
|
-
});
|
|
9
|
-
it('creates different ids across successive calls', () => {
|
|
10
|
-
const randomSpy = vi
|
|
11
|
-
.spyOn(Math, 'random')
|
|
12
|
-
.mockReturnValueOnce(0)
|
|
13
|
-
.mockReturnValueOnce(1 / 36)
|
|
14
|
-
.mockReturnValueOnce(2 / 36)
|
|
15
|
-
.mockReturnValueOnce(3 / 36)
|
|
16
|
-
.mockReturnValueOnce(4 / 36)
|
|
17
|
-
.mockReturnValueOnce(5 / 36)
|
|
18
|
-
.mockReturnValueOnce(6 / 36)
|
|
19
|
-
.mockReturnValueOnce(7 / 36)
|
|
20
|
-
.mockReturnValueOnce(8 / 36)
|
|
21
|
-
.mockReturnValueOnce(9 / 36)
|
|
22
|
-
.mockReturnValueOnce(10 / 36)
|
|
23
|
-
.mockReturnValueOnce(11 / 36)
|
|
24
|
-
.mockReturnValueOnce(12 / 36)
|
|
25
|
-
.mockReturnValueOnce(13 / 36)
|
|
26
|
-
.mockReturnValueOnce(14 / 36)
|
|
27
|
-
.mockReturnValueOnce(15 / 36)
|
|
28
|
-
.mockReturnValueOnce(16 / 36)
|
|
29
|
-
.mockReturnValueOnce(17 / 36)
|
|
30
|
-
.mockReturnValueOnce(18 / 36)
|
|
31
|
-
.mockReturnValueOnce(19 / 36)
|
|
32
|
-
.mockReturnValueOnce(20 / 36)
|
|
33
|
-
.mockReturnValueOnce(21 / 36)
|
|
34
|
-
.mockReturnValueOnce(22 / 36)
|
|
35
|
-
.mockReturnValueOnce(23 / 36)
|
|
36
|
-
.mockReturnValueOnce(24 / 36)
|
|
37
|
-
.mockReturnValueOnce(25 / 36)
|
|
38
|
-
.mockReturnValueOnce(26 / 36)
|
|
39
|
-
.mockReturnValueOnce(27 / 36)
|
|
40
|
-
.mockReturnValueOnce(28 / 36)
|
|
41
|
-
.mockReturnValueOnce(29 / 36)
|
|
42
|
-
.mockReturnValueOnce(30 / 36)
|
|
43
|
-
.mockReturnValueOnce(31 / 36);
|
|
44
|
-
expect(createId()).toBe('abcdefghijklmnop');
|
|
45
|
-
expect(createId()).toBe('qrstuvwxyz012345');
|
|
46
|
-
randomSpy.mockRestore();
|
|
47
|
-
});
|
|
48
|
-
});
|