git-viewer 7.0.0 → 9.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.
@@ -1597,7 +1597,8 @@ var state = {
1597
1597
  diff: null,
1598
1598
  filter: "all",
1599
1599
  search: "",
1600
- loading: true
1600
+ loading: true,
1601
+ fullscreenDiff: false
1601
1602
  };
1602
1603
  var updateApp;
1603
1604
  async function fetchRefs() {
@@ -1645,6 +1646,17 @@ async function selectCommit(commit) {
1645
1646
  state.diff = await fetchDiff(commit.sha);
1646
1647
  updateApp();
1647
1648
  }
1649
+ function toggleFullscreenDiff(open) {
1650
+ if (!document.startViewTransition) {
1651
+ state.fullscreenDiff = open;
1652
+ updateApp();
1653
+ return;
1654
+ }
1655
+ document.startViewTransition(() => {
1656
+ state.fullscreenDiff = open;
1657
+ updateApp();
1658
+ });
1659
+ }
1648
1660
  var colors = {
1649
1661
  bg: "#ffffff",
1650
1662
  bgLight: "#f6f8fa",
@@ -1711,9 +1723,6 @@ function Sidebar() {
1711
1723
  "div",
1712
1724
  {
1713
1725
  css: {
1714
- minWidth: "180px",
1715
- maxWidth: "300px",
1716
- width: "fit-content",
1717
1726
  borderRight: `1px solid ${colors.border}`,
1718
1727
  display: "flex",
1719
1728
  flexDirection: "column",
@@ -1725,7 +1734,6 @@ function Sidebar() {
1725
1734
  {
1726
1735
  css: {
1727
1736
  padding: "12px",
1728
- borderBottom: `1px solid ${colors.border}`,
1729
1737
  fontWeight: 600,
1730
1738
  fontSize: "11px",
1731
1739
  textTransform: "uppercase",
@@ -1837,7 +1845,7 @@ function RefNodeItem(handle) {
1837
1845
  },
1838
1846
  on: { click: () => setFilter(node.fullName) },
1839
1847
  children: [
1840
- node.current && "\u25CF ",
1848
+ node.current && /* @__PURE__ */ jsx("span", { css: { fontSize: "8px", marginRight: "4px" }, children: "\u25CF" }),
1841
1849
  node.name
1842
1850
  ]
1843
1851
  }
@@ -2125,7 +2133,20 @@ function CommitRow() {
2125
2133
  };
2126
2134
  }
2127
2135
  function DiffPanel() {
2136
+ let diffContentRef;
2137
+ function scrollToFile(path) {
2138
+ if (!diffContentRef || !path) return;
2139
+ let fileHeaders = diffContentRef.querySelectorAll(".d2h-file-header");
2140
+ for (let header of fileHeaders) {
2141
+ let nameEl = header.querySelector(".d2h-file-name");
2142
+ if (nameEl?.textContent?.includes(path)) {
2143
+ header.scrollIntoView({ block: "start" });
2144
+ break;
2145
+ }
2146
+ }
2147
+ }
2128
2148
  return () => {
2149
+ let isFullscreen = state.fullscreenDiff;
2129
2150
  if (!state.selectedCommit) {
2130
2151
  return /* @__PURE__ */ jsx(
2131
2152
  "div",
@@ -2149,64 +2170,333 @@ function DiffPanel() {
2149
2170
  flex: 1,
2150
2171
  display: "flex",
2151
2172
  flexDirection: "column",
2152
- background: colors.bgLight
2173
+ background: colors.bgLight,
2174
+ viewTransitionName: "diff-panel",
2175
+ ...isFullscreen ? {
2176
+ position: "fixed",
2177
+ top: 0,
2178
+ left: 0,
2179
+ right: 0,
2180
+ bottom: 0,
2181
+ zIndex: 100
2182
+ } : {}
2153
2183
  },
2154
2184
  children: [
2155
2185
  /* @__PURE__ */ jsx(
2156
2186
  "div",
2157
2187
  {
2158
- css: { padding: "12px", borderBottom: `1px solid ${colors.border}` },
2188
+ css: {
2189
+ padding: "12px",
2190
+ borderBottom: `1px solid ${colors.border}`,
2191
+ display: "flex",
2192
+ alignItems: "flex-start",
2193
+ justifyContent: "space-between",
2194
+ gap: "12px",
2195
+ background: colors.bgLight
2196
+ },
2159
2197
  children: [
2160
- /* @__PURE__ */ jsx("div", { css: { fontWeight: 600, marginBottom: "4px" }, children: state.selectedCommit.subject }),
2161
- /* @__PURE__ */ jsx("div", { css: { fontSize: "12px", color: colors.textMuted }, children: [
2162
- /* @__PURE__ */ jsx("span", { children: state.selectedCommit.author }),
2163
- /* @__PURE__ */ jsx("span", { css: { margin: "0 8px" }, children: "\u2022" }),
2164
- /* @__PURE__ */ jsx("span", { children: state.selectedCommit.date }),
2165
- /* @__PURE__ */ jsx("span", { css: { margin: "0 8px" }, children: "\u2022" }),
2166
- /* @__PURE__ */ jsx("code", { css: { color: colors.accent }, children: state.selectedCommit.shortSha })
2167
- ] })
2198
+ /* @__PURE__ */ jsx("div", { css: { flex: 1, minWidth: 0 }, children: [
2199
+ /* @__PURE__ */ jsx("div", { css: { fontWeight: 600, marginBottom: "4px" }, children: state.selectedCommit.subject }),
2200
+ /* @__PURE__ */ jsx("div", { css: { fontSize: "12px", color: colors.textMuted }, children: [
2201
+ /* @__PURE__ */ jsx("span", { children: state.selectedCommit.author }),
2202
+ /* @__PURE__ */ jsx("span", { css: { margin: "0 8px" }, children: "\u2022" }),
2203
+ /* @__PURE__ */ jsx("span", { children: state.selectedCommit.date }),
2204
+ /* @__PURE__ */ jsx("span", { css: { margin: "0 8px" }, children: "\u2022" }),
2205
+ /* @__PURE__ */ jsx("code", { css: { color: colors.accent }, children: state.selectedCommit.shortSha }),
2206
+ state.diff && /* @__PURE__ */ jsx(Fragment, { children: [
2207
+ /* @__PURE__ */ jsx("span", { css: { margin: "0 8px" }, children: "\u2022" }),
2208
+ /* @__PURE__ */ jsx("span", { children: [
2209
+ state.diff.files.length,
2210
+ " file",
2211
+ state.diff.files.length !== 1 ? "s" : ""
2212
+ ] })
2213
+ ] })
2214
+ ] }),
2215
+ state.selectedCommit.body && /* @__PURE__ */ jsx(
2216
+ "div",
2217
+ {
2218
+ css: {
2219
+ marginTop: "8px",
2220
+ whiteSpace: "pre-wrap",
2221
+ fontSize: "12px",
2222
+ lineHeight: "1.4"
2223
+ },
2224
+ children: state.selectedCommit.body
2225
+ }
2226
+ )
2227
+ ] }),
2228
+ state.diff && /* @__PURE__ */ jsx(
2229
+ "button",
2230
+ {
2231
+ css: {
2232
+ display: "flex",
2233
+ alignItems: "center",
2234
+ gap: "6px",
2235
+ padding: "6px 12px",
2236
+ border: `1px solid ${colors.border}`,
2237
+ borderRadius: "4px",
2238
+ background: colors.bg,
2239
+ color: colors.text,
2240
+ fontSize: "12px",
2241
+ cursor: "pointer",
2242
+ whiteSpace: "nowrap",
2243
+ "&:hover": {
2244
+ background: colors.bgLighter,
2245
+ borderColor: colors.accent
2246
+ }
2247
+ },
2248
+ on: { click: () => toggleFullscreenDiff(!isFullscreen) },
2249
+ children: isFullscreen ? /* @__PURE__ */ jsx(Fragment, { children: [
2250
+ /* @__PURE__ */ jsx(
2251
+ "svg",
2252
+ {
2253
+ width: "14",
2254
+ height: "14",
2255
+ viewBox: "0 0 24 24",
2256
+ fill: "none",
2257
+ stroke: "currentColor",
2258
+ "stroke-width": "2",
2259
+ children: /* @__PURE__ */ jsx("path", { d: "M4 14h6v6m10-10h-6V4m0 6 7-7M3 21l7-7" })
2260
+ }
2261
+ ),
2262
+ "Collapse"
2263
+ ] }) : /* @__PURE__ */ jsx(Fragment, { children: [
2264
+ /* @__PURE__ */ jsx(
2265
+ "svg",
2266
+ {
2267
+ width: "14",
2268
+ height: "14",
2269
+ viewBox: "0 0 24 24",
2270
+ fill: "none",
2271
+ stroke: "currentColor",
2272
+ "stroke-width": "2",
2273
+ children: /* @__PURE__ */ jsx("path", { d: "M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3" })
2274
+ }
2275
+ ),
2276
+ "Expand"
2277
+ ] })
2278
+ }
2279
+ )
2168
2280
  ]
2169
2281
  }
2170
2282
  ),
2171
- /* @__PURE__ */ jsx("div", { css: { flex: 1, overflow: "auto" }, children: state.diff ? /* @__PURE__ */ jsx(
2172
- "section",
2173
- {
2174
- css: {
2175
- "& .d2h-wrapper": { background: "transparent" },
2176
- "& .d2h-file-header": {
2177
- background: colors.bgLighter,
2178
- borderBottom: `1px solid ${colors.border}`,
2179
- padding: "8px 12px"
2283
+ /* @__PURE__ */ jsx("div", { css: { flex: 1, display: "flex", overflow: "hidden" }, children: [
2284
+ state.diff && state.diff.files.length > 0 && /* @__PURE__ */ jsx(
2285
+ "div",
2286
+ {
2287
+ css: {
2288
+ borderRight: `1px solid ${colors.border}`,
2289
+ display: "flex",
2290
+ flexDirection: "column",
2291
+ background: colors.bg,
2292
+ overflow: "hidden"
2180
2293
  },
2181
- "& .d2h-file-name": { color: colors.text },
2182
- "& .d2h-code-line": { padding: "0 8px" },
2183
- "& .d2h-code-line-ctn": { color: colors.text },
2184
- "& .d2h-ins": { background: "#dafbe1" },
2185
- "& .d2h-del": { background: "#ffebe9" },
2186
- "& .d2h-ins .d2h-code-line-ctn": { color: colors.green },
2187
- "& .d2h-del .d2h-code-line-ctn": { color: colors.red },
2188
- "& .d2h-code-linenumber": {
2189
- color: colors.textMuted,
2190
- borderRight: `1px solid ${colors.border}`
2294
+ children: [
2295
+ /* @__PURE__ */ jsx(
2296
+ "div",
2297
+ {
2298
+ css: {
2299
+ padding: "8px 12px",
2300
+ fontSize: "11px",
2301
+ fontWeight: 600,
2302
+ textTransform: "uppercase",
2303
+ letterSpacing: "0.5px",
2304
+ color: colors.textMuted,
2305
+ borderBottom: `1px solid ${colors.border}`
2306
+ },
2307
+ children: "Changed Files"
2308
+ }
2309
+ ),
2310
+ /* @__PURE__ */ jsx("div", { css: { flex: 1, overflow: "auto", padding: "4px 0" }, children: state.diff.files.map((file) => /* @__PURE__ */ jsx(
2311
+ FileListItem,
2312
+ {
2313
+ file,
2314
+ onSelect: () => scrollToFile(file.path)
2315
+ },
2316
+ file.path
2317
+ )) })
2318
+ ]
2319
+ }
2320
+ ),
2321
+ /* @__PURE__ */ jsx("div", { css: { flex: 1, overflow: "auto" }, children: state.diff ? /* @__PURE__ */ jsx(
2322
+ "section",
2323
+ {
2324
+ connect: (node) => diffContentRef = node,
2325
+ css: {
2326
+ "& .d2h-wrapper": { background: "transparent" },
2327
+ "& .d2h-file-header": {
2328
+ background: colors.bgLighter,
2329
+ borderBottom: `1px solid ${colors.border}`,
2330
+ padding: "8px 12px",
2331
+ position: "sticky",
2332
+ top: 0,
2333
+ zIndex: 1
2334
+ },
2335
+ "& .d2h-file-name": { color: colors.text },
2336
+ "& .d2h-code-line": { padding: "0 8px" },
2337
+ "& .d2h-code-line-ctn": { color: colors.text },
2338
+ "& .d2h-ins": { background: "#dafbe1" },
2339
+ "& .d2h-del": { background: "#ffebe9" },
2340
+ "& .d2h-ins .d2h-code-line-ctn": { color: colors.green },
2341
+ "& .d2h-del .d2h-code-line-ctn": { color: colors.red },
2342
+ "& .d2h-code-linenumber": {
2343
+ color: colors.textMuted,
2344
+ borderRight: `1px solid ${colors.border}`
2345
+ },
2346
+ "& .d2h-file-diff": {
2347
+ borderBottom: `1px solid ${colors.border}`
2348
+ },
2349
+ "& .d2h-diff-tbody": { position: "relative" }
2191
2350
  },
2192
- "& .d2h-file-diff": {
2193
- borderBottom: `1px solid ${colors.border}`
2351
+ innerHTML: state.diff.diffHtml
2352
+ }
2353
+ ) : /* @__PURE__ */ jsx(
2354
+ "div",
2355
+ {
2356
+ css: {
2357
+ padding: "20px",
2358
+ textAlign: "center",
2359
+ color: colors.textMuted
2194
2360
  },
2195
- "& .d2h-diff-tbody": { position: "relative" }
2361
+ children: "Loading diff..."
2362
+ }
2363
+ ) })
2364
+ ] })
2365
+ ]
2366
+ }
2367
+ );
2368
+ };
2369
+ }
2370
+ function FileListItem() {
2371
+ return ({ file, onSelect }) => {
2372
+ let displayName = file.path.split("/").pop() ?? file.path;
2373
+ let fullPath = file.path;
2374
+ return /* @__PURE__ */ jsx(
2375
+ "div",
2376
+ {
2377
+ css: {
2378
+ padding: "6px 12px",
2379
+ cursor: "pointer",
2380
+ "&:hover": {
2381
+ background: colors.bgLighter
2382
+ }
2383
+ },
2384
+ on: { click: onSelect },
2385
+ children: [
2386
+ /* @__PURE__ */ jsx(
2387
+ "div",
2388
+ {
2389
+ css: {
2390
+ display: "flex",
2391
+ alignItems: "center",
2392
+ gap: "8px"
2196
2393
  },
2197
- innerHTML: state.diff.diffHtml
2394
+ children: [
2395
+ /* @__PURE__ */ jsx(
2396
+ "span",
2397
+ {
2398
+ css: {
2399
+ display: "flex",
2400
+ alignItems: "center",
2401
+ gap: "2px",
2402
+ fontSize: "10px",
2403
+ fontWeight: 500,
2404
+ minWidth: "50px"
2405
+ },
2406
+ children: [
2407
+ file.additions > 0 && /* @__PURE__ */ jsx("span", { css: { color: colors.green }, children: [
2408
+ "+",
2409
+ file.additions
2410
+ ] }),
2411
+ file.deletions > 0 && /* @__PURE__ */ jsx("span", { css: { color: colors.red }, children: [
2412
+ "-",
2413
+ file.deletions
2414
+ ] })
2415
+ ]
2416
+ }
2417
+ ),
2418
+ /* @__PURE__ */ jsx(
2419
+ "span",
2420
+ {
2421
+ css: {
2422
+ flex: 1,
2423
+ overflow: "hidden",
2424
+ textOverflow: "ellipsis",
2425
+ whiteSpace: "nowrap",
2426
+ fontSize: "12px"
2427
+ },
2428
+ title: fullPath,
2429
+ children: [
2430
+ file.isNew && /* @__PURE__ */ jsx(
2431
+ "span",
2432
+ {
2433
+ css: {
2434
+ display: "inline-block",
2435
+ padding: "1px 4px",
2436
+ marginRight: "6px",
2437
+ borderRadius: "3px",
2438
+ background: colors.green,
2439
+ color: "#fff",
2440
+ fontSize: "9px",
2441
+ fontWeight: 600
2442
+ },
2443
+ children: "NEW"
2444
+ }
2445
+ ),
2446
+ file.isDeleted && /* @__PURE__ */ jsx(
2447
+ "span",
2448
+ {
2449
+ css: {
2450
+ display: "inline-block",
2451
+ padding: "1px 4px",
2452
+ marginRight: "6px",
2453
+ borderRadius: "3px",
2454
+ background: colors.red,
2455
+ color: "#fff",
2456
+ fontSize: "9px",
2457
+ fontWeight: 600
2458
+ },
2459
+ children: "DEL"
2460
+ }
2461
+ ),
2462
+ file.isRenamed && /* @__PURE__ */ jsx(
2463
+ "span",
2464
+ {
2465
+ css: {
2466
+ display: "inline-block",
2467
+ padding: "1px 4px",
2468
+ marginRight: "6px",
2469
+ borderRadius: "3px",
2470
+ background: colors.accent,
2471
+ color: "#fff",
2472
+ fontSize: "9px",
2473
+ fontWeight: 600
2474
+ },
2475
+ children: "REN"
2476
+ }
2477
+ ),
2478
+ displayName
2479
+ ]
2480
+ }
2481
+ )
2482
+ ]
2198
2483
  }
2199
- ) : /* @__PURE__ */ jsx(
2484
+ ),
2485
+ fullPath !== displayName && /* @__PURE__ */ jsx(
2200
2486
  "div",
2201
2487
  {
2202
2488
  css: {
2203
- padding: "20px",
2204
- textAlign: "center",
2205
- color: colors.textMuted
2489
+ fontSize: "10px",
2490
+ color: colors.textMuted,
2491
+ marginTop: "2px",
2492
+ marginLeft: "58px",
2493
+ overflow: "hidden",
2494
+ textOverflow: "ellipsis",
2495
+ whiteSpace: "nowrap"
2206
2496
  },
2207
- children: "Loading diff..."
2497
+ children: fullPath
2208
2498
  }
2209
- ) })
2499
+ )
2210
2500
  ]
2211
2501
  }
2212
2502
  );
package/dist/index.html CHANGED
@@ -13,6 +13,38 @@
13
13
  height: 100%;
14
14
  overflow: hidden;
15
15
  }
16
+
17
+ /* View Transition Styles */
18
+ @view-transition {
19
+ navigation: auto;
20
+ }
21
+
22
+ /* Diff panel morphs between positions */
23
+ ::view-transition-old(diff-panel),
24
+ ::view-transition-new(diff-panel) {
25
+ animation-duration: 0.35s;
26
+ animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
27
+ }
28
+
29
+ /* Make the old and new states crossfade while morphing */
30
+ ::view-transition-old(diff-panel) {
31
+ animation: none;
32
+ }
33
+
34
+ ::view-transition-new(diff-panel) {
35
+ animation: none;
36
+ }
37
+
38
+ /* The group handles the position/size morphing automatically */
39
+ ::view-transition-group(diff-panel) {
40
+ animation-duration: 0.35s;
41
+ animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
42
+ }
43
+
44
+ /* Image pair handles crossfade */
45
+ ::view-transition-image-pair(diff-panel) {
46
+ isolation: auto;
47
+ }
16
48
  </style>
17
49
  </head>
18
50
  <body>
package/dist/server.js CHANGED
@@ -8827,11 +8827,11 @@ if (!repoDir) {
8827
8827
  process.exit(1);
8828
8828
  }
8829
8829
  async function git(args) {
8830
- let { stdout } = await exec(`git ${args}`, {
8830
+ let { stdout } = await exec(`git -c color.ui=never ${args}`, {
8831
8831
  cwd: repoDir,
8832
8832
  maxBuffer: 10 * 1024 * 1024
8833
8833
  });
8834
- return stdout.trim();
8834
+ return stdout.trimEnd();
8835
8835
  }
8836
8836
  async function getCurrentBranch() {
8837
8837
  return git("rev-parse --abbrev-ref HEAD");
@@ -8854,11 +8854,11 @@ async function getRefs() {
8854
8854
  }
8855
8855
  let remotes = {};
8856
8856
  for (let [remote, branches] of Object.entries(remotesByOrigin)) {
8857
- remotes[remote] = buildTree(branches);
8857
+ remotes[remote] = buildTree(branches, void 0, `${remote}/`);
8858
8858
  }
8859
8859
  return { local, remotes, currentBranch };
8860
8860
  }
8861
- function buildTree(branches, currentBranch) {
8861
+ function buildTree(branches, currentBranch, prefix = "") {
8862
8862
  let root = [];
8863
8863
  let sorted = [...branches].sort((a, b) => {
8864
8864
  let aHasSlash = a.includes("/");
@@ -8868,7 +8868,7 @@ function buildTree(branches, currentBranch) {
8868
8868
  });
8869
8869
  for (let branch of sorted) {
8870
8870
  let parts = branch.split("/");
8871
- insertIntoTree(root, parts, branch, currentBranch);
8871
+ insertIntoTree(root, parts, prefix + branch, currentBranch);
8872
8872
  }
8873
8873
  return root;
8874
8874
  }
@@ -8893,21 +8893,22 @@ function insertIntoTree(nodes, parts, fullName, currentBranch) {
8893
8893
  insertIntoTree(folder.children, rest, fullName, currentBranch);
8894
8894
  }
8895
8895
  async function getCommits(ref, search) {
8896
- let format = "%H%x00%h%x00%s%x00%an%x00%ai%x00%P%x00%D";
8897
- let args = `log --format="${format}" -n 500`;
8896
+ let format = "%H%x1f%h%x1f%s%x1f%b%x1f%an%x1f%ai%x1f%P%x1f%D";
8897
+ let args = `log -z --format="${format}" -n 500`;
8898
8898
  if (ref && ref !== "all") {
8899
8899
  args += ` ${ref}`;
8900
8900
  } else {
8901
8901
  args += " --all";
8902
8902
  }
8903
8903
  let output = await git(args);
8904
- let lines = output ? output.split("\n").filter(Boolean) : [];
8905
- let rawCommits = lines.map((line) => {
8906
- let [sha, shortSha, subject, author, date, parents, refs] = line.split("\0");
8904
+ let records = output ? output.split("\0").filter(Boolean) : [];
8905
+ let rawCommits = records.map((record) => {
8906
+ let [sha, shortSha, subject, body, author, date, parents, refs] = record.split("");
8907
8907
  return {
8908
8908
  sha,
8909
8909
  shortSha,
8910
8910
  subject,
8911
+ body: body ? body.trimEnd() : "",
8911
8912
  author,
8912
8913
  date: formatDate(date),
8913
8914
  parents: parents ? parents.split(" ").filter(Boolean) : [],
@@ -8917,9 +8918,13 @@ async function getCommits(ref, search) {
8917
8918
  let filteredCommits = rawCommits;
8918
8919
  if (search) {
8919
8920
  let query = search.toLowerCase();
8920
- filteredCommits = rawCommits.filter(
8921
- (c) => c.subject.toLowerCase().includes(query) || c.author.toLowerCase().includes(query) || c.sha.toLowerCase().includes(query)
8922
- );
8921
+ filteredCommits = rawCommits.filter((c) => {
8922
+ let haystack = `${c.subject}
8923
+ ${c.body}
8924
+ ${c.author}
8925
+ ${c.sha}`;
8926
+ return haystack.toLowerCase().includes(query);
8927
+ });
8923
8928
  }
8924
8929
  let { commits, maxLane } = computeGraph(filteredCommits);
8925
8930
  return { commits, maxLane };
@@ -9029,11 +9034,22 @@ function formatDate(date) {
9029
9034
  });
9030
9035
  }
9031
9036
  async function getDiff(sha) {
9032
- let format = "%H%x00%h%x00%s%x00%an%x00%ai%x00%P";
9033
- let metaOutput = await git(`show --format="${format}" -s ${sha}`);
9034
- let [fullSha, shortSha, subject, author, date, parents] = metaOutput.split("\0");
9037
+ let format = "%H%x1f%h%x1f%s%x1f%b%x1f%an%x1f%ai%x1f%P";
9038
+ let metaOutput = await git(`show -z --format="${format}" -s ${sha}`);
9039
+ let [record] = metaOutput.split("\0");
9040
+ let [fullSha, shortSha, subject, body, author, date, parents] = record.split("");
9035
9041
  let diffOutput = await git(`show --format="" ${sha}`);
9036
- let diffHtml = (0, import_diff2html.html)((0, import_diff2html.parse)(diffOutput), {
9042
+ let parsedDiff = (0, import_diff2html.parse)(diffOutput);
9043
+ let files = parsedDiff.map((file) => ({
9044
+ path: file.newName || file.oldName || "",
9045
+ oldPath: file.isRename ? file.oldName : void 0,
9046
+ additions: file.addedLines,
9047
+ deletions: file.deletedLines,
9048
+ isNew: file.isNew || false,
9049
+ isDeleted: file.isDeleted || false,
9050
+ isRenamed: file.isRename || false
9051
+ }));
9052
+ let diffHtml = (0, import_diff2html.html)(parsedDiff, {
9037
9053
  drawFileList: false,
9038
9054
  outputFormat: "line-by-line",
9039
9055
  matching: "lines"
@@ -9042,10 +9058,12 @@ async function getDiff(sha) {
9042
9058
  sha: fullSha,
9043
9059
  shortSha,
9044
9060
  subject,
9061
+ body: body ? body.trimEnd() : "",
9045
9062
  author,
9046
9063
  date: formatDate(date),
9047
9064
  parents: parents ? parents.split(" ").filter(Boolean) : [],
9048
- diffHtml
9065
+ diffHtml,
9066
+ files
9049
9067
  };
9050
9068
  }
9051
9069
  var packageDir = import.meta.dirname;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "git-viewer",
3
- "version": "7.0.0",
3
+ "version": "9.0.0",
4
4
  "description": "Visual git log viewer with branch graph and diff display",
5
5
  "repository": {
6
6
  "type": "git",