@zjex/git-workflow 0.4.0 → 0.4.2

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/dist/index.js CHANGED
@@ -94,7 +94,7 @@ import { execSync as execSync6 } from "child_process";
94
94
  import { readFileSync as readFileSync3, writeFileSync as writeFileSync4, existsSync as existsSync3, unlinkSync as unlinkSync2 } from "fs";
95
95
  import { homedir as homedir3 } from "os";
96
96
  import { join as join4 } from "path";
97
- import boxen from "boxen";
97
+ import boxen2 from "boxen";
98
98
  import { select as select7 } from "@inquirer/prompts";
99
99
  import ora5 from "ora";
100
100
  import semver from "semver";
@@ -180,7 +180,7 @@ function showSimpleNotification(current, latest) {
180
180
  "gw update"
181
181
  )} ${colors.dim("\u66F4\u65B0")}`;
182
182
  console.log(
183
- boxen(message, {
183
+ boxen2(message, {
184
184
  padding: { top: 0, bottom: 0, left: 2, right: 2 },
185
185
  margin: { top: 0, bottom: 0, left: 0, right: 0 },
186
186
  borderStyle: "round",
@@ -197,7 +197,7 @@ async function showUpdateMessage(current, latest, packageName) {
197
197
  ].join("\n");
198
198
  console.log("");
199
199
  console.log(
200
- boxen(message, {
200
+ boxen2(message, {
201
201
  padding: { top: 1, bottom: 1, left: 3, right: 3 },
202
202
  margin: { top: 0, bottom: 0, left: 1, right: 1 },
203
203
  borderStyle: "round",
@@ -252,7 +252,7 @@ async function performUpdate(packageName) {
252
252
  clearUpdateCache();
253
253
  console.log("");
254
254
  console.log(
255
- boxen(
255
+ boxen2(
256
256
  [
257
257
  colors.green(colors.bold("\u2728 \u66F4\u65B0\u5B8C\u6210\uFF01")),
258
258
  "",
@@ -1675,9 +1675,10 @@ async function init() {
1675
1675
 
1676
1676
  // src/commands/stash.ts
1677
1677
  init_utils();
1678
- import { execSync as execSync4 } from "child_process";
1678
+ import { execSync as execSync4, spawn } from "child_process";
1679
1679
  import { select as select5, input as input4 } from "@inquirer/prompts";
1680
1680
  import ora3 from "ora";
1681
+ import boxen from "boxen";
1681
1682
  function parseStashList() {
1682
1683
  const raw = execOutput('git stash list --format="%gd|%s|%ar"');
1683
1684
  if (!raw) return [];
@@ -1848,18 +1849,119 @@ function applyStash(index, pop) {
1848
1849
  }
1849
1850
  async function showDiff(index) {
1850
1851
  try {
1851
- execSync4(`git stash show -p --color=always stash@{${index}}`, {
1852
- stdio: "inherit"
1853
- });
1854
- console.log();
1852
+ const diffOutput = execOutput(
1853
+ `git stash show -p --no-color stash@{${index}}`
1854
+ );
1855
+ if (!diffOutput) {
1856
+ console.log(colors.yellow("\u6CA1\u6709\u5DEE\u5F02\u5185\u5BB9"));
1857
+ await input4({
1858
+ message: colors.dim("\u6309 Enter \u8FD4\u56DE\u83DC\u5355..."),
1859
+ theme
1860
+ });
1861
+ return;
1862
+ }
1863
+ const statsOutput = execOutput(`git stash show --stat stash@{${index}}`);
1864
+ const files = parseDiffByFile(diffOutput);
1865
+ let fullOutput = "";
1866
+ if (statsOutput) {
1867
+ const statsBox = boxen(statsOutput, {
1868
+ padding: { top: 0, bottom: 0, left: 1, right: 1 },
1869
+ margin: { top: 0, bottom: 1, left: 0, right: 0 },
1870
+ borderStyle: "double",
1871
+ borderColor: "yellow",
1872
+ title: `\u{1F4CA} Stash #${index} \u7EDF\u8BA1`,
1873
+ titleAlignment: "center"
1874
+ });
1875
+ fullOutput += statsBox + "\n";
1876
+ }
1877
+ for (const file of files) {
1878
+ const fileContent = formatFileDiff(file);
1879
+ const fileBox = boxen(fileContent, {
1880
+ padding: { top: 0, bottom: 0, left: 1, right: 1 },
1881
+ margin: { top: 0, bottom: 1, left: 0, right: 0 },
1882
+ borderStyle: "round",
1883
+ borderColor: "cyan",
1884
+ title: `\u{1F4C4} ${file.path}`,
1885
+ titleAlignment: "left"
1886
+ });
1887
+ fullOutput += fileBox + "\n";
1888
+ }
1889
+ await startPager(fullOutput);
1890
+ } catch (error) {
1891
+ console.log(colors.red("\u65E0\u6CD5\u663E\u793A\u5DEE\u5F02"));
1855
1892
  await input4({
1856
1893
  message: colors.dim("\u6309 Enter \u8FD4\u56DE\u83DC\u5355..."),
1857
1894
  theme
1858
1895
  });
1859
- } catch {
1860
- console.log(colors.red("\u65E0\u6CD5\u663E\u793A\u5DEE\u5F02"));
1861
1896
  }
1862
1897
  }
1898
+ function parseDiffByFile(diffOutput) {
1899
+ const files = [];
1900
+ const lines = diffOutput.split("\n");
1901
+ let currentFile = null;
1902
+ for (const line of lines) {
1903
+ if (line.startsWith("diff --git")) {
1904
+ if (currentFile && currentFile.lines.length > 0) {
1905
+ files.push(currentFile);
1906
+ }
1907
+ const match = line.match(/diff --git a\/(.*?) b\/(.*?)$/);
1908
+ const path = match ? match[2] : "unknown";
1909
+ currentFile = { path, lines: [] };
1910
+ } else if (currentFile) {
1911
+ if (line.startsWith("index ") || line.startsWith("--- ") || line.startsWith("+++ ")) {
1912
+ continue;
1913
+ }
1914
+ currentFile.lines.push(line);
1915
+ }
1916
+ }
1917
+ if (currentFile && currentFile.lines.length > 0) {
1918
+ files.push(currentFile);
1919
+ }
1920
+ return files;
1921
+ }
1922
+ function formatFileDiff(file) {
1923
+ const formattedLines = [];
1924
+ for (const line of file.lines) {
1925
+ if (line.startsWith("@@")) {
1926
+ formattedLines.push(colors.blue(line));
1927
+ } else if (line.startsWith("+")) {
1928
+ formattedLines.push(colors.green(line));
1929
+ } else if (line.startsWith("-")) {
1930
+ formattedLines.push(colors.red(line));
1931
+ } else {
1932
+ formattedLines.push(colors.dim(line));
1933
+ }
1934
+ }
1935
+ return formattedLines.join("\n");
1936
+ }
1937
+ function startPager(content) {
1938
+ return new Promise((resolve) => {
1939
+ const pager = process.env.PAGER || "less";
1940
+ try {
1941
+ const pagerProcess = spawn(pager, ["-R", "-S", "-F", "-X", "-i"], {
1942
+ stdio: ["pipe", "inherit", "inherit"],
1943
+ env: { ...process.env, LESS: "-R -S -F -X -i" }
1944
+ });
1945
+ pagerProcess.stdin.on("error", (err) => {
1946
+ if (err.code !== "EPIPE") {
1947
+ console.error(err);
1948
+ }
1949
+ });
1950
+ pagerProcess.stdin.write(content);
1951
+ pagerProcess.stdin.end();
1952
+ pagerProcess.on("exit", () => {
1953
+ resolve();
1954
+ });
1955
+ pagerProcess.on("error", () => {
1956
+ console.log(content);
1957
+ resolve();
1958
+ });
1959
+ } catch (error) {
1960
+ console.log(content);
1961
+ resolve();
1962
+ }
1963
+ });
1964
+ }
1863
1965
  async function createBranchFromStash(index) {
1864
1966
  const type = await select5({
1865
1967
  message: "\u9009\u62E9\u5206\u652F\u7C7B\u578B:",
@@ -2574,7 +2676,7 @@ init_update_notifier();
2574
2676
  init_utils();
2575
2677
  import { execSync as execSync7 } from "child_process";
2576
2678
  import ora6 from "ora";
2577
- import boxen2 from "boxen";
2679
+ import boxen3 from "boxen";
2578
2680
  import semver2 from "semver";
2579
2681
  import { existsSync as existsSync4, unlinkSync as unlinkSync3 } from "fs";
2580
2682
  import { homedir as homedir4 } from "os";
@@ -2626,7 +2728,7 @@ async function update(currentVersion) {
2626
2728
  spinner.stop();
2627
2729
  if (semver2.gte(currentVersion, latestVersion)) {
2628
2730
  console.log(
2629
- boxen2(
2731
+ boxen3(
2630
2732
  [
2631
2733
  colors.green(colors.bold("\u2705 \u5DF2\u662F\u6700\u65B0\u7248\u672C")),
2632
2734
  "",
@@ -2645,7 +2747,7 @@ async function update(currentVersion) {
2645
2747
  }
2646
2748
  const versionText = `${currentVersion} \u2192 ${latestVersion}`;
2647
2749
  console.log(
2648
- boxen2(
2750
+ boxen3(
2649
2751
  [
2650
2752
  colors.yellow(colors.bold("\u{1F389} \u53D1\u73B0\u65B0\u7248\u672C\uFF01")),
2651
2753
  "",
@@ -2673,7 +2775,7 @@ async function update(currentVersion) {
2673
2775
  clearUpdateCache2();
2674
2776
  console.log("");
2675
2777
  console.log(
2676
- boxen2(
2778
+ boxen3(
2677
2779
  [
2678
2780
  colors.green(colors.bold("\u2728 \u66F4\u65B0\u5B8C\u6210\uFF01")),
2679
2781
  "",
@@ -2709,8 +2811,8 @@ async function update(currentVersion) {
2709
2811
  // src/commands/log.ts
2710
2812
  init_utils();
2711
2813
  import { execSync as execSync8 } from "child_process";
2712
- import boxen3 from "boxen";
2713
- import { spawn } from "child_process";
2814
+ import boxen4 from "boxen";
2815
+ import { spawn as spawn2 } from "child_process";
2714
2816
  function parseGitLog(output) {
2715
2817
  const commits = [];
2716
2818
  const lines = output.trim().split("\n");
@@ -2914,7 +3016,7 @@ function formatTimelineStyle(commits) {
2914
3016
  }
2915
3017
  }
2916
3018
  }
2917
- const commitBox = boxen3(commitContent.join("\n"), {
3019
+ const commitBox = boxen4(commitContent.join("\n"), {
2918
3020
  padding: { top: 0, bottom: 0, left: 1, right: 1 },
2919
3021
  margin: { top: 0, bottom: 0, left: 0, right: 0 },
2920
3022
  borderStyle: "round",
@@ -2928,7 +3030,7 @@ function formatTimelineStyle(commits) {
2928
3030
  function startInteractivePager(content) {
2929
3031
  const pager = process.env.PAGER || "less";
2930
3032
  try {
2931
- const pagerProcess = spawn(pager, ["-R", "-S", "-F", "-X", "-i"], {
3033
+ const pagerProcess = spawn2(pager, ["-R", "-S", "-F", "-X", "-i"], {
2932
3034
  stdio: ["pipe", "inherit", "inherit"],
2933
3035
  env: { ...process.env, LESS: "-R -S -F -X -i" }
2934
3036
  });
@@ -2974,7 +3076,7 @@ function executeTimelineLog(options) {
2974
3076
  console.log(fullOutput);
2975
3077
  }
2976
3078
  } else {
2977
- const noCommitsMsg = "\n" + boxen3("\u{1F4ED} \u6CA1\u6709\u627E\u5230\u5339\u914D\u7684\u63D0\u4EA4\u8BB0\u5F55", {
3079
+ const noCommitsMsg = "\n" + boxen4("\u{1F4ED} \u6CA1\u6709\u627E\u5230\u5339\u914D\u7684\u63D0\u4EA4\u8BB0\u5F55", {
2978
3080
  padding: { top: 0, bottom: 0, left: 2, right: 2 },
2979
3081
  borderStyle: "round",
2980
3082
  borderColor: "yellow",
@@ -2993,7 +3095,7 @@ function executeTimelineLog(options) {
2993
3095
  } else {
2994
3096
  errorMessage = `\u274C \u6267\u884C\u5931\u8D25: ${error.message}`;
2995
3097
  }
2996
- const errorBox = "\n" + boxen3(errorMessage, {
3098
+ const errorBox = "\n" + boxen4(errorMessage, {
2997
3099
  padding: { top: 0, bottom: 0, left: 2, right: 2 },
2998
3100
  borderStyle: "round",
2999
3101
  borderColor: "red",
@@ -3041,7 +3143,7 @@ process.on("SIGTERM", () => {
3041
3143
  console.log("");
3042
3144
  process.exit(0);
3043
3145
  });
3044
- var version = true ? "0.4.0" : "0.0.0-dev";
3146
+ var version = true ? "0.4.2" : "0.0.0-dev";
3045
3147
  async function mainMenu() {
3046
3148
  console.log(
3047
3149
  colors.green(`
@@ -1,168 +1,179 @@
1
- import { defineConfig } from 'vitepress'
1
+ import { defineConfig } from "vitepress";
2
2
 
3
3
  export default defineConfig({
4
- title: 'Git Workflow',
5
- description: '🚀 极简的 Git 工作流 CLI 工具,让分支管理和版本发布变得轻松愉快',
6
-
4
+ title: "Git Workflow",
5
+ description:
6
+ "🚀 极简的 Git 工作流 CLI 工具,让分支管理和版本发布变得轻松愉快",
7
+
7
8
  // 基础配置
8
- base: '/git-workflow/',
9
- lang: 'zh-CN',
10
-
9
+ base: "/git-workflow/",
10
+ lang: "zh-CN",
11
+
11
12
  // 主题配置
12
13
  themeConfig: {
13
14
  // Logo
14
- logo: '/logo.svg',
15
-
15
+ logo: "/logo.svg",
16
+
16
17
  // 导航栏
17
18
  nav: [
18
- { text: '首页', link: '/' },
19
- { text: '快速开始', link: '/guide/getting-started' },
20
- { text: '命令参考', link: '/commands/' },
21
- { text: '配置', link: '/config/' },
22
- { text: 'GitHub', link: 'https://github.com/iamzjt-front-end/git-workflow' }
19
+ { text: "首页", link: "/" },
20
+ { text: "快速开始", link: "/guide/getting-started" },
21
+ { text: "命令参考", link: "/commands/" },
22
+ { text: "配置", link: "/config/" },
23
23
  ],
24
24
 
25
25
  // 侧边栏
26
26
  sidebar: {
27
- '/guide/': [
27
+ "/guide/": [
28
28
  {
29
- text: '指南',
29
+ text: "指南",
30
30
  items: [
31
- { text: '介绍', link: '/guide/' },
32
- { text: '快速开始', link: '/guide/getting-started' },
33
- { text: '安装', link: '/guide/installation' },
34
- { text: '基础用法', link: '/guide/basic-usage' },
35
- { text: '最佳实践', link: '/guide/best-practices' }
36
- ]
31
+ { text: "介绍", link: "/guide/" },
32
+ { text: "快速开始", link: "/guide/getting-started" },
33
+ { text: "安装", link: "/guide/installation" },
34
+ { text: "基础用法", link: "/guide/basic-usage" },
35
+ { text: "最佳实践", link: "/guide/best-practices" },
36
+ ],
37
37
  },
38
38
  {
39
- text: '核心功能',
39
+ text: "核心功能",
40
40
  items: [
41
- { text: 'AI 智能提交', link: '/guide/ai-commit' },
42
- { text: '分支管理', link: '/guide/branch-management' },
43
- { text: 'Tag 管理', link: '/guide/tag-management' },
44
- { text: 'Stash 管理', link: '/guide/stash-management' },
45
- { text: '版本发布', link: '/guide/release-management' }
46
- ]
41
+ { text: "AI 智能提交", link: "/guide/ai-commit" },
42
+ { text: "分支管理", link: "/guide/branch-management" },
43
+ { text: "Tag 管理", link: "/guide/tag-management" },
44
+ { text: "Stash 管理", link: "/guide/stash-management" },
45
+ { text: "版本发布", link: "/guide/release-management" },
46
+ ],
47
47
  },
48
48
  {
49
- text: '高级用法',
50
- items: [
51
- { text: '团队协作', link: '/guide/team-collaboration' },
52
- { text: '工作流集成', link: '/guide/workflow-integration' },
53
- { text: '自动化脚本', link: '/guide/automation' }
54
- ]
55
- }
56
- ],
57
- '/commands/': [
49
+ text: "团队协作",
50
+ items: [{ text: "团队协作指南", link: "/guide/team-collaboration" }],
51
+ },
58
52
  {
59
- text: '命令参考',
53
+ text: "开发与贡献",
60
54
  items: [
61
- { text: '概览', link: '/commands/' },
62
- { text: '交互式菜单', link: '/commands/interactive' },
63
- { text: '分支命令', link: '/commands/branch' },
64
- { text: '提交命令', link: '/commands/commit' },
65
- { text: '日志命令', link: '/commands/log' },
66
- { text: 'Tag 命令', link: '/commands/tag' },
67
- { text: 'Stash 命令', link: '/commands/stash' },
68
- { text: '版本命令', link: '/commands/release' },
69
- { text: '配置命令', link: '/commands/config' },
70
- { text: '更新命令', link: '/commands/update' },
71
- { text: '帮助命令', link: '/commands/help' }
72
- ]
73
- }
55
+ { text: "开发指南", link: "/guide/development" },
56
+ { text: "测试指南", link: "/guide/testing" },
57
+ { text: "API 文档", link: "/guide/api" },
58
+ { text: "贡献指南", link: "/guide/contributing" },
59
+ ],
60
+ },
74
61
  ],
75
- '/config/': [
62
+ "/commands/": [
76
63
  {
77
- text: '配置',
64
+ text: "命令参考",
78
65
  items: [
79
- { text: '配置概览', link: '/config/' },
80
- { text: '配置文件', link: '/config/config-file' },
81
- { text: 'AI 配置', link: '/config/ai-config' },
82
- { text: '分支配置', link: '/config/branch-config' },
83
- { text: '提交配置', link: '/config/commit-config' },
84
- { text: '配置示例', link: '/config/examples' }
85
- ]
86
- }
66
+ { text: "概览", link: "/commands/" },
67
+ { text: "交互式菜单", link: "/commands/interactive" },
68
+ { text: "分支命令", link: "/commands/branch" },
69
+ { text: "提交命令", link: "/commands/commit" },
70
+ { text: "日志命令", link: "/commands/log" },
71
+ { text: "Tag 命令", link: "/commands/tag" },
72
+ { text: "Stash 命令", link: "/commands/stash" },
73
+ { text: "版本命令", link: "/commands/release" },
74
+ { text: "配置命令", link: "/commands/config" },
75
+ { text: "更新命令", link: "/commands/update" },
76
+ { text: "帮助命令", link: "/commands/help" },
77
+ ],
78
+ },
87
79
  ],
88
- '/api/': [
80
+ "/config/": [
89
81
  {
90
- text: 'API 参考',
82
+ text: "配置",
91
83
  items: [
92
- { text: 'CLI API', link: '/api/cli' },
93
- { text: '配置 API', link: '/api/config' },
94
- { text: '工具函数', link: '/api/utils' }
95
- ]
96
- }
97
- ]
84
+ { text: "配置概览", link: "/config/" },
85
+ { text: "配置文件", link: "/config/config-file" },
86
+ { text: "AI 配置", link: "/config/ai-config" },
87
+ { text: "分支配置", link: "/config/branch-config" },
88
+ { text: "提交配置", link: "/config/commit-config" },
89
+ { text: "配置示例", link: "/config/examples" },
90
+ ],
91
+ },
92
+ ],
98
93
  },
99
94
 
100
95
  // 社交链接
101
96
  socialLinks: [
102
- { icon: 'github', link: 'https://github.com/iamzjt-front-end/git-workflow' },
103
- { icon: 'npm', link: 'https://www.npmjs.com/package/@zjex/git-workflow' }
97
+ {
98
+ icon: "github",
99
+ link: "https://github.com/iamzjt-front-end/git-workflow",
100
+ },
101
+ { icon: "npm", link: "https://www.npmjs.com/package/@zjex/git-workflow" },
104
102
  ],
105
103
 
106
104
  // 页脚
107
105
  footer: {
108
- message: 'Released under the MIT License.',
109
- copyright: 'Copyright © 2026 zjex'
106
+ message: "Released under the MIT License.",
107
+ copyright: "Copyright © 2026 zjex",
110
108
  },
111
109
 
112
110
  // 搜索
113
111
  search: {
114
- provider: 'local'
112
+ provider: "local",
115
113
  },
116
114
 
117
115
  // 编辑链接
118
116
  editLink: {
119
- pattern: 'https://github.com/iamzjt-front-end/git-workflow/edit/main/docs/:path',
120
- text: '在 GitHub 上编辑此页'
117
+ pattern:
118
+ "https://github.com/iamzjt-front-end/git-workflow/edit/main/docs/:path",
119
+ text: "在 GitHub 上编辑此页",
121
120
  },
122
121
 
123
122
  // 最后更新时间
124
123
  lastUpdated: {
125
- text: '最后更新',
124
+ text: "最后更新",
126
125
  formatOptions: {
127
- dateStyle: 'short',
128
- timeStyle: 'medium'
129
- }
126
+ dateStyle: "short",
127
+ timeStyle: "medium",
128
+ },
130
129
  },
131
130
 
132
131
  // 大纲配置
133
132
  outline: {
134
133
  level: [2, 3],
135
- label: '页面导航'
134
+ label: "页面导航",
136
135
  },
137
136
 
138
137
  // 返回顶部
139
- returnToTopLabel: '返回顶部',
138
+ returnToTopLabel: "返回顶部",
140
139
 
141
140
  // 深色模式切换
142
- darkModeSwitchLabel: '主题',
143
- lightModeSwitchTitle: '切换到浅色模式',
144
- darkModeSwitchTitle: '切换到深色模式'
141
+ darkModeSwitchLabel: "主题",
142
+ lightModeSwitchTitle: "切换到浅色模式",
143
+ darkModeSwitchTitle: "切换到深色模式",
145
144
  },
146
145
 
147
146
  // Markdown 配置
148
147
  markdown: {
149
148
  lineNumbers: true,
150
149
  theme: {
151
- light: 'github-light',
152
- dark: 'github-dark'
153
- }
150
+ light: "github-light",
151
+ dark: "github-dark",
152
+ },
154
153
  },
155
154
 
156
155
  // 头部配置
157
156
  head: [
158
- ['link', { rel: 'icon', type: 'image/svg+xml', href: '/git-workflow/favicon.svg' }],
159
- ['link', { rel: 'apple-touch-icon', href: '/git-workflow/logo.svg' }],
160
- ['meta', { name: 'theme-color', content: '#646cff' }],
161
- ['meta', { name: 'og:type', content: 'website' }],
162
- ['meta', { name: 'og:locale', content: 'zh-CN' }],
163
- ['meta', { name: 'og:site_name', content: 'Git Workflow' }],
164
- ['meta', { name: 'og:image', content: '/git-workflow/logo.svg' }],
165
- ['meta', { name: 'og:title', content: 'Git Workflow - 极简的 Git 工作流 CLI 工具' }],
166
- ['meta', { name: 'og:description', content: '让分支管理和版本发布变得轻松愉快' }]
167
- ]
168
- })
157
+ [
158
+ "link",
159
+ { rel: "icon", type: "image/svg+xml", href: "/git-workflow/favicon.svg" },
160
+ ],
161
+ ["link", { rel: "apple-touch-icon", href: "/git-workflow/logo.svg" }],
162
+ ["meta", { name: "theme-color", content: "#646cff" }],
163
+ ["meta", { name: "og:type", content: "website" }],
164
+ ["meta", { name: "og:locale", content: "zh-CN" }],
165
+ ["meta", { name: "og:site_name", content: "Git Workflow" }],
166
+ ["meta", { name: "og:image", content: "/git-workflow/logo.svg" }],
167
+ [
168
+ "meta",
169
+ {
170
+ name: "og:title",
171
+ content: "Git Workflow - 极简的 Git 工作流 CLI 工具",
172
+ },
173
+ ],
174
+ [
175
+ "meta",
176
+ { name: "og:description", content: "让分支管理和版本发布变得轻松愉快" },
177
+ ],
178
+ ],
179
+ });