@heyhuynhgiabuu/pi-diff 0.2.2 → 0.4.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.
Files changed (59) hide show
  1. package/README.md +117 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +55 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/core/diff.d.ts +14 -0
  7. package/dist/core/diff.d.ts.map +1 -0
  8. package/dist/core/diff.js +72 -0
  9. package/dist/core/diff.js.map +1 -0
  10. package/dist/index.d.ts +42 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +1738 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/review/command.d.ts +2 -0
  15. package/dist/review/command.d.ts.map +1 -0
  16. package/dist/review/command.js +365 -0
  17. package/dist/review/command.js.map +1 -0
  18. package/dist/review/export.d.ts +7 -0
  19. package/dist/review/export.d.ts.map +1 -0
  20. package/dist/review/export.js +77 -0
  21. package/dist/review/export.js.map +1 -0
  22. package/dist/review/file-preview.d.ts +9 -0
  23. package/dist/review/file-preview.d.ts.map +1 -0
  24. package/dist/review/file-preview.js +228 -0
  25. package/dist/review/file-preview.js.map +1 -0
  26. package/dist/review/git.d.ts +49 -0
  27. package/dist/review/git.d.ts.map +1 -0
  28. package/dist/review/git.js +200 -0
  29. package/dist/review/git.js.map +1 -0
  30. package/dist/review/hunk-preview.d.ts +25 -0
  31. package/dist/review/hunk-preview.d.ts.map +1 -0
  32. package/dist/review/hunk-preview.js +973 -0
  33. package/dist/review/hunk-preview.js.map +1 -0
  34. package/dist/review/interactive.d.ts +27 -0
  35. package/dist/review/interactive.d.ts.map +1 -0
  36. package/dist/review/interactive.js +146 -0
  37. package/dist/review/interactive.js.map +1 -0
  38. package/dist/review/model.d.ts +33 -0
  39. package/dist/review/model.d.ts.map +1 -0
  40. package/dist/review/model.js +208 -0
  41. package/dist/review/model.js.map +1 -0
  42. package/dist/review/prompt.d.ts +4 -0
  43. package/dist/review/prompt.d.ts.map +1 -0
  44. package/dist/review/prompt.js +43 -0
  45. package/dist/review/prompt.js.map +1 -0
  46. package/dist/review/session.d.ts +69 -0
  47. package/dist/review/session.d.ts.map +1 -0
  48. package/dist/review/session.js +190 -0
  49. package/dist/review/session.js.map +1 -0
  50. package/dist/review/tui.d.ts +57 -0
  51. package/dist/review/tui.d.ts.map +1 -0
  52. package/dist/review/tui.js +486 -0
  53. package/dist/review/tui.js.map +1 -0
  54. package/media/review-diff.png +0 -0
  55. package/package.json +73 -5
  56. package/prompts/review-diff-agent.md +19 -0
  57. package/biome.json +0 -29
  58. package/src/index.ts +0 -1635
  59. package/tsconfig.json +0 -19
package/README.md CHANGED
@@ -25,6 +25,7 @@ A [pi](https://pi.dev) extension that replaces the default `write` and `edit` to
25
25
  - **Adaptive layout** — auto-detects terminal width; wraps intelligently on wide terminals, truncates on narrow ones
26
26
  - **LRU cache** — singleton Shiki highlighter with 192-entry cache for fast re-renders
27
27
  - **Large diff fallback** — gracefully degrades (skips highlighting, still shows diff structure) for files > 80k chars
28
+ - **Review context export** — `pi-diff-review` exports Git changes as agent-ready markdown for Warp-style local code review
28
29
  - **Fully customizable** — every color and threshold is overridable via environment variables
29
30
 
30
31
  ## Install
@@ -41,6 +42,122 @@ Or load directly for development:
41
42
  pi -e ./src/index.ts
42
43
  ```
43
44
 
45
+ ## Git Review in Pi TUI
46
+
47
+ pi-diff now has two review paths:
48
+
49
+ 1. **`/review-diff`** — the primary interactive local-review command
50
+ 2. **`review_git_diff`** — the read-only markdown/tooling path for agent context and scripted review
51
+
52
+ ### `/review-diff` — interactive local review
53
+
54
+ Use `/review-diff` inside Pi TUI to open a full-width centered review overlay for your local Git diff.
55
+
56
+ <img width="900" alt="pi-diff review-diff interactive Git review overlay" src="media/review-diff.png" />
57
+
58
+ ```text
59
+ /review-diff
60
+ /review-diff --base main
61
+ /review-diff working-tree
62
+ /review-diff feature/base-branch
63
+ ```
64
+
65
+ What the overlay supports now:
66
+ - keyboard-driven file navigation
67
+ - hunk navigation for the selected file
68
+ - a fixed-height focused **hunk diff viewport** instead of a panel that grows/shrinks with diff size
69
+ - hunk-level preview scrolling inside the selected hunk, with scroll status and a visible `▶` selection marker
70
+ - load the selected file/line into Pi's main editor as review context
71
+ - copy the selected file/line/hunk reference to the clipboard
72
+ - line-anchored draft/edit/delete review comments
73
+ - approve/dismiss comments before submission
74
+ - batch-submit approved comments back into Pi as a follow-up prompt
75
+ - live auto-refresh while the overlay is open when the local git diff changes
76
+ - manual refresh of the current diff without leaving the review flow
77
+ - session persistence via Pi custom entries so reopening `/review-diff` restores the latest review state for the current session
78
+
79
+ Key bindings in the overlay:
80
+ - `Tab` cycles focus between files, hunks, preview, and comments
81
+ - `↑↓` / `Ctrl+j` / `Ctrl+k` navigate the focused region; in Preview focus this scrolls the selected hunk while keeping rendered content visible
82
+ - `PageUp` / `PageDown` move by a full visible page in the focused region; in Preview focus this scrolls the selected hunk viewport
83
+ - `Home` / `End` jump to the start/end of the focused region; in Preview focus this jumps within the selected hunk viewport
84
+ - mouse wheel scrolls the selected hunk viewport vertically when Pi forwards terminal wheel events to the overlay
85
+ - `[` / `]` jump between files
86
+ - `o` loads the selected file/line into Pi's main editor as review context
87
+ - `y` copies the selected file/line/hunk reference to the clipboard; if clipboard access fails, it loads the reference into Pi's main editor
88
+ - `c` drafts a comment on the current hunk / anchored preview line
89
+ - `e` edits the selected comment; if none exists yet, the overlay warns instead of silently doing nothing
90
+ - `x` deletes the selected comment
91
+ - `a` approves the selected comment
92
+ - `d` dismisses the selected comment
93
+ - `A` approves all comments
94
+ - `r` manually refreshes the diff immediately (the overlay also auto-refreshes while open)
95
+ - `s` submits approved comments back to Pi
96
+ - `Esc` / `q` closes the overlay
97
+
98
+ **Important:** `/review-diff` is a command, not a prompt template. Pi resolves extension commands before prompt templates, so a prompt template with the same name would be shadowed and never run.
99
+
100
+ ### `/review-diff-agent` — prompt template companion
101
+
102
+ If you want a blunt text review from the agent instead of the interactive overlay, use the bundled prompt template:
103
+
104
+ ```text
105
+ /review-diff-agent
106
+ ```
107
+
108
+ This prompt asks the agent to use `review_git_diff` as needed and produce a brutal review of the current local diff.
109
+
110
+ ### `review_git_diff` — read-only markdown review tool
111
+
112
+ `review_git_diff` remains available for agent/tool use and for non-destructive markdown exports.
113
+
114
+ ```ts
115
+ // Open the read-only review markdown for working-tree changes, including untracked files
116
+ review_git_diff({})
117
+
118
+ // Review branch changes as main...HEAD
119
+ review_git_diff({ base: "main" })
120
+
121
+ // Focus a file from the changed-file list
122
+ review_git_diff({ file: "src/index.ts" })
123
+
124
+ // Focus a hunk ID shown by the panel
125
+ review_git_diff({ file: "src/index.ts", hunkId: "src/index.ts:10:12" })
126
+
127
+ // Draft inline comments through the tool API
128
+ review_git_comment({ file: "src/index.ts", line: 42, body: "This needs a regression test." })
129
+
130
+ // List or clear drafted comments
131
+ review_git_comments({})
132
+ review_git_comments({ clear: true })
133
+
134
+ // Return the older full markdown export with raw unified diff included
135
+ review_git_diff({ base: "main", includeRawDiff: true })
136
+ ```
137
+
138
+ - No `base` means working-tree review, including untracked files.
139
+ - `base: "main"` means `main...HEAD` branch review.
140
+ - `includeRawDiff` returns the older full review export with raw unified diff.
141
+ - `maxLinesPerHunk`, `maxFiles`, and `maxHunks` cap large markdown reviews.
142
+ - The tool path is intentionally non-destructive: it never reverts, stages, commits, discards, or edits files.
143
+
144
+ ## Review Export CLI
145
+
146
+ `pi-diff-review` exports the same Git review context as markdown for use outside Pi TUI.
147
+
148
+ ```bash
149
+ # Review uncommitted working-tree changes
150
+ pi-diff-review
151
+
152
+ # Review branch changes like a pull request
153
+ pi-diff-review --base main
154
+
155
+ # Include the raw git diff after the structured summary
156
+ pi-diff-review --raw
157
+ ```
158
+
159
+ The export includes changed files, hunk headers, changed-line numbers, and review instructions focused on correctness, regressions, security, tests, and maintainability.
160
+
44
161
  ## How It Works
45
162
 
46
163
  pi-diff wraps the built-in `write` and `edit` tools from the pi SDK, including single-edit and multi-edit `edit` calls. When the agent writes or edits a file:
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const export_js_1 = require("./review/export.js");
5
+ const git_js_1 = require("./review/git.js");
6
+ function main(argv) {
7
+ const options = parseArgs(argv);
8
+ const diff = (0, git_js_1.readGitDiff)(process.cwd(), options.mode);
9
+ process.stdout.write((0, export_js_1.formatReviewMarkdown)(diff, {
10
+ includeRawDiff: options.includeRawDiff,
11
+ maxLinesPerHunk: options.maxLinesPerHunk,
12
+ }));
13
+ }
14
+ function parseArgs(argv) {
15
+ const options = { mode: { type: "working-tree" }, includeRawDiff: false };
16
+ for (let index = 0; index < argv.length; index++) {
17
+ const arg = argv[index];
18
+ if (arg === "--help" || arg === "-h") {
19
+ printHelp();
20
+ process.exit(0);
21
+ }
22
+ if (arg === "--base") {
23
+ const base = argv[++index];
24
+ if (!base)
25
+ throw new Error("--base requires a branch name");
26
+ options.mode = { type: "branch", base };
27
+ continue;
28
+ }
29
+ if (arg === "--raw") {
30
+ options.includeRawDiff = true;
31
+ continue;
32
+ }
33
+ if (arg === "--max-lines-per-hunk") {
34
+ const value = Number(argv[++index]);
35
+ if (!Number.isInteger(value) || value <= 0)
36
+ throw new Error("--max-lines-per-hunk requires a positive integer");
37
+ options.maxLinesPerHunk = value;
38
+ continue;
39
+ }
40
+ throw new Error(`Unknown argument: ${arg}`);
41
+ }
42
+ return options;
43
+ }
44
+ function printHelp() {
45
+ process.stdout.write(`pi-diff-review\n\nExport current Git changes as agent-ready code review context.\n\nUsage:\n pi-diff-review [--base <branch>] [--raw] [--max-lines-per-hunk <n>]\n\nOptions:\n --base <branch> Compare <branch>...HEAD instead of working tree changes.\n --raw Include the raw git diff at the end.\n --max-lines-per-hunk <n> Limit emitted lines per hunk (default: 80).\n`);
46
+ }
47
+ try {
48
+ main(process.argv.slice(2));
49
+ }
50
+ catch (error) {
51
+ const message = error instanceof Error ? error.message : String(error);
52
+ process.stderr.write(`pi-diff-review: ${message}\n`);
53
+ process.exitCode = 1;
54
+ }
55
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;AAEA,kDAA0D;AAC1D,4CAAmE;AAQnE,SAAS,IAAI,CAAC,IAAc;IAC3B,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,IAAA,oBAAW,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CACnB,IAAA,gCAAoB,EAAC,IAAI,EAAE;QAC1B,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,eAAe,EAAE,OAAO,CAAC,eAAe;KACxC,CAAC,CACF,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,IAAc;IAChC,MAAM,OAAO,GAAe,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;IACtF,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;QAClD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACtC,SAAS,EAAE,CAAC;YACZ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;QACD,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;YACtB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;YAC3B,IAAI,CAAC,IAAI;gBAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;YAC5D,OAAO,CAAC,IAAI,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;YACxC,SAAS;QACV,CAAC;QACD,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YACrB,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;YAC9B,SAAS;QACV,CAAC;QACD,IAAI,GAAG,KAAK,sBAAsB,EAAE,CAAC;YACpC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;YACpC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;YAChH,OAAO,CAAC,eAAe,GAAG,KAAK,CAAC;YAChC,SAAS;QACV,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,SAAS,SAAS;IACjB,OAAO,CAAC,MAAM,CAAC,KAAK,CACnB,+YAA+Y,CAC/Y,CAAC;AACH,CAAC;AAED,IAAI,CAAC;IACJ,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7B,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IAChB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,OAAO,IAAI,CAAC,CAAC;IACrD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACtB,CAAC"}
@@ -0,0 +1,14 @@
1
+ export interface DiffLine {
2
+ type: "add" | "del" | "ctx" | "sep";
3
+ oldNum: number | null;
4
+ newNum: number | null;
5
+ content: string;
6
+ }
7
+ export interface ParsedDiff {
8
+ lines: DiffLine[];
9
+ added: number;
10
+ removed: number;
11
+ chars: number;
12
+ }
13
+ export declare function parseDiff(oldContent: string, newContent: string, ctx?: number): ParsedDiff;
14
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/core/diff.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,QAAQ;IACxB,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;IACpC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,UAAU;IAC1B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,SAAI,GAAG,UAAU,CA+BrF"}
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.parseDiff = parseDiff;
37
+ const Diff = __importStar(require("diff"));
38
+ function parseDiff(oldContent, newContent, ctx = 3) {
39
+ const patch = Diff.structuredPatch("", "", oldContent, newContent, "", "", { context: ctx });
40
+ const lines = [];
41
+ let added = 0;
42
+ let removed = 0;
43
+ for (let hi = 0; hi < patch.hunks.length; hi++) {
44
+ if (hi > 0) {
45
+ const prev = patch.hunks[hi - 1];
46
+ const gap = patch.hunks[hi].oldStart - (prev.oldStart + prev.oldLines);
47
+ lines.push({ type: "sep", oldNum: null, newNum: gap > 0 ? gap : null, content: "" });
48
+ }
49
+ const h = patch.hunks[hi];
50
+ let oL = h.oldStart;
51
+ let nL = h.newStart;
52
+ for (const raw of h.lines) {
53
+ if (raw === "\")
54
+ continue;
55
+ const ch = raw[0];
56
+ const text = raw.slice(1);
57
+ if (ch === "+") {
58
+ lines.push({ type: "add", oldNum: null, newNum: nL++, content: text });
59
+ added++;
60
+ }
61
+ else if (ch === "-") {
62
+ lines.push({ type: "del", oldNum: oL++, newNum: null, content: text });
63
+ removed++;
64
+ }
65
+ else {
66
+ lines.push({ type: "ctx", oldNum: oL++, newNum: nL++, content: text });
67
+ }
68
+ }
69
+ }
70
+ return { lines, added, removed, chars: oldContent.length + newContent.length };
71
+ }
72
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/core/diff.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgBA,8BA+BC;AA/CD,2CAA6B;AAgB7B,SAAgB,SAAS,CAAC,UAAkB,EAAE,UAAkB,EAAE,GAAG,GAAG,CAAC;IACxE,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7F,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;QAChD,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;YACjC,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,QAAQ,GAAG,CAAC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;QACtF,CAAC;QACD,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1B,IAAI,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC;QACpB,IAAI,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC;QACpB,KAAK,MAAM,GAAG,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;YAC3B,IAAI,GAAG,KAAK,8BAA8B;gBAAE,SAAS;YACrD,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YAClB,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC1B,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;gBAChB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvE,KAAK,EAAE,CAAC;YACT,CAAC;iBAAM,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;gBACvB,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvE,OAAO,EAAE,CAAC;YACX,CAAC;iBAAM,CAAC;gBACP,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YACxE,CAAC;QACF,CAAC;IACF,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC;AAChF,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * pi-diff — Shiki-powered terminal diff renderer for pi.
3
+ *
4
+ * @module pi-diff
5
+ * @see https://github.com/buddingnewinsights/pi-diff
6
+ *
7
+ * Architecture (like OpenTUI / delta):
8
+ * 1. Syntax-highlight full code blocks via Shiki → ANSI (fg-only codes)
9
+ * 2. Layer diff background colors underneath (composites at cell level)
10
+ * 3. For word-level changes, inject brighter bg at changed char positions
11
+ * 4. Result: syntax fg + diff bg + word emphasis — all three visible together
12
+ *
13
+ * Views:
14
+ * • Split (side-by-side) — edit tool, auto-falls back to unified on narrow terminals
15
+ * • Unified (stacked) — write tool overwrites
16
+ *
17
+ * Performance:
18
+ * • Singleton Shiki highlighter (managed by @shikijs/cli)
19
+ * • LRU memo cache per highlighted block
20
+ * • Large-diff fallback (skip highlighting, still show diff)
21
+ * • Async rendering with invalidate() for non-blocking preview
22
+ */
23
+ import type { BundledLanguage } from "shiki";
24
+ import { type ParsedDiff, parseDiff } from "./core/diff.js";
25
+ /** Resolved ANSI colors for diff rendering — theme overrides hardcoded defaults. */
26
+ interface DiffColors {
27
+ fgAdd: string;
28
+ fgDel: string;
29
+ fgCtx: string;
30
+ }
31
+ declare function normalizeShikiContrast(ansi: string): string;
32
+ declare function renderUnified(diff: ParsedDiff, language: BundledLanguage | undefined, max?: number, dc?: DiffColors): Promise<string>;
33
+ declare function renderSplit(diff: ParsedDiff, language: BundledLanguage | undefined, max?: number, dc?: DiffColors): Promise<string>;
34
+ export declare const __testing: {
35
+ normalizeShikiContrast: typeof normalizeShikiContrast;
36
+ parseDiff: typeof parseDiff;
37
+ renderSplit: typeof renderSplit;
38
+ renderUnified: typeof renderUnified;
39
+ };
40
+ export default function diffRendererExtension(pi: any): Promise<void>;
41
+ export {};
42
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAOH,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,OAAO,CAAC;AAE3D,OAAO,EAAiB,KAAK,UAAU,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAuc3E,oFAAoF;AACpF,UAAU,UAAU;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACd;AAuKD,iBAAS,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIpD;AAkVD,iBAAe,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,eAAe,GAAG,SAAS,EACrC,GAAG,SAAmB,EACtB,EAAE,GAAE,UAAgC,GAClC,OAAO,CAAC,MAAM,CAAC,CAwHjB;AAMD,iBAAe,WAAW,CACzB,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,eAAe,GAAG,SAAS,EACrC,GAAG,SAAoB,EACvB,EAAE,GAAE,UAAgC,GAClC,OAAO,CAAC,MAAM,CAAC,CA6JjB;AAMD,eAAO,MAAM,SAAS;;;;;CAKrB,CAAC;AA8CF,wBAA8B,qBAAqB,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAykB1E"}