wukong-gitlog-cli 1.0.34 → 1.0.35

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/CHANGELOG.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ### [1.0.35](https://github.com/tomatobybike/wukong-gitlog-cli/compare/v1.0.34...v1.0.35) (2025-12-12)
6
+
7
+
8
+ ### Features
9
+
10
+ * 🎸 createAuthorNormalizer ([a23a80e](https://github.com/tomatobybike/wukong-gitlog-cli/commit/a23a80e6d664cc5db89b40a63456d8e8d4b2c321))
11
+
5
12
  ### [1.0.34](https://github.com/tomatobybike/wukong-gitlog-cli/compare/v1.0.33...v1.0.34) (2025-12-12)
6
13
 
7
14
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wukong-gitlog-cli",
3
- "version": "1.0.34",
3
+ "version": "1.0.35",
4
4
  "description": "Advanced Git commit log exporter with Excel/JSON/TXT output, grouping, stats and CLI.",
5
5
  "keywords": [
6
6
  "git",
@@ -1,42 +1,69 @@
1
1
  // authorNormalizer.js
2
-
3
2
  /**
4
- * 一个按邮箱自动归一化作者名字的工具。
3
+ * 按邮箱自动归一化作者名字
5
4
  * - 优先使用中文姓名
6
5
  * - 如果同邮箱出现多个非中文名,保持第一个
7
- * - 保留原始 author 以防 debug
6
+ * - 自动清理空格与不可见字符
7
+ * - 保留原始 author 以便 debug
8
8
  */
9
-
10
9
  export function createAuthorNormalizer() {
11
10
  const map = {} // email -> canonical name
11
+ const originalMap = {} // email -> 原始所有 author 名
12
12
 
13
13
  function isChinese(str) {
14
14
  return /[\u4e00-\u9fa5]/.test(str)
15
15
  }
16
16
 
17
+ function cleanName(str) {
18
+ if (!str) return ''
19
+ return str
20
+ // eslint-disable-next-line no-misleading-character-class
21
+ .replace(/[\u200B\u200C\u200D\uFEFF]/g, '') // 去零宽空格
22
+ .replace(/\s+/g, ' ') // 多空格 -> 单空格
23
+ .trim()
24
+ }
25
+
26
+ function cleanEmail(str) {
27
+ return (str || '').trim()
28
+ }
29
+
17
30
  function getAuthor(name, email) {
18
- if (!email) return name
31
+ const cleanedName = cleanName(name)
32
+ const cleanedEmail = cleanEmail(email)
33
+
34
+ if (!cleanedEmail) return cleanedName || 'Unknown'
19
35
 
20
- const canonical = map[email]
36
+ // 记录原始 author 便于 debug
37
+ if (!originalMap[cleanedEmail]) originalMap[cleanedEmail] = new Set()
38
+ if (cleanedName) originalMap[cleanedEmail].add(cleanedName)
39
+
40
+ const canonical = map[cleanedEmail]
21
41
 
22
42
  // 首次遇到这个邮箱 → 记录当前作者名
23
43
  if (!canonical) {
24
- map[email] = name
25
- return name
44
+ map[cleanedEmail] = cleanedName || cleanedEmail
45
+ return map[cleanedEmail]
26
46
  }
27
47
 
28
- // 如果新的作者名是中文 → 覆盖旧的
29
- if (isChinese(name)) {
30
- map[email] = name
31
- return name
48
+ // 新名是中文 → 覆盖旧的
49
+ if (isChinese(cleanedName)) {
50
+ map[cleanedEmail] = cleanedName
51
+ return map[cleanedEmail]
32
52
  }
33
53
 
34
- // 新名不是中文返回已有中文(或旧名)
54
+ // 新名非中文保留已有中文或旧名
35
55
  return canonical
36
56
  }
37
57
 
38
58
  return {
39
59
  getAuthor,
40
- getMap: () => map
60
+ getMap: () => map,
61
+ getOriginalMap: () => {
62
+ const res = {}
63
+ for (const [email, names] of Object.entries(originalMap)) {
64
+ res[email] = Array.from(names)
65
+ }
66
+ return res
67
+ }
41
68
  }
42
69
  }