difit 1.1.1 → 1.1.3

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 @@
1
+ import{g as u}from"./index-Blx_E2fr.js";function p(t,a){for(var r=0;r<a.length;r++){const e=a[r];if(typeof e!="string"&&!Array.isArray(e)){for(const s in e)if(s!=="default"&&!(s in t)){const n=Object.getOwnPropertyDescriptor(e,s);n&&Object.defineProperty(t,s,n.get?n:{enumerable:!0,get:()=>e[s]})}}}return Object.freeze(Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}))}var o={},i;function d(){return i||(i=1,function(t){var a=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,r=/(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source,e={pattern:RegExp(/(^|[^\w.])/.source+r+/[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};t.languages.java=t.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[e,{pattern:RegExp(/(^|[^\w.])/.source+r+/[A-Z]\w*(?=\s+\w+\s*[;,=()]|\s*(?:\[[\s,]*\]\s*)?::\s*new\b)/.source),lookbehind:!0,inside:e.inside},{pattern:RegExp(/(\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\s+)/.source+r+/[A-Z]\w*\b/.source),lookbehind:!0,inside:e.inside}],keyword:a,function:[t.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0},constant:/\b[A-Z][A-Z_\d]+\b/}),t.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),t.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":e,keyword:a,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp(/(\bimport\s+)/.source+r+/(?:[A-Z]\w*|\*)(?=\s*;)/.source),lookbehind:!0,inside:{namespace:e.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp(/(\bimport\s+static\s+)/.source+r+/(?:\w+|\*)(?=\s*;)/.source),lookbehind:!0,alias:"static",inside:{namespace:e.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],namespace:{pattern:RegExp(/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)(?!<keyword>)[a-z]\w*(?:\.[a-z]\w*)*\.?/.source.replace(/<keyword>/g,function(){return a.source})),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism)),o}var c=d();const l=u(c),w=p({__proto__:null,default:l},[c]);export{w as p};
@@ -0,0 +1 @@
1
+ import{g as c}from"./index-Blx_E2fr.js";function f(e,r){for(var n=0;n<r.length;n++){const t=r[n];if(typeof t!="string"&&!Array.isArray(t)){for(const a in t)if(a!=="default"&&!(a in e)){const i=Object.getOwnPropertyDescriptor(t,a);i&&Object.defineProperty(e,a,i.get?i:{enumerable:!0,get:()=>t[a]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}var u={},d;function g(){return d||(d=1,function(e){var r=/\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/,n=[{pattern:/\b(?:false|true)\b/i,alias:"boolean"},{pattern:/(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,greedy:!0,lookbehind:!0},{pattern:/(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,greedy:!0,lookbehind:!0},/\b(?:null)\b/i,/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/],t=/\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i,a=/<?=>|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/,i=/[{}\[\](),:;]/;e.languages.php={delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"},comment:r,variable:/\$+(?:\w+\b|(?=\{))/,package:{pattern:/(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,lookbehind:!0,inside:{punctuation:/\\/}},"class-name-definition":{pattern:/(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,lookbehind:!0,alias:"class-name"},"function-definition":{pattern:/(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,lookbehind:!0,alias:"function"},keyword:[{pattern:/(\(\s*)\b(?:array|bool|boolean|float|int|integer|object|string)\b(?=\s*\))/i,alias:"type-casting",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|object|self|static|string)\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|never|object|self|static|string|void)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/\b(?:array(?!\s*\()|bool|float|int|iterable|mixed|object|string|void)\b/i,alias:"type-declaration",greedy:!0},{pattern:/(\|\s*)(?:false|null)\b|\b(?:false|null)(?=\s*\|)/i,alias:"type-declaration",greedy:!0,lookbehind:!0},{pattern:/\b(?:parent|self|static)(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(\byield\s+)from\b/i,lookbehind:!0},/\bclass\b/i,{pattern:/((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|match|namespace|never|new|or|parent|print|private|protected|public|readonly|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield|__halt_compiler)\b/i,lookbehind:!0}],"argument-name":{pattern:/([(,]\s*)\b[a-z_]\w*(?=\s*:(?!:))/i,lookbehind:!0},"class-name":[{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/(\|\s*)\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,greedy:!0},{pattern:/(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,alias:"class-name-fully-qualified",greedy:!0,inside:{punctuation:/\\/}},{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*\$)/i,alias:"type-declaration",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-declaration"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,alias:["class-name-fully-qualified","static-context"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-hint"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:["class-name-fully-qualified","return-type"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:n,function:{pattern:/(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,lookbehind:!0,inside:{punctuation:/\\/}},property:{pattern:/(->\s*)\w+/,lookbehind:!0},number:t,operator:a,punctuation:i};var l={pattern:/\{\$(?:\{(?:\{[^{}]+\}|[^{}]+)\}|[^{}])+\}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,lookbehind:!0,inside:e.languages.php},o=[{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,alias:"nowdoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:l}},{pattern:/`(?:\\[\s\S]|[^\\`])*`/,alias:"backtick-quoted-string",greedy:!0},{pattern:/'(?:\\[\s\S]|[^\\'])*'/,alias:"single-quoted-string",greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,alias:"double-quoted-string",greedy:!0,inside:{interpolation:l}}];e.languages.insertBefore("php","variable",{string:o,attribute:{pattern:/#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,greedy:!0,inside:{"attribute-content":{pattern:/^(#\[)[\s\S]+(?=\]$)/,lookbehind:!0,inside:{comment:r,string:o,"attribute-class-name":[{pattern:/([^:]|^)\b[a-z_]\w*(?!\\)\b/i,alias:"class-name",greedy:!0,lookbehind:!0},{pattern:/([^:]|^)(?:\\?\b[a-z_]\w*)+/i,alias:["class-name","class-name-fully-qualified"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:n,number:t,operator:a,punctuation:i}},delimiter:{pattern:/^#\[|\]$/,alias:"punctuation"}}}}),e.hooks.add("before-tokenize",function(s){if(/<\?/.test(s.code)){var p=/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/g;e.languages["markup-templating"].buildPlaceholders(s,"php",p)}}),e.hooks.add("after-tokenize",function(s){e.languages["markup-templating"].tokenizePlaceholders(s,"php")})}(Prism)),u}var b=g();const y=c(b),m=f({__proto__:null,default:y},[b]);export{m as p};
@@ -0,0 +1 @@
1
+ import{g as l}from"./index-Blx_E2fr.js";function d(e,r){for(var n=0;n<r.length;n++){const t=r[n];if(typeof t!="string"&&!Array.isArray(t)){for(const i in t)if(i!=="default"&&!(i in e)){const s=Object.getOwnPropertyDescriptor(t,i);s&&Object.defineProperty(e,i,s.get?s:{enumerable:!0,get:()=>t[i]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}var a={},o;function g(){return o||(o=1,function(e){e.languages.ruby=e.languages.extend("clike",{comment:{pattern:/#.*|^=begin\s[\s\S]*?^=end/m,greedy:!0},"class-name":{pattern:/(\b(?:class|module)\s+|\bcatch\s+\()[\w.\\]+|\b[A-Z_]\w*(?=\s*\.\s*new\b)/,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:BEGIN|END|alias|and|begin|break|case|class|def|define_method|defined|do|each|else|elsif|end|ensure|extend|for|if|in|include|module|new|next|nil|not|or|prepend|private|protected|public|raise|redo|require|rescue|retry|return|self|super|then|throw|undef|unless|until|when|while|yield)\b/,operator:/\.{2,3}|&\.|===|<?=>|[!=]?~|(?:&&|\|\||<<|>>|\*\*|[+\-*/%<>!^&|=])=?|[?:]/,punctuation:/[(){}[\].,;]/}),e.languages.insertBefore("ruby","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}});var r={pattern:/((?:^|[^\\])(?:\\{2})*)#\{(?:[^{}]|\{[^{}]*\})*\}/,lookbehind:!0,inside:{content:{pattern:/^(#\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:e.languages.ruby},delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"}}};delete e.languages.ruby.function;var n="(?:"+[/([^a-zA-Z0-9\s{(\[<=])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,/\((?:[^()\\]|\\[\s\S]|\((?:[^()\\]|\\[\s\S])*\))*\)/.source,/\{(?:[^{}\\]|\\[\s\S]|\{(?:[^{}\\]|\\[\s\S])*\})*\}/.source,/\[(?:[^\[\]\\]|\\[\s\S]|\[(?:[^\[\]\\]|\\[\s\S])*\])*\]/.source,/<(?:[^<>\\]|\\[\s\S]|<(?:[^<>\\]|\\[\s\S])*>)*>/.source].join("|")+")",t=/(?:"(?:\\.|[^"\\\r\n])*"|(?:\b[a-zA-Z_]\w*|[^\s\0-\x7F]+)[?!]?|\$.)/.source;e.languages.insertBefore("ruby","keyword",{"regex-literal":[{pattern:RegExp(/%r/.source+n+/[egimnosux]{0,6}/.source),greedy:!0,inside:{interpolation:r,regex:/[\s\S]+/}},{pattern:/(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[egimnosux]{0,6}(?=\s*(?:$|[\r\n,.;})#]))/,lookbehind:!0,greedy:!0,inside:{interpolation:r,regex:/[\s\S]+/}}],variable:/[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,symbol:[{pattern:RegExp(/(^|[^:]):/.source+t),lookbehind:!0,greedy:!0},{pattern:RegExp(/([\r\n{(,][ \t]*)/.source+t+/(?=:(?!:))/.source),lookbehind:!0,greedy:!0}],"method-definition":{pattern:/(\bdef\s+)\w+(?:\s*\.\s*\w+)?/,lookbehind:!0,inside:{function:/\b\w+$/,keyword:/^self\b/,"class-name":/^\w+/,punctuation:/\./}}}),e.languages.insertBefore("ruby","string",{"string-literal":[{pattern:RegExp(/%[qQiIwWs]?/.source+n),greedy:!0,inside:{interpolation:r,string:/[\s\S]+/}},{pattern:/("|')(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|(?!\1)[^\\#\r\n])*\1/,greedy:!0,inside:{interpolation:r,string:/[\s\S]+/}},{pattern:/<<[-~]?([a-z_]\w*)[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?[a-z_]\w*|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?/}},interpolation:r,string:/[\s\S]+/}},{pattern:/<<[-~]?'([a-z_]\w*)'[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?'[a-z_]\w*'|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?'|'$/}},string:/[\s\S]+/}}],"command-literal":[{pattern:RegExp(/%x/.source+n),greedy:!0,inside:{interpolation:r,command:{pattern:/[\s\S]+/,alias:"string"}}},{pattern:/`(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|[^\\`#\r\n])*`/,greedy:!0,inside:{interpolation:r,command:{pattern:/[\s\S]+/,alias:"string"}}}]}),delete e.languages.ruby.string,e.languages.insertBefore("ruby","number",{builtin:/\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Fixnum|Float|Hash|IO|Integer|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|Stat|String|Struct|Symbol|TMS|Thread|ThreadGroup|Time|TrueClass)\b/,constant:/\b[A-Z][A-Z0-9_]*(?:[?!]|\b)/}),e.languages.rb=e.languages.ruby}(Prism)),a}var u=g();const p=l(u),b=d({__proto__:null,default:p},[u]);export{b as p};
@@ -10,8 +10,8 @@
10
10
  <link rel="icon" type="image/png" sizes="512x512" href="/icon-512x512.png" />
11
11
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
12
12
  <title>ReviewIt - Git Diff Viewer</title>
13
- <script type="module" crossorigin src="/assets/index-B67TY4_1.js"></script>
14
- <link rel="stylesheet" crossorigin href="/assets/index-BHrhjAlZ.css">
13
+ <script type="module" crossorigin src="/assets/index-Blx_E2fr.js"></script>
14
+ <link rel="stylesheet" crossorigin href="/assets/index-BKXkeB0O.css">
15
15
  </head>
16
16
  <body>
17
17
  <div id="root"></div>
@@ -1,5 +1,5 @@
1
1
  import simpleGit from 'simple-git';
2
- import { validateDiffArguments } from '../cli/utils.js';
2
+ import { validateDiffArguments, createCommitRangeString } from '../cli/utils.js';
3
3
  export async function loadGitDiff(targetCommitish, baseCommitish) {
4
4
  // Validate arguments
5
5
  const validation = validateDiffArguments(targetCommitish, baseCommitish);
@@ -23,7 +23,10 @@ export async function loadGitDiff(targetCommitish, baseCommitish) {
23
23
  }
24
24
  else {
25
25
  // Both are regular commits: standard commit-to-commit comparison
26
- diff = await git.diff([`${baseCommitish}..${targetCommitish}`, '--name-status']);
26
+ diff = await git.diff([
27
+ createCommitRangeString(baseCommitish, targetCommitish),
28
+ '--name-status',
29
+ ]);
27
30
  if (!diff.trim()) {
28
31
  // Try without parent (for initial commit)
29
32
  const diffInitial = await git.diff([targetCommitish, '--name-status']);
@@ -60,7 +63,11 @@ export async function loadGitDiff(targetCommitish, baseCommitish) {
60
63
  else {
61
64
  try {
62
65
  // Both are regular commits: standard commit-to-commit comparison
63
- fileDiff = await git.diff([`${baseCommitish}..${targetCommitish}`, '--', path]);
66
+ fileDiff = await git.diff([
67
+ createCommitRangeString(baseCommitish, targetCommitish),
68
+ '--',
69
+ path,
70
+ ]);
64
71
  }
65
72
  catch {
66
73
  // For new files or if parent doesn't exist
@@ -1,6 +1,7 @@
1
1
  import { simpleGit } from 'simple-git';
2
- import { validateDiffArguments, shortHash } from '../cli/utils.js';
2
+ import { validateDiffArguments, shortHash, createCommitRangeString } from '../cli/utils.js';
3
3
  export class GitDiffParser {
4
+ git;
4
5
  constructor(repoPath = process.cwd()) {
5
6
  this.git = simpleGit(repoPath);
6
7
  }
@@ -35,7 +36,7 @@ export class GitDiffParser {
35
36
  // Both are regular commits: standard commit-to-commit comparison
36
37
  const targetHash = await this.git.revparse([targetCommitish]);
37
38
  const baseHash = await this.git.revparse([baseCommitish]);
38
- resolvedCommit = `${shortHash(baseHash)}..${shortHash(targetHash)}`;
39
+ resolvedCommit = createCommitRangeString(shortHash(baseHash), shortHash(targetHash));
39
40
  diffArgs = [baseCommitish, targetCommitish];
40
41
  }
41
42
  if (ignoreWhitespace) {
@@ -11,6 +11,7 @@ export async function startServer(options) {
11
11
  let diffData = null;
12
12
  let currentIgnoreWhitespace = options.ignoreWhitespace || false;
13
13
  app.use(express.json());
14
+ app.use(express.text()); // For sendBeacon text/plain requests
14
15
  app.use((_req, res, next) => {
15
16
  res.header('Access-Control-Allow-Origin', 'http://localhost:*');
16
17
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
@@ -30,6 +31,58 @@ export async function startServer(options) {
30
31
  }
31
32
  res.json({ ...diffData, ignoreWhitespace });
32
33
  });
34
+ // Store comments for final output
35
+ let finalComments = [];
36
+ app.post('/api/comments', (req, res) => {
37
+ try {
38
+ // Handle both JSON and text/plain content types (sendBeacon sends as text/plain)
39
+ let comments = [];
40
+ if (req.headers['content-type']?.includes('application/json')) {
41
+ comments = req.body.comments || [];
42
+ }
43
+ else if (typeof req.body === 'string') {
44
+ const parsed = JSON.parse(req.body);
45
+ comments = parsed.comments || [];
46
+ }
47
+ else {
48
+ comments = req.body.comments || [];
49
+ }
50
+ finalComments = comments;
51
+ res.json({ success: true });
52
+ }
53
+ catch (error) {
54
+ console.error('Error parsing comments:', error);
55
+ res.status(400).json({ error: 'Invalid comment data' });
56
+ }
57
+ });
58
+ app.get('/api/comments-output', (_req, res) => {
59
+ if (finalComments.length > 0) {
60
+ const output = formatCommentsOutput(finalComments);
61
+ res.send(output);
62
+ }
63
+ else {
64
+ res.send('');
65
+ }
66
+ });
67
+ // Function to format comments for output
68
+ function formatCommentsOutput(comments) {
69
+ const prompts = comments.map((comment) => {
70
+ return `${comment.file}:${comment.line}\n${comment.body}`;
71
+ });
72
+ return [
73
+ '\nšŸ“ Comments from review session:',
74
+ '='.repeat(50),
75
+ prompts.join('\n=====\n'),
76
+ '='.repeat(50),
77
+ `Total comments: ${comments.length}\n`,
78
+ ].join('\n');
79
+ }
80
+ // Function to output comments when server shuts down
81
+ function outputFinalComments() {
82
+ if (finalComments.length > 0) {
83
+ console.log(formatCommentsOutput(finalComments));
84
+ }
85
+ }
33
86
  // SSE endpoint to detect when tab is closed
34
87
  app.get('/api/heartbeat', (req, res) => {
35
88
  res.writeHead(200, {
@@ -48,6 +101,7 @@ export async function startServer(options) {
48
101
  req.on('close', () => {
49
102
  clearInterval(heartbeatInterval);
50
103
  console.log('Client disconnected, shutting down server...');
104
+ outputFinalComments();
51
105
  process.exit(0);
52
106
  });
53
107
  });
@@ -57,7 +111,7 @@ export async function startServer(options) {
57
111
  // Find client files relative to the CLI executable location
58
112
  const distPath = join(__dirname, '..', 'client');
59
113
  app.use(express.static(distPath));
60
- app.get('*', (_req, res) => {
114
+ app.get('/{*splat}', (_req, res) => {
61
115
  res.sendFile(join(distPath, 'index.html'));
62
116
  });
63
117
  }
@@ -85,7 +139,7 @@ export async function startServer(options) {
85
139
  try {
86
140
  await open(url);
87
141
  }
88
- catch (error) {
142
+ catch {
89
143
  console.warn('Failed to open browser automatically');
90
144
  }
91
145
  }
@@ -106,7 +160,7 @@ async function startServerWithFallback(app, preferredPort) {
106
160
  .catch(reject);
107
161
  }
108
162
  else {
109
- reject(err);
163
+ reject(new Error(`Server error: ${err instanceof Error ? err.message : String(err)}`));
110
164
  }
111
165
  });
112
166
  });
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "difit",
3
- "version": "1.1.1",
3
+ "version": "1.1.3",
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": {
7
- "node": ">=18.0.0"
7
+ "node": ">=21.0.0"
8
8
  },
9
9
  "bin": {
10
10
  "difit": "./dist/cli/index.js"
@@ -34,17 +34,17 @@
34
34
  "prepublishOnly": "NODE_ENV=production pnpm run build"
35
35
  },
36
36
  "dependencies": {
37
- "commander": "^11.1.0",
38
- "express": "^4.18.2",
39
- "ink": "^5.2.1",
37
+ "commander": "^14.0.0",
38
+ "express": "^5.1.0",
39
+ "ink": "^6.0.1",
40
40
  "lucide-react": "^0.525.0",
41
- "open": "^10.0.3",
41
+ "open": "^10.1.2",
42
42
  "prism-react-renderer": "^2.4.1",
43
43
  "prismjs": "^1.30.0",
44
- "react": "^18.2.0",
45
- "react-dom": "^18.2.0",
46
- "shiki": "^0.14.7",
47
- "simple-git": "^3.20.0"
44
+ "react": "^19.1.0",
45
+ "react-dom": "^19.1.0",
46
+ "shiki": "^3.7.0",
47
+ "simple-git": "^3.28.0"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@eslint/eslintrc": "^3.3.1",
@@ -52,28 +52,28 @@
52
52
  "@tailwindcss/postcss": "^4.1.11",
53
53
  "@tailwindcss/typography": "^0.5.16",
54
54
  "@tsconfig/strictest": "^2.0.5",
55
- "@types/express": "^4.17.21",
56
- "@types/node": "^20.10.5",
55
+ "@types/express": "^5.0.3",
56
+ "@types/node": "^24.0.8",
57
57
  "@types/prismjs": "^1.26.5",
58
- "@types/react": "^18.2.45",
59
- "@types/react-dom": "^18.2.18",
60
- "@typescript-eslint/eslint-plugin": "^6.15.0",
61
- "@typescript-eslint/parser": "^6.15.0",
62
- "@vitejs/plugin-react": "^4.2.1",
58
+ "@types/react": "^19.1.8",
59
+ "@types/react-dom": "^19.1.6",
60
+ "@typescript-eslint/eslint-plugin": "^8.35.1",
61
+ "@typescript-eslint/parser": "^8.35.1",
62
+ "@vitejs/plugin-react": "^4.6.0",
63
63
  "autoprefixer": "^10.4.21",
64
- "eslint": "^8.56.0",
64
+ "eslint": "^9.30.0",
65
65
  "eslint-config-prettier": "^10.1.5",
66
66
  "eslint-plugin-import": "^2.32.0",
67
- "eslint-plugin-react": "^7.33.2",
68
- "eslint-plugin-react-hooks": "^4.6.0",
67
+ "eslint-plugin-react": "^7.37.5",
68
+ "eslint-plugin-react-hooks": "^5.2.0",
69
69
  "eslint-plugin-unused-imports": "^4.1.4",
70
- "lefthook": "^1.5.5",
70
+ "lefthook": "^1.11.14",
71
71
  "postcss": "^8.5.6",
72
- "prettier": "^3.1.1",
72
+ "prettier": "^3.6.2",
73
73
  "tailwindcss": "^4.1.11",
74
- "typescript": "^5.3.3",
75
- "vite": "^5.0.10",
76
- "vitest": "^1.1.0"
74
+ "typescript": "^5.8.3",
75
+ "vite": "^7.0.0",
76
+ "vitest": "^3.2.4"
77
77
  },
78
78
  "files": [
79
79
  "dist",