difit 0.0.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.
Files changed (46) hide show
  1. package/README.md +106 -0
  2. package/dist/cli/index.d.ts +2 -0
  3. package/dist/cli/index.js +44 -0
  4. package/dist/cli/index.test.d.ts +1 -0
  5. package/dist/cli/index.test.js +676 -0
  6. package/dist/cli/utils.d.ts +1 -0
  7. package/dist/cli/utils.js +11 -0
  8. package/dist/cli/utils.test.d.ts +1 -0
  9. package/dist/cli/utils.test.js +214 -0
  10. package/dist/client/assets/index-BUtmfbD2.js +53 -0
  11. package/dist/client/assets/index-mZRIDsXW.css +1 -0
  12. package/dist/client/assets/prism-css-Bpx-unsJ.js +1 -0
  13. package/dist/client/assets/prism-json-xwnKirkR.js +1 -0
  14. package/dist/client/assets/prism-typescript-B2PMeEx1.js +1 -0
  15. package/dist/client/index.html +14 -0
  16. package/dist/server/comment-store.d.ts +13 -0
  17. package/dist/server/comment-store.js +63 -0
  18. package/dist/server/git-diff-tui.d.ts +2 -0
  19. package/dist/server/git-diff-tui.js +95 -0
  20. package/dist/server/git-diff.d.ts +10 -0
  21. package/dist/server/git-diff.js +124 -0
  22. package/dist/server/git-diff.test.d.ts +1 -0
  23. package/dist/server/git-diff.test.js +292 -0
  24. package/dist/server/server.d.ts +11 -0
  25. package/dist/server/server.js +128 -0
  26. package/dist/server/server.test.d.ts +1 -0
  27. package/dist/server/server.test.js +382 -0
  28. package/dist/tui/App.d.ts +8 -0
  29. package/dist/tui/App.js +92 -0
  30. package/dist/tui/App.test.d.ts +1 -0
  31. package/dist/tui/App.test.js +31 -0
  32. package/dist/tui/components/DiffViewer.d.ts +9 -0
  33. package/dist/tui/components/DiffViewer.js +88 -0
  34. package/dist/tui/components/FileList.d.ts +8 -0
  35. package/dist/tui/components/FileList.js +48 -0
  36. package/dist/tui/components/SideBySideDiffViewer.d.ts +9 -0
  37. package/dist/tui/components/SideBySideDiffViewer.js +237 -0
  38. package/dist/tui/components/StatusBar.d.ts +8 -0
  39. package/dist/tui/components/StatusBar.js +23 -0
  40. package/dist/tui/utils/parseDiff.d.ts +2 -0
  41. package/dist/tui/utils/parseDiff.js +68 -0
  42. package/dist/types/diff.d.ts +33 -0
  43. package/dist/types/diff.js +1 -0
  44. package/dist/utils/fileUtils.d.ts +12 -0
  45. package/dist/utils/fileUtils.js +21 -0
  46. package/package.json +91 -0
@@ -0,0 +1 @@
1
+ /*! tailwindcss v4.1.11 | MIT License | https://tailwindcss.com */@layer properties{@supports ((-webkit-hyphens:none) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-duration:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-100:oklch(93.6% .032 17.717);--color-yellow-100:oklch(97.3% .071 103.193);--color-green-100:oklch(96.2% .044 156.743);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-600:oklch(54.6% .245 262.881);--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--font-weight-medium:500;--font-weight-semibold:600;--tracking-wide:.025em;--radius-md:.375rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-github-bg-primary:#0d1117;--color-github-bg-secondary:#161b22;--color-github-bg-tertiary:#21262d;--color-github-border:#30363d;--color-github-text-primary:#f0f6fc;--color-github-text-secondary:#8b949e;--color-github-text-muted:#6e7681;--color-github-accent:#238636;--color-github-danger:#da3633;--color-github-warning:#d29922;--color-diff-addition-bg:#0d4429;--color-diff-deletion-bg:#67060c}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::-moz-placeholder{opacity:1}::placeholder{opacity:1}@supports (not (-webkit-appearance:-apple-pay-button)) or (contain-intrinsic-size:1px){::-moz-placeholder{color:currentColor}::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::-moz-placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.absolute{position:absolute}.relative{position:relative}.top-1\/2{top:50%}.right-2{right:calc(var(--spacing)*2)}.m-0{margin:calc(var(--spacing)*0)}.m-2{margin:calc(var(--spacing)*2)}.mx-3{margin-inline:calc(var(--spacing)*3)}.mx-4{margin-inline:calc(var(--spacing)*4)}.mr-1{margin-right:calc(var(--spacing)*1)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-1\.5{margin-bottom:calc(var(--spacing)*1.5)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.block{display:block}.flex{display:flex}.inline{display:inline}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-full{height:100%}.h-screen{height:100vh}.min-h-\[20px\]{min-height:20px}.min-h-\[60px\]{min-height:60px}.w-1\/2{width:50%}.w-3{width:calc(var(--spacing)*3)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-6{width:calc(var(--spacing)*6)}.w-80{width:calc(var(--spacing)*80)}.w-\[50px\]{width:50px}.w-\[60px\]{width:60px}.w-full{width:100%}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-80{min-width:calc(var(--spacing)*80)}.flex-1{flex:1}.flex-shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.cursor-pointer{cursor:pointer}.resize-y{resize:vertical}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:calc(var(--spacing)*1)}.gap-2{gap:calc(var(--spacing)*2)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l-4{border-left-style:var(--tw-border-style);border-left-width:4px}.border-none{--tw-border-style:none;border-style:none}.border-\[var\(--border\)\]{border-color:var(--border)}.border-\[var\(--border-muted\)\]{border-color:var(--border-muted)}.border-blue-600{border-color:var(--color-blue-600)}.border-github-border{border-color:var(--color-github-border)}.border-l-blue-600{border-left-color:var(--color-blue-600)}.bg-\[var\(--bg-secondary\)\]{background-color:var(--bg-secondary)}.bg-\[var\(--bg-tertiary\)\]{background-color:var(--bg-tertiary)}.bg-blue-600{background-color:var(--color-blue-600)}.bg-diff-addition-bg{background-color:var(--color-diff-addition-bg)}.bg-diff-deletion-bg{background-color:var(--color-diff-deletion-bg)}.bg-github-bg-primary{background-color:var(--color-github-bg-primary)}.bg-github-bg-secondary{background-color:var(--color-github-bg-secondary)}.bg-github-bg-tertiary{background-color:var(--color-github-bg-tertiary)}.bg-green-100\/10{background-color:#dcfce71a}@supports (color:color-mix(in lab,red,red)){.bg-green-100\/10{background-color:color-mix(in oklab,var(--color-green-100)10%,transparent)}}.bg-red-100\/10{background-color:#ffe2e21a}@supports (color:color-mix(in lab,red,red)){.bg-red-100\/10{background-color:color-mix(in oklab,var(--color-red-100)10%,transparent)}}.bg-transparent{background-color:#0000}.bg-yellow-100{background-color:var(--color-yellow-100)}.p-0{padding:calc(var(--spacing)*0)}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.px-1{padding-inline:calc(var(--spacing)*1)}.px-1\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-5{padding-inline:calc(var(--spacing)*5)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-3{padding-block:calc(var(--spacing)*3)}.py-4{padding-block:calc(var(--spacing)*4)}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[13px\]{font-size:13px}.leading-5{--tw-leading:calc(var(--spacing)*5);line-height:calc(var(--spacing)*5)}.leading-6{--tw-leading:calc(var(--spacing)*6);line-height:calc(var(--spacing)*6)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.break-all{word-break:break-all}.text-ellipsis{text-overflow:ellipsis}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-\[var\(--text-muted\)\]{color:var(--text-muted)}.text-\[var\(--text-primary\)\]{color:var(--text-primary)}.text-github-accent{color:var(--color-github-accent)}.text-github-danger{color:var(--color-github-danger)}.text-github-text-muted{color:var(--color-github-text-muted)}.text-github-text-primary{color:var(--color-github-text-primary)}.text-github-text-secondary{color:var(--color-github-text-secondary)}.text-github-warning{color:var(--color-github-warning)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.line-through{text-decoration-line:line-through}.accent-github-accent{accent-color:var(--color-github-accent)}.opacity-0{opacity:0}.opacity-70{opacity:.7}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}@media (hover:hover){.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}.hover\:border-blue-600:hover{border-color:var(--color-blue-600)}.hover\:bg-\[var\(--bg-tertiary\)\]:hover{background-color:var(--bg-tertiary)}.hover\:bg-blue-100\/10:hover{background-color:#dbeafe1a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-blue-100\/10:hover{background-color:color-mix(in oklab,var(--color-blue-100)10%,transparent)}}.hover\:bg-github-bg-secondary:hover{background-color:var(--color-github-bg-secondary)}.hover\:bg-github-bg-tertiary:hover{background-color:var(--color-github-bg-tertiary)}.hover\:text-github-text-primary:hover{color:var(--color-github-text-primary)}.hover\:opacity-80:hover{opacity:.8}}.focus\:min-h-\[80px\]:focus{min-height:80px}.focus\:border-blue-600:focus{border-color:var(--color-blue-600)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-blue-600\/30:focus{--tw-ring-color:#155dfc4d}@supports (color:color-mix(in lab,red,red)){.focus\:ring-blue-600\/30:focus{--tw-ring-color:color-mix(in oklab,var(--color-blue-600)30%,transparent)}}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.disabled\:opacity-50:disabled{opacity:.5}.\[\&_code\]\:\!bg-transparent code{background-color:#0000!important}.\[\&_code\]\:text-inherit code{color:inherit}.\[\&_pre\]\:m-0 pre{margin:calc(var(--spacing)*0)}.\[\&_pre\]\:\!bg-transparent pre{background-color:#0000!important}.\[\&_pre\]\:p-0 pre{padding:calc(var(--spacing)*0)}.\[\&_pre\]\:text-inherit pre{color:inherit}}html,body{color:#f0f6fc;background-color:#0d1117;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Noto Sans,Helvetica,Arial,sans-serif;font-size:14px;line-height:1.5}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}
@@ -0,0 +1 @@
1
+ (function(s){var e=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:RegExp("@[\\w-](?:"+/[^;{\s"']|\s+(?!\s)/.source+"|"+e.source+")*?"+/(?:;|(?=\s*\{))/.source),inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:{pattern:RegExp(`(^|[{}\\s])[^{}\\s](?:[^{};"'\\s]|\\s+(?![\\s{])|`+e.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:e,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))})(Prism);
@@ -0,0 +1 @@
1
+ Prism.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}};Prism.languages.webmanifest=Prism.languages.json;
@@ -0,0 +1 @@
1
+ (function(e){e.languages.typescript=e.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var a=e.languages.extend("typescript",{});delete a["class-name"],e.languages.typescript["class-name"].inside=a,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:a}}}}),e.languages.ts=e.languages.typescript})(Prism);
@@ -0,0 +1,14 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>ReviewIt - Git Diff Viewer</title>
8
+ <script type="module" crossorigin src="/assets/index-BUtmfbD2.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-mZRIDsXW.css">
10
+ </head>
11
+ <body>
12
+ <div id="root"></div>
13
+ </body>
14
+ </html>
@@ -0,0 +1,13 @@
1
+ import { Comment } from '../types/diff.js';
2
+ export declare class CommentStore {
3
+ private sessionId;
4
+ private filePath;
5
+ private comments;
6
+ constructor(sessionId?: string);
7
+ addComment(file: string, line: number, body: string): Promise<Comment>;
8
+ getComments(): Promise<Comment[]>;
9
+ getCommentsForFile(file: string): Promise<Comment[]>;
10
+ generatePrompt(comment: Comment, diffContent: string): string;
11
+ private saveToFile;
12
+ loadFromFile(): Promise<void>;
13
+ }
@@ -0,0 +1,63 @@
1
+ import { promises as fs } from 'fs';
2
+ import { join, dirname } from 'path';
3
+ export class CommentStore {
4
+ constructor(sessionId) {
5
+ this.comments = new Map();
6
+ this.sessionId = sessionId || Date.now().toString();
7
+ this.filePath = join(process.cwd(), '.reviewit', `tmp-comments-${this.sessionId}.json`);
8
+ }
9
+ async addComment(file, line, body) {
10
+ const comment = {
11
+ id: `${file}:${line}:${Date.now()}`,
12
+ file,
13
+ line,
14
+ body,
15
+ timestamp: new Date().toISOString(),
16
+ };
17
+ this.comments.set(comment.id, comment);
18
+ await this.saveToFile();
19
+ return comment;
20
+ }
21
+ async getComments() {
22
+ return Array.from(this.comments.values());
23
+ }
24
+ async getCommentsForFile(file) {
25
+ return Array.from(this.comments.values()).filter((c) => c.file === file);
26
+ }
27
+ generatePrompt(comment, diffContent) {
28
+ const lines = diffContent.split('\n');
29
+ const contextStart = Math.max(0, comment.line - 3);
30
+ const contextEnd = Math.min(lines.length, comment.line + 3);
31
+ const context = lines.slice(contextStart, contextEnd + 1).join('\n');
32
+ return [
33
+ `📄 ${comment.file} L${comment.line}`,
34
+ '----',
35
+ context,
36
+ '----',
37
+ `コメント: 「${comment.body}」`,
38
+ ].join('\n');
39
+ }
40
+ async saveToFile() {
41
+ try {
42
+ await fs.mkdir(dirname(this.filePath), { recursive: true });
43
+ const data = JSON.stringify(Array.from(this.comments.values()), null, 2);
44
+ await fs.writeFile(this.filePath, data, 'utf8');
45
+ }
46
+ catch (error) {
47
+ console.error('Failed to save comments:', error);
48
+ }
49
+ }
50
+ async loadFromFile() {
51
+ try {
52
+ const data = await fs.readFile(this.filePath, 'utf8');
53
+ const comments = JSON.parse(data);
54
+ this.comments.clear();
55
+ comments.forEach((comment) => {
56
+ this.comments.set(comment.id, comment);
57
+ });
58
+ }
59
+ catch (error) {
60
+ // File doesn't exist or is corrupted, start fresh
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,2 @@
1
+ import type { FileDiff } from '../types/diff.js';
2
+ export declare function loadGitDiff(targetCommitish: string, baseCommitish: string): Promise<FileDiff[]>;
@@ -0,0 +1,95 @@
1
+ import simpleGit from 'simple-git';
2
+ import { validateDiffArguments, createCommitRangeString } from '../cli/utils.js';
3
+ export async function loadGitDiff(targetCommitish, baseCommitish) {
4
+ // Validate arguments
5
+ const validation = validateDiffArguments(targetCommitish, baseCommitish);
6
+ if (!validation.valid) {
7
+ throw new Error(validation.error);
8
+ }
9
+ const git = simpleGit();
10
+ let diff;
11
+ // Handle target special chars (base is always a regular commit)
12
+ if (targetCommitish === 'working') {
13
+ // Show unstaged changes (working vs staged)
14
+ diff = await git.diff(['--name-status']);
15
+ }
16
+ else if (targetCommitish === 'staged') {
17
+ // Show staged changes against base commit
18
+ diff = await git.diff(['--cached', baseCommitish, '--name-status']);
19
+ }
20
+ else if (targetCommitish === '.') {
21
+ // Show all uncommitted changes against base commit
22
+ diff = await git.diff([baseCommitish, '--name-status']);
23
+ }
24
+ else {
25
+ // Both are regular commits: standard commit-to-commit comparison
26
+ diff = await git.diff([
27
+ createCommitRangeString(baseCommitish, targetCommitish),
28
+ '--name-status',
29
+ ]);
30
+ if (!diff.trim()) {
31
+ // Try without parent (for initial commit)
32
+ const diffInitial = await git.diff([targetCommitish, '--name-status']);
33
+ if (!diffInitial.trim()) {
34
+ throw new Error('No changes found in this commit');
35
+ }
36
+ diff = diffInitial;
37
+ }
38
+ }
39
+ const fileChanges = diff
40
+ .split('\n')
41
+ .filter((line) => line.trim())
42
+ .map((line) => {
43
+ const [status, ...pathParts] = line.split('\t');
44
+ const path = pathParts.join('\t');
45
+ return { status, path };
46
+ });
47
+ // Get diff for each file individually
48
+ const fileDiffs = await Promise.all(fileChanges.map(async ({ status, path }) => {
49
+ let fileDiff = '';
50
+ // Handle individual file diffs (base is always a regular commit)
51
+ if (targetCommitish === 'working') {
52
+ // Show unstaged changes (working vs staged)
53
+ fileDiff = await git.diff(['--', path]);
54
+ }
55
+ else if (targetCommitish === 'staged') {
56
+ // Show staged changes against base commit
57
+ fileDiff = await git.diff(['--cached', baseCommitish, '--', path]);
58
+ }
59
+ else if (targetCommitish === '.') {
60
+ // Show all uncommitted changes against base commit
61
+ fileDiff = await git.diff([baseCommitish, '--', path]);
62
+ }
63
+ else {
64
+ try {
65
+ // Both are regular commits: standard commit-to-commit comparison
66
+ fileDiff = await git.diff([
67
+ createCommitRangeString(baseCommitish, targetCommitish),
68
+ '--',
69
+ path,
70
+ ]);
71
+ }
72
+ catch {
73
+ // For new files or if parent doesn't exist
74
+ fileDiff = await git.diff([targetCommitish, '--', path]);
75
+ }
76
+ }
77
+ const lines = fileDiff.split('\n');
78
+ let additions = 0;
79
+ let deletions = 0;
80
+ lines.forEach((line) => {
81
+ if (line.startsWith('+') && !line.startsWith('+++'))
82
+ additions++;
83
+ if (line.startsWith('-') && !line.startsWith('---'))
84
+ deletions++;
85
+ });
86
+ return {
87
+ path,
88
+ status: status,
89
+ diff: fileDiff,
90
+ additions,
91
+ deletions,
92
+ };
93
+ }));
94
+ return fileDiffs;
95
+ }
@@ -0,0 +1,10 @@
1
+ import { DiffResponse } from '../types/diff.js';
2
+ export declare class GitDiffParser {
3
+ private git;
4
+ constructor(repoPath?: string);
5
+ parseDiff(commitish: string): Promise<DiffResponse>;
6
+ private parseUnifiedDiff;
7
+ private parseFileBlock;
8
+ private parseChunks;
9
+ validateCommit(commitish: string): Promise<boolean>;
10
+ }
@@ -0,0 +1,124 @@
1
+ import { simpleGit } from 'simple-git';
2
+ export class GitDiffParser {
3
+ constructor(repoPath = process.cwd()) {
4
+ this.git = simpleGit(repoPath);
5
+ }
6
+ async parseDiff(commitish) {
7
+ try {
8
+ const diffSummary = await this.git.diffSummary([`${commitish}^`, commitish]);
9
+ const diffRaw = await this.git.diff([`${commitish}^`, commitish]);
10
+ const files = await this.parseUnifiedDiff(diffRaw, diffSummary.files);
11
+ return {
12
+ commit: commitish,
13
+ files,
14
+ };
15
+ }
16
+ catch (error) {
17
+ throw new Error(`Failed to parse diff for ${commitish}: ${error instanceof Error ? error.message : 'Unknown error'}`);
18
+ }
19
+ }
20
+ async parseUnifiedDiff(diffText, summary) {
21
+ const files = [];
22
+ const fileBlocks = diffText.split(/^diff --git /m).slice(1);
23
+ for (let i = 0; i < fileBlocks.length; i++) {
24
+ const block = `diff --git ${fileBlocks[i]}`;
25
+ const summaryItem = summary[i];
26
+ if (!summaryItem)
27
+ continue;
28
+ const file = this.parseFileBlock(block, summaryItem);
29
+ if (file) {
30
+ files.push(file);
31
+ }
32
+ }
33
+ return files;
34
+ }
35
+ parseFileBlock(block, summary) {
36
+ const lines = block.split('\n');
37
+ const headerLine = lines[0];
38
+ const pathMatch = headerLine.match(/^diff --git a\/(.+) b\/(.+)$/);
39
+ if (!pathMatch)
40
+ return null;
41
+ const oldPath = pathMatch[1];
42
+ const newPath = pathMatch[2];
43
+ const path = newPath;
44
+ let status = 'modified';
45
+ if (summary.binary)
46
+ return null;
47
+ if (oldPath !== newPath) {
48
+ status = 'renamed';
49
+ }
50
+ else if (summary.insertions && !summary.deletions) {
51
+ status = 'added';
52
+ }
53
+ else if (summary.deletions && !summary.insertions) {
54
+ status = 'deleted';
55
+ }
56
+ const chunks = this.parseChunks(lines);
57
+ return {
58
+ path,
59
+ oldPath: oldPath !== newPath ? oldPath : undefined,
60
+ status,
61
+ additions: summary.insertions || 0,
62
+ deletions: summary.deletions || 0,
63
+ chunks,
64
+ };
65
+ }
66
+ parseChunks(lines) {
67
+ const chunks = [];
68
+ let currentChunk = null;
69
+ let oldLineNum = 0;
70
+ let newLineNum = 0;
71
+ for (const line of lines) {
72
+ if (line.startsWith('@@')) {
73
+ if (currentChunk) {
74
+ chunks.push(currentChunk);
75
+ }
76
+ const match = line.match(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)/);
77
+ if (match) {
78
+ const oldStart = parseInt(match[1]);
79
+ const oldLines = parseInt(match[2] || '1');
80
+ const newStart = parseInt(match[3]);
81
+ const newLines = parseInt(match[4] || '1');
82
+ oldLineNum = oldStart;
83
+ newLineNum = newStart;
84
+ currentChunk = {
85
+ header: line,
86
+ oldStart,
87
+ oldLines,
88
+ newStart,
89
+ newLines,
90
+ lines: [],
91
+ };
92
+ }
93
+ }
94
+ else if (currentChunk &&
95
+ (line.startsWith('+') || line.startsWith('-') || line.startsWith(' '))) {
96
+ const type = line.startsWith('+') ? 'add' : line.startsWith('-') ? 'delete' : 'normal';
97
+ const diffLine = {
98
+ type,
99
+ content: line.slice(1),
100
+ oldLineNumber: type !== 'add' ? oldLineNum : undefined,
101
+ newLineNumber: type !== 'delete' ? newLineNum : undefined,
102
+ };
103
+ currentChunk.lines.push(diffLine);
104
+ if (type !== 'add')
105
+ oldLineNum++;
106
+ if (type !== 'delete')
107
+ newLineNum++;
108
+ }
109
+ }
110
+ if (currentChunk) {
111
+ chunks.push(currentChunk);
112
+ }
113
+ return chunks;
114
+ }
115
+ async validateCommit(commitish) {
116
+ try {
117
+ await this.git.show([commitish, '--name-only']);
118
+ return true;
119
+ }
120
+ catch {
121
+ return false;
122
+ }
123
+ }
124
+ }
@@ -0,0 +1 @@
1
+ export {};