difit 2.2.0 → 2.2.1

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.
@@ -0,0 +1,4 @@
1
+ import type { Comment } from '../types/diff';
2
+ export declare function formatCommentPrompt(file: string, line: number | number[], body: string): string;
3
+ export declare function formatAllCommentsPrompt(comments: Comment[]): string;
4
+ export declare function formatCommentsOutput(comments: Comment[]): string;
@@ -0,0 +1,24 @@
1
+ export function formatCommentPrompt(file, line, body) {
2
+ const lineInfo = typeof line === 'number' ? `L${line}`
3
+ : Array.isArray(line) ? `L${line[0]}-L${line[1]}`
4
+ : '';
5
+ // Handle undefined or null file paths
6
+ const filePath = file || '<unknown file>';
7
+ return `${filePath}:${lineInfo}\n${body}`;
8
+ }
9
+ export function formatAllCommentsPrompt(comments) {
10
+ if (comments.length === 0)
11
+ return '';
12
+ const prompts = comments.map((comment) => formatCommentPrompt(comment.file, comment.line, comment.body));
13
+ return prompts.join('\n=====\n');
14
+ }
15
+ export function formatCommentsOutput(comments) {
16
+ const allPrompts = formatAllCommentsPrompt(comments);
17
+ return [
18
+ '\n📝 Comments from review session:',
19
+ '='.repeat(50),
20
+ allPrompts,
21
+ '='.repeat(50),
22
+ `Total comments: ${comments.length}\n`,
23
+ ].join('\n');
24
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,220 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { formatCommentPrompt, formatAllCommentsPrompt, formatCommentsOutput, } from './commentFormatting';
3
+ describe('commentFormatting', () => {
4
+ describe('formatCommentPrompt', () => {
5
+ it('should format single line number correctly', () => {
6
+ const result = formatCommentPrompt('src/components/Button.tsx', 42, 'Fix accessibility');
7
+ expect(result).toBe('src/components/Button.tsx:L42\nFix accessibility');
8
+ });
9
+ it('should format line range correctly', () => {
10
+ const result = formatCommentPrompt('src/utils/validation.ts', [100, 120], 'Extract validation logic');
11
+ expect(result).toBe('src/utils/validation.ts:L100-L120\nExtract validation logic');
12
+ });
13
+ it('should handle line range as array correctly', () => {
14
+ const result = formatCommentPrompt('src/api/client.ts', [75, 80], 'Add retry logic');
15
+ expect(result).toBe('src/api/client.ts:L75-L80\nAdd retry logic');
16
+ });
17
+ it('should handle multi-line comment body', () => {
18
+ const body = 'This is a comment\nwith multiple lines\nof text';
19
+ const result = formatCommentPrompt('src/index.ts', 10, body);
20
+ expect(result).toBe('src/index.ts:L10\nThis is a comment\nwith multiple lines\nof text');
21
+ });
22
+ it('should handle file paths with special characters', () => {
23
+ const result = formatCommentPrompt('src/components/@shared/Button.tsx', 15, 'Update styles');
24
+ expect(result).toBe('src/components/@shared/Button.tsx:L15\nUpdate styles');
25
+ });
26
+ it('should handle undefined file path gracefully', () => {
27
+ const result = formatCommentPrompt(undefined, 10, 'Comment body');
28
+ expect(result).toBe('<unknown file>:L10\nComment body');
29
+ });
30
+ it('should handle null file path gracefully', () => {
31
+ const result = formatCommentPrompt(null, 10, 'Comment body');
32
+ expect(result).toBe('<unknown file>:L10\nComment body');
33
+ });
34
+ it('should handle empty string file path', () => {
35
+ const result = formatCommentPrompt('', 10, 'Comment body');
36
+ expect(result).toBe('<unknown file>:L10\nComment body');
37
+ });
38
+ });
39
+ describe('formatAllCommentsPrompt', () => {
40
+ it('should return empty string for empty comments array', () => {
41
+ const result = formatAllCommentsPrompt([]);
42
+ expect(result).toBe('');
43
+ });
44
+ it('should format single comment without separator', () => {
45
+ const comments = [
46
+ {
47
+ id: '1',
48
+ file: 'src/App.tsx',
49
+ line: 10,
50
+ body: 'Single comment',
51
+ timestamp: '2024-01-01T00:00:00Z',
52
+ },
53
+ ];
54
+ const result = formatAllCommentsPrompt(comments);
55
+ expect(result).toBe('src/App.tsx:L10\nSingle comment');
56
+ });
57
+ it('should format multiple comments with separator', () => {
58
+ const comments = [
59
+ {
60
+ id: '1',
61
+ file: 'src/App.tsx',
62
+ line: 10,
63
+ body: 'First comment',
64
+ timestamp: '2024-01-01T00:00:00Z',
65
+ },
66
+ {
67
+ id: '2',
68
+ file: 'src/utils/helper.ts',
69
+ line: [20, 25],
70
+ body: 'Second comment',
71
+ timestamp: '2024-01-01T00:01:00Z',
72
+ },
73
+ ];
74
+ const result = formatAllCommentsPrompt(comments);
75
+ expect(result).toBe('src/App.tsx:L10\nFirst comment\n=====\nsrc/utils/helper.ts:L20-L25\nSecond comment');
76
+ });
77
+ it('should handle comments with line ranges', () => {
78
+ const comments = [
79
+ {
80
+ id: '1',
81
+ file: 'src/components/Form.tsx',
82
+ line: [50, 75],
83
+ body: 'Refactor form validation',
84
+ timestamp: '2024-01-01T00:00:00Z',
85
+ },
86
+ {
87
+ id: '2',
88
+ file: 'src/api/endpoints.ts',
89
+ line: [100, 150],
90
+ body: 'Add error handling',
91
+ timestamp: '2024-01-01T00:01:00Z',
92
+ },
93
+ ];
94
+ const result = formatAllCommentsPrompt(comments);
95
+ expect(result).toBe('src/components/Form.tsx:L50-L75\nRefactor form validation\n=====\nsrc/api/endpoints.ts:L100-L150\nAdd error handling');
96
+ });
97
+ it('should preserve comment order', () => {
98
+ const comments = [
99
+ {
100
+ id: '3',
101
+ file: 'third.ts',
102
+ line: 30,
103
+ body: 'Third',
104
+ timestamp: '2024-01-01T00:02:00Z',
105
+ },
106
+ {
107
+ id: '1',
108
+ file: 'first.ts',
109
+ line: 10,
110
+ body: 'First',
111
+ timestamp: '2024-01-01T00:00:00Z',
112
+ },
113
+ {
114
+ id: '2',
115
+ file: 'second.ts',
116
+ line: 20,
117
+ body: 'Second',
118
+ timestamp: '2024-01-01T00:01:00Z',
119
+ },
120
+ ];
121
+ const result = formatAllCommentsPrompt(comments);
122
+ expect(result).toBe('third.ts:L30\nThird\n=====\nfirst.ts:L10\nFirst\n=====\nsecond.ts:L20\nSecond');
123
+ });
124
+ });
125
+ describe('formatCommentsOutput', () => {
126
+ it('should format empty comments with header and footer', () => {
127
+ const result = formatCommentsOutput([]);
128
+ const lines = result.split('\n');
129
+ expect(lines[0]).toBe('');
130
+ expect(lines[1]).toBe('📝 Comments from review session:');
131
+ expect(lines[2]).toBe('='.repeat(50));
132
+ expect(lines[3]).toBe('');
133
+ expect(lines[4]).toBe('='.repeat(50));
134
+ expect(lines[5]).toBe('Total comments: 0');
135
+ });
136
+ it('should format single comment with header and footer', () => {
137
+ const comments = [
138
+ {
139
+ id: '1',
140
+ file: 'src/App.tsx',
141
+ line: 10,
142
+ body: 'Fix this issue',
143
+ timestamp: '2024-01-01T00:00:00Z',
144
+ },
145
+ ];
146
+ const result = formatCommentsOutput(comments);
147
+ expect(result).toContain('📝 Comments from review session:');
148
+ expect(result).toContain('src/App.tsx:L10\nFix this issue');
149
+ expect(result).toContain('Total comments: 1');
150
+ expect(result).toContain('='.repeat(50));
151
+ });
152
+ it('should format multiple comments with separators', () => {
153
+ const comments = [
154
+ {
155
+ id: '1',
156
+ file: 'src/App.tsx',
157
+ line: 10,
158
+ body: 'First issue',
159
+ timestamp: '2024-01-01T00:00:00Z',
160
+ },
161
+ {
162
+ id: '2',
163
+ file: 'src/utils/helper.ts',
164
+ line: [20, 30],
165
+ body: 'Second issue',
166
+ timestamp: '2024-01-01T00:01:00Z',
167
+ },
168
+ {
169
+ id: '3',
170
+ file: 'src/components/Button.tsx',
171
+ line: 42,
172
+ body: 'Third issue',
173
+ timestamp: '2024-01-01T00:02:00Z',
174
+ },
175
+ ];
176
+ const result = formatCommentsOutput(comments);
177
+ expect(result).toContain('📝 Comments from review session:');
178
+ expect(result).toContain('src/App.tsx:L10\nFirst issue');
179
+ expect(result).toContain('=====');
180
+ expect(result).toContain('src/utils/helper.ts:L20-L30\nSecond issue');
181
+ expect(result).toContain('src/components/Button.tsx:L42\nThird issue');
182
+ expect(result).toContain('Total comments: 3');
183
+ });
184
+ it('should handle comments with multi-line bodies', () => {
185
+ const comments = [
186
+ {
187
+ id: '1',
188
+ file: 'src/complex.ts',
189
+ line: [100, 200],
190
+ body: 'This is a complex issue that\nspans multiple lines\nand needs attention',
191
+ timestamp: '2024-01-01T00:00:00Z',
192
+ },
193
+ ];
194
+ const result = formatCommentsOutput(comments);
195
+ expect(result).toContain('src/complex.ts:L100-L200');
196
+ expect(result).toContain('This is a complex issue that\nspans multiple lines\nand needs attention');
197
+ expect(result).toContain('Total comments: 1');
198
+ });
199
+ it('should format output with correct structure', () => {
200
+ const comments = [
201
+ {
202
+ id: '1',
203
+ file: 'test.ts',
204
+ line: 1,
205
+ body: 'Test comment',
206
+ timestamp: '2024-01-01T00:00:00Z',
207
+ },
208
+ ];
209
+ const result = formatCommentsOutput(comments);
210
+ const lines = result.split('\n');
211
+ expect(lines[0]).toBe('');
212
+ expect(lines[1]).toBe('📝 Comments from review session:');
213
+ expect(lines[2]).toBe('='.repeat(50));
214
+ expect(lines[3]).toBe('test.ts:L1');
215
+ expect(lines[4]).toBe('Test comment');
216
+ expect(lines[5]).toBe('='.repeat(50));
217
+ expect(lines[6]).toBe('Total comments: 1');
218
+ });
219
+ });
220
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "difit",
3
- "version": "2.2.0",
3
+ "version": "2.2.1",
4
4
  "description": "A lightweight command-line tool that spins up a local web server to display Git commit diffs in a GitHub-like Files changed view",
5
5
  "type": "module",
6
6
  "engines": {
@@ -54,8 +54,7 @@
54
54
  "react": "^19.1.0",
55
55
  "react-dom": "^19.1.0",
56
56
  "react-hotkeys-hook": "^5.1.0",
57
- "simple-git": "^3.28.0",
58
- "uuid": "^11.1.0"
57
+ "simple-git": "^3.28.0"
59
58
  },
60
59
  "devDependencies": {
61
60
  "@eslint/js": "^9.30.1",
@@ -72,7 +71,6 @@
72
71
  "@types/prismjs": "^1.26.5",
73
72
  "@types/react": "^19.1.8",
74
73
  "@types/react-dom": "^19.1.6",
75
- "@types/uuid": "^10.0.0",
76
74
  "@typescript-eslint/eslint-plugin": "^8.35.1",
77
75
  "@typescript-eslint/parser": "^8.35.1",
78
76
  "@vitejs/plugin-react": "^4.6.0",