difftab 0.1.3 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -37,14 +37,17 @@ Running it again in the same repository reuses the running instance.
37
37
  - **Diffs, lazily** — click a file to load its patch, rendered by
38
38
  [diff2html](https://diff2html.xyz/) + highlight.js in a VS Code-like theme, side by side
39
39
  until the pane gets too narrow.
40
+ - **File tree** — a second sidebar tab browses the whole repository rather than only what
41
+ changed: tracked, untracked and ignored files (the ignored ones dimmed), loaded one
42
+ directory at a time. Click any file to read it, highlighted by the same theme.
40
43
  - **Branch status** — branch name, ahead/behind counts, "no upstream", detached HEAD, and
41
44
  an in-progress rebase / merge / cherry-pick / revert / bisect / `git am`.
42
45
  - **Auto-refresh** — a file watcher pushes changes over SSE, falling back to polling where
43
46
  recursive watching would exhaust the inotify quota (and saying so in the UI).
44
47
  - **Exits on its own** — 45 seconds after the last tab closes.
45
- - **Cheap to run** — about 30 ms from launch to a listening server, well inside the 300 ms
48
+ - **Cheap to run** — about 40 ms from launch to a listening server, well inside the 300 ms
46
49
  budget CI enforces on every commit across nine Node × OS combinations; the JS bundle is
47
- 68 KB gzipped.
50
+ 71 KB gzipped.
48
51
 
49
52
  Empty repositories, interrupted rebases, linked worktrees, submodules, binary and >5 MB
50
53
  files, renames, and paths with spaces, quotes, CJK or emoji are handled explicitly.
package/README.zh-CN.md CHANGED
@@ -32,11 +32,12 @@ npx difftab
32
32
 
33
33
  - **变更列表**——已暂存、未暂存、未跟踪、冲突四组,未跟踪的目录展开到文件粒度。
34
34
  - **按文件懒加载的 diff**——点开某个文件才取它的补丁,渲染用 [diff2html](https://diff2html.xyz/) + highlight.js,配色仿 VS Code,面板窄到放不下两列时自动切成逐行。
35
+ - **文件树**——侧栏第二个 tab 浏览整个仓库,而不只是改动过的那些:已跟踪、未跟踪与被忽略的文件(后者灰显),按目录懒加载。点任一文件在右侧只读查看,高亮复用同一套配色。
35
36
  - **分支状态**——当前分支、ahead/behind 计数、无上游、游离 HEAD,以及进行中的 rebase /
36
37
  merge / cherry-pick / revert / bisect / `git am`。
37
38
  - **自动刷新**——文件监听经 SSE 推到前端;递归监听会耗尽 inotify 配额的场合改用轮询,并在界面上标注。
38
39
  - **自己退出**——最后一个标签页关掉 45 秒后自动退。
39
- - **跑起来很轻**——从启动到端口就绪约 30ms,远在 CI 每次提交都验的 300ms 预算之内(九个 Node × 平台组合各跑一遍);打包后的 JS gzip 68KB。
40
+ - **跑起来很轻**——从启动到端口就绪约 40ms,远在 CI 每次提交都验的 300ms 预算之内(九个 Node × 平台组合各跑一遍);打包后的 JS gzip 71KB。
40
41
 
41
42
  空仓库、停在中途的 rebase、linked worktree、submodule、二进制与超过 5MB 的文件、重命名,以及带空格、引号、中日韩文字或 emoji 的路径,都是被显式处理的。
42
43
 
package/bin/difftab.js CHANGED
@@ -1,51 +1,43 @@
1
1
  #!/usr/bin/env node
2
- // difftab CLI 入口 —— 版本守卫。
2
+ // difftab CLI 入口——版本守卫。
3
3
  //
4
- // 本文件手写维护,不参与 TypeScript 编译、不作为任何打包入口。
5
- // 一旦它进了构建管线,就可能被注入超出 Node 22 的语法或被合并进主模块,
6
- // 低于下限的用户拿到的将是解析期 SyntaxError —— 守卫在解析期即失效。
4
+ // 本文件手写维护,不参与 TypeScript 编译、不作为任何打包入口:一旦它进了构建管线,就可能被
5
+ // 注入超出 Node 22 的语法或被合并进主模块,低于下限的用户拿到的将是解析期 SyntaxError——
6
+ // 守卫在解析期即失效。因此这里只用「保守语法」:ES2015 之内,不使用可选链 / 空值合并 /
7
+ // 顶层 await / class 字段等更晚的语法。守卫通过后,才动态 import 主模块。
7
8
  //
8
- // 因此这里只用「保守语法」:ES2015 之内,不使用可选链 / 空值合并 /
9
- // 顶层 await / class 字段等更晚的语法。守卫通过后,才动态 import 主模块。
10
- //
11
- // `node:fs` 是**内建模块**,静态 import 它不违反上面那条 —— 守卫要防的是「解析期就
12
- // 炸掉」与「把主模块的新语法拖进来」,而内建模块两条都不沾,且在 Node 12 起就支持
13
- // `node:` 前缀。写成静态 import 而不是在分支里动态 import:那条路要么 `await`
14
- // (顶层 await 正是禁项),要么把报错塞进 `.then()` 回调里,而回调里的 `process.exit()`
15
- // 与本文件要修的问题是同一类。
9
+ // `node:fs` 是**内建模块**,静态 import 它不违反上面那条——守卫要防的是解析期就炸掉与把
10
+ // 主模块的新语法拖进来,而内建模块两条都不沾。写成静态 import 是因为动态那条要么 `await`
11
+ // (顶层 await 正是禁项)、要么把报错塞进 `.then()` 回调里。
16
12
 
17
13
  import { writeSync } from 'node:fs';
18
14
 
19
15
  /**
20
- * 退出前的报错**一律 `writeSync(2, …)`**(红线)。
21
- *
22
- * `process.stderr.write(…)` + `process.exit()` 在 Windows 上写**管道**时是异步的,
23
- * 整条消息会被丢掉 —— 症状是 stderr 全空、只剩一个退出码。而**文件重定向看不出
24
- * 区别**(那条是同步写),所以门禁那侧必须经管道取回 stderr,见 CI 的 old-node-guard。
16
+ * 退出前的报错**一律 `writeSync(2, …)`**。`process.stderr.write(…)` + `process.exit()` 在
17
+ * Windows 上写**管道**时是异步的,整条消息会被丢掉——症状是 stderr 全空、只剩一个退出码,
18
+ * 而**文件重定向看不出区别**(那条是同步写),所以门禁那侧必须经管道取回 stderr。
25
19
  *
26
- * try/catch 是因为读端可能先走(`difftab | head -1`):此刻要报的是别的事,
27
- * 不该被一个 EPIPE 顶掉。
20
+ * try/catch 是因为读端可能先走(`difftab | head -1`):此刻要报的是别的事,不该被 EPIPE 顶掉。
28
21
  */
29
22
  function writeStderr(message) {
30
23
  try {
31
24
  writeSync(2, message);
32
25
  } catch (_cause) {
33
- // 报不出来就算了 —— 退出码仍然是对的。
34
- // 绑定写成 `_cause` 而不是省略:可选 catch 绑定是 ES2019,本文件只用 ES2015
26
+ // 报不出来就算了——退出码仍然是对的。
27
+ // 绑定写成 `_cause` 而不是省略:可选 catch 绑定是 ES2019,本文件只用 ES2015
35
28
  }
36
29
  }
37
30
 
38
- // 下限只写一次。写成两个常量时,把 MIN_MAJOR 提到 24 却忘了改 MIN_VERSION,
39
- // 结果是守卫正确地拒掉 Node 22、却告诉用户「requires Node.js 22.0.0 or newer,
40
- // but this is v22.5.0」—— 没有任何门禁会因此变红。
41
- // 与 package.json 的 engines.node 对齐由冒烟测试断言。
31
+ // 下限只写一次。写成两个常量时,把 MIN_MAJOR 提到 24 却忘了改 MIN_VERSION,结果是守卫正确
32
+ // 地拒掉 Node 22、却告诉用户「requires Node.js 22.0.0 or newer, but this is v22.5.0」——
33
+ // 没有任何门禁会因此变红。与 package.json 的 engines.node 对齐由冒烟测试断言
42
34
  const MIN_MAJOR = 22;
43
35
  const MIN_VERSION = `${MIN_MAJOR}.0.0`;
44
36
 
45
37
  const raw = process.versions.node;
46
38
  const major = parseInt(raw.split('.')[0], 10);
47
39
 
48
- // 写成 !(major >= MIN_MAJOR) 而非 major < MIN_MAJOR:解析失败得到 NaN 时同样报错。
40
+ // 写成 !(major >= MIN_MAJOR) 而非 major < MIN_MAJOR:解析失败得到 NaN 时同样报错。
49
41
  if (!(major >= MIN_MAJOR)) {
50
42
  writeStderr(
51
43
  'difftab: requires Node.js ' +