github-weekly-reporter 0.1.0 → 0.2.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.
Files changed (176) hide show
  1. package/README.md +86 -115
  2. package/dist/cli/commands/deploy.d.ts.map +1 -1
  3. package/dist/cli/commands/deploy.js +9 -3
  4. package/dist/cli/commands/deploy.js.map +1 -1
  5. package/dist/cli/commands/fetch.d.ts +3 -0
  6. package/dist/cli/commands/fetch.d.ts.map +1 -0
  7. package/dist/cli/commands/fetch.js +148 -0
  8. package/dist/cli/commands/fetch.js.map +1 -0
  9. package/dist/cli/commands/generate.d.ts.map +1 -1
  10. package/dist/cli/commands/generate.js +59 -80
  11. package/dist/cli/commands/generate.js.map +1 -1
  12. package/dist/cli/commands/render.d.ts +3 -0
  13. package/dist/cli/commands/render.d.ts.map +1 -0
  14. package/dist/cli/commands/render.js +172 -0
  15. package/dist/cli/commands/render.js.map +1 -0
  16. package/dist/cli/commands/setup.d.ts +3 -0
  17. package/dist/cli/commands/setup.d.ts.map +1 -0
  18. package/dist/cli/commands/setup.js +709 -0
  19. package/dist/cli/commands/setup.js.map +1 -0
  20. package/dist/cli/index.js +6 -0
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/collector/clean-body.d.ts +2 -0
  23. package/dist/collector/clean-body.d.ts.map +1 -0
  24. package/dist/collector/clean-body.js +27 -0
  25. package/dist/collector/clean-body.js.map +1 -0
  26. package/dist/collector/date-range.d.ts +3 -2
  27. package/dist/collector/date-range.d.ts.map +1 -1
  28. package/dist/collector/date-range.js +125 -5
  29. package/dist/collector/date-range.js.map +1 -1
  30. package/dist/collector/fetch-contributions.d.ts +11 -1
  31. package/dist/collector/fetch-contributions.d.ts.map +1 -1
  32. package/dist/collector/fetch-contributions.js +15 -3
  33. package/dist/collector/fetch-contributions.js.map +1 -1
  34. package/dist/collector/fetch-events.d.ts +6 -0
  35. package/dist/collector/fetch-events.d.ts.map +1 -0
  36. package/dist/collector/fetch-events.js +106 -0
  37. package/dist/collector/fetch-events.js.map +1 -0
  38. package/dist/collector/fetch-repo-prs.d.ts +7 -0
  39. package/dist/collector/fetch-repo-prs.d.ts.map +1 -0
  40. package/dist/collector/fetch-repo-prs.js +62 -0
  41. package/dist/collector/fetch-repo-prs.js.map +1 -0
  42. package/dist/collector/queries.d.ts +1 -4
  43. package/dist/collector/queries.d.ts.map +1 -1
  44. package/dist/collector/queries.js +7 -59
  45. package/dist/collector/queries.js.map +1 -1
  46. package/dist/deployer/index-page.d.ts +22 -2
  47. package/dist/deployer/index-page.d.ts.map +1 -1
  48. package/dist/deployer/index-page.js +424 -33
  49. package/dist/deployer/index-page.js.map +1 -1
  50. package/dist/deployer/week.d.ts +1 -1
  51. package/dist/deployer/week.d.ts.map +1 -1
  52. package/dist/deployer/week.js +17 -6
  53. package/dist/deployer/week.js.map +1 -1
  54. package/dist/i18n/fonts.d.ts +8 -0
  55. package/dist/i18n/fonts.d.ts.map +1 -0
  56. package/dist/i18n/fonts.js +44 -0
  57. package/dist/i18n/fonts.js.map +1 -0
  58. package/dist/i18n/index.d.ts +28 -0
  59. package/dist/i18n/index.d.ts.map +1 -0
  60. package/dist/i18n/index.js +259 -0
  61. package/dist/i18n/index.js.map +1 -0
  62. package/dist/index.d.ts +2 -3
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +1 -2
  65. package/dist/index.js.map +1 -1
  66. package/dist/llm/index.d.ts +2 -1
  67. package/dist/llm/index.d.ts.map +1 -1
  68. package/dist/llm/index.js +77 -5
  69. package/dist/llm/index.js.map +1 -1
  70. package/dist/llm/preprocess.d.ts +3 -0
  71. package/dist/llm/preprocess.d.ts.map +1 -0
  72. package/dist/llm/preprocess.js +92 -0
  73. package/dist/llm/preprocess.js.map +1 -0
  74. package/dist/llm/prompt.d.ts.map +1 -1
  75. package/dist/llm/prompt.js +109 -29
  76. package/dist/llm/prompt.js.map +1 -1
  77. package/dist/llm/providers/anthropic.js +1 -1
  78. package/dist/llm/providers/anthropic.js.map +1 -1
  79. package/dist/llm/providers/grok.d.ts +3 -0
  80. package/dist/llm/providers/grok.d.ts.map +1 -0
  81. package/dist/llm/providers/grok.js +18 -0
  82. package/dist/llm/providers/grok.js.map +1 -0
  83. package/dist/llm/providers/groq.d.ts +3 -0
  84. package/dist/llm/providers/groq.d.ts.map +1 -0
  85. package/dist/llm/providers/groq.js +18 -0
  86. package/dist/llm/providers/groq.js.map +1 -0
  87. package/dist/llm/providers/openai.js +1 -1
  88. package/dist/llm/providers/openai.js.map +1 -1
  89. package/dist/llm/providers/openrouter.d.ts +3 -0
  90. package/dist/llm/providers/openrouter.d.ts.map +1 -0
  91. package/dist/llm/providers/openrouter.js +18 -0
  92. package/dist/llm/providers/openrouter.js.map +1 -0
  93. package/dist/llm/types.d.ts +5 -2
  94. package/dist/llm/types.d.ts.map +1 -1
  95. package/dist/renderer/helpers.d.ts +6 -1
  96. package/dist/renderer/helpers.d.ts.map +1 -1
  97. package/dist/renderer/helpers.js +54 -17
  98. package/dist/renderer/helpers.js.map +1 -1
  99. package/dist/renderer/index.d.ts +11 -2
  100. package/dist/renderer/index.d.ts.map +1 -1
  101. package/dist/renderer/index.js +41 -19
  102. package/dist/renderer/index.js.map +1 -1
  103. package/dist/renderer/og-image.d.ts +15 -0
  104. package/dist/renderer/og-image.d.ts.map +1 -0
  105. package/dist/renderer/og-image.js +152 -0
  106. package/dist/renderer/og-image.js.map +1 -0
  107. package/dist/renderer/themes.d.ts +2 -17
  108. package/dist/renderer/themes.d.ts.map +1 -1
  109. package/dist/renderer/themes.js +371 -147
  110. package/dist/renderer/themes.js.map +1 -1
  111. package/dist/types.d.ts +103 -11
  112. package/dist/types.d.ts.map +1 -1
  113. package/package.json +9 -2
  114. package/src/renderer/templates/partials/footer.hbs +3 -1
  115. package/src/renderer/templates/partials/header.hbs +10 -7
  116. package/src/renderer/templates/partials/highlights.hbs +24 -0
  117. package/src/renderer/templates/partials/overview.hbs +3 -0
  118. package/src/renderer/templates/partials/summaries.hbs +73 -0
  119. package/src/renderer/templates/report.hbs +100 -15
  120. package/dist/cli/config.d.ts +0 -11
  121. package/dist/cli/config.d.ts.map +0 -1
  122. package/dist/cli/config.js +0 -16
  123. package/dist/cli/config.js.map +0 -1
  124. package/dist/cli/config.test.d.ts +0 -2
  125. package/dist/cli/config.test.d.ts.map +0 -1
  126. package/dist/cli/config.test.js +0 -32
  127. package/dist/cli/config.test.js.map +0 -1
  128. package/dist/collector/aggregate.test.d.ts +0 -2
  129. package/dist/collector/aggregate.test.d.ts.map +0 -1
  130. package/dist/collector/aggregate.test.js +0 -88
  131. package/dist/collector/aggregate.test.js.map +0 -1
  132. package/dist/collector/date-range.test.d.ts +0 -2
  133. package/dist/collector/date-range.test.d.ts.map +0 -1
  134. package/dist/collector/date-range.test.js +0 -25
  135. package/dist/collector/date-range.test.js.map +0 -1
  136. package/dist/collector/fetch-issues.d.ts +0 -5
  137. package/dist/collector/fetch-issues.d.ts.map +0 -1
  138. package/dist/collector/fetch-issues.js +0 -31
  139. package/dist/collector/fetch-issues.js.map +0 -1
  140. package/dist/collector/fetch-languages.d.ts +0 -4
  141. package/dist/collector/fetch-languages.d.ts.map +0 -1
  142. package/dist/collector/fetch-languages.js +0 -42
  143. package/dist/collector/fetch-languages.js.map +0 -1
  144. package/dist/collector/fetch-pull-requests.d.ts +0 -5
  145. package/dist/collector/fetch-pull-requests.d.ts.map +0 -1
  146. package/dist/collector/fetch-pull-requests.js +0 -31
  147. package/dist/collector/fetch-pull-requests.js.map +0 -1
  148. package/dist/collector/index.d.ts +0 -3
  149. package/dist/collector/index.d.ts.map +0 -1
  150. package/dist/collector/index.js +0 -50
  151. package/dist/collector/index.js.map +0 -1
  152. package/dist/deployer/index-page.test.d.ts +0 -2
  153. package/dist/deployer/index-page.test.d.ts.map +0 -1
  154. package/dist/deployer/index-page.test.js +0 -29
  155. package/dist/deployer/index-page.test.js.map +0 -1
  156. package/dist/deployer/week.test.d.ts +0 -2
  157. package/dist/deployer/week.test.d.ts.map +0 -1
  158. package/dist/deployer/week.test.js +0 -21
  159. package/dist/deployer/week.test.js.map +0 -1
  160. package/dist/llm/llm.test.d.ts +0 -2
  161. package/dist/llm/llm.test.d.ts.map +0 -1
  162. package/dist/llm/llm.test.js +0 -24
  163. package/dist/llm/llm.test.js.map +0 -1
  164. package/dist/llm/prompt.test.d.ts +0 -2
  165. package/dist/llm/prompt.test.d.ts.map +0 -1
  166. package/dist/llm/prompt.test.js +0 -48
  167. package/dist/llm/prompt.test.js.map +0 -1
  168. package/dist/renderer/renderer.test.d.ts +0 -2
  169. package/dist/renderer/renderer.test.d.ts.map +0 -1
  170. package/dist/renderer/renderer.test.js +0 -111
  171. package/dist/renderer/renderer.test.js.map +0 -1
  172. package/src/renderer/templates/partials/heatmap.hbs +0 -11
  173. package/src/renderer/templates/partials/languages.hbs +0 -19
  174. package/src/renderer/templates/partials/narrative.hbs +0 -10
  175. package/src/renderer/templates/partials/repositories.hbs +0 -25
  176. package/src/renderer/templates/partials/stats.hbs +0 -8
package/dist/types.d.ts CHANGED
@@ -11,39 +11,101 @@ export type RepositoryActivity = {
11
11
  issuesClosed: number;
12
12
  url: string;
13
13
  };
14
- export type LanguageBreakdown = {
15
- language: string;
16
- bytes: number;
17
- percentage: number;
18
- color: string;
19
- };
20
14
  export type PullRequest = {
21
15
  title: string;
16
+ body: string | null;
22
17
  url: string;
23
18
  repository: string;
24
19
  state: "open" | "merged" | "closed";
20
+ labels: string[];
21
+ additions: number;
22
+ deletions: number;
23
+ changedFiles: number;
24
+ author: string;
25
25
  createdAt: string;
26
26
  mergedAt: string | null;
27
27
  };
28
28
  export type Issue = {
29
29
  title: string;
30
+ body: string | null;
30
31
  url: string;
31
32
  repository: string;
32
33
  state: "open" | "closed";
34
+ labels: string[];
35
+ author: string;
33
36
  createdAt: string;
34
37
  closedAt: string | null;
35
38
  };
39
+ export type GitHubEvent = {
40
+ id: string;
41
+ type: string;
42
+ repo: string;
43
+ createdAt: string;
44
+ payload: EventPayload;
45
+ };
46
+ export type EventPayload = PushEventPayload | PullRequestReviewEventPayload | ReleaseEventPayload | PullRequestEventPayload | IssuesEventPayload | GenericEventPayload;
47
+ export type PushEventPayload = {
48
+ kind: "push";
49
+ ref: string;
50
+ commits: string[];
51
+ };
52
+ export type PullRequestReviewEventPayload = {
53
+ kind: "review";
54
+ action: string;
55
+ prNumber: number;
56
+ prTitle: string;
57
+ state: string;
58
+ };
59
+ export type ReleaseEventPayload = {
60
+ kind: "release";
61
+ action: string;
62
+ tag: string;
63
+ name: string;
64
+ };
65
+ export type PullRequestEventPayload = {
66
+ kind: "pull_request";
67
+ action: string;
68
+ number: number;
69
+ title: string;
70
+ };
71
+ export type IssuesEventPayload = {
72
+ kind: "issues";
73
+ action: string;
74
+ number: number;
75
+ title: string;
76
+ };
77
+ export type GenericEventPayload = {
78
+ kind: "generic";
79
+ action: string;
80
+ };
36
81
  export type WeeklyStats = {
37
82
  totalCommits: number;
83
+ totalAdditions: number;
84
+ totalDeletions: number;
38
85
  prsOpened: number;
39
86
  prsMerged: number;
40
87
  prsReviewed: number;
41
88
  issuesOpened: number;
42
89
  issuesClosed: number;
43
90
  };
91
+ export type ExternalContribution = {
92
+ repo: string;
93
+ events: GitHubEvent[];
94
+ pullRequests: PullRequest[];
95
+ };
96
+ export type UserProfile = {
97
+ name: string | null;
98
+ bio: string | null;
99
+ company: string | null;
100
+ location: string | null;
101
+ followers: number;
102
+ following: number;
103
+ publicRepos: number;
104
+ };
44
105
  export type WeeklyReportData = {
45
106
  username: string;
46
107
  avatarUrl: string;
108
+ profile?: UserProfile;
47
109
  dateRange: {
48
110
  from: string;
49
111
  to: string;
@@ -51,18 +113,48 @@ export type WeeklyReportData = {
51
113
  stats: WeeklyStats;
52
114
  dailyCommits: DailyCommitCount[];
53
115
  repositories: RepositoryActivity[];
54
- languages: LanguageBreakdown[];
55
116
  pullRequests: PullRequest[];
56
117
  issues: Issue[];
57
- aiNarrative: string | null;
118
+ events: GitHubEvent[];
119
+ externalContributions: ExternalContribution[];
120
+ aiContent: AIContent;
121
+ };
122
+ export type SummaryType = string;
123
+ export type HighlightType = "pr" | "release" | "issue" | "discussion";
124
+ export type DataChip = {
125
+ label: string;
126
+ value: string;
127
+ color?: "green" | "red" | "default";
128
+ };
129
+ export type SummarySection = {
130
+ type: SummaryType;
131
+ heading: string;
132
+ body: string;
133
+ chips?: DataChip[];
134
+ };
135
+ export type HighlightSection = {
136
+ type: HighlightType;
137
+ title: string;
138
+ repo: string;
139
+ meta: string;
140
+ body: string;
141
+ url?: string;
142
+ };
143
+ export type AIContent = {
144
+ title: string;
145
+ subtitle: string;
146
+ overview: string;
147
+ summaries: SummarySection[];
148
+ highlights: HighlightSection[];
58
149
  };
59
- export type LLMProvider = "openai" | "anthropic" | "gemini";
60
- export type Theme = "default" | "dark";
150
+ export type LLMProvider = "openai" | "anthropic" | "gemini" | "openrouter" | "groq" | "grok";
151
+ export type Language = "en" | "ja" | "zh-CN" | "zh-TW" | "ko" | "es" | "fr" | "de" | "pt" | "ru";
61
152
  export type ReportConfig = {
62
153
  githubToken: string;
63
154
  llmProvider: LLMProvider | null;
64
155
  llmApiKey: string | null;
65
156
  llmModel: string | null;
66
- theme: Theme;
157
+ language: Language;
158
+ timezone: string;
67
159
  };
68
160
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,QAAQ,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,KAAK,EAAE,WAAW,CAAC;IACnB,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,YAAY,EAAE,kBAAkB,EAAE,CAAC;IACnC,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAIF,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE5D,MAAM,MAAM,KAAK,GAAG,SAAS,GAAG,MAAM,CAAC;AAEvC,MAAM,MAAM,YAAY,GAAG;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,KAAK,CAAC;CACd,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "github-weekly-reporter",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Generate beautiful weekly GitHub activity reports with optional AI narratives",
5
5
  "type": "module",
6
6
  "bin": {
@@ -10,6 +10,7 @@
10
10
  "types": "./dist/index.d.ts",
11
11
  "files": [
12
12
  "dist/",
13
+ "!dist/**/*.test.*",
13
14
  "src/renderer/templates/"
14
15
  ],
15
16
  "scripts": {
@@ -39,11 +40,17 @@
39
40
  "dependencies": {
40
41
  "@anthropic-ai/sdk": "^0.82.0",
41
42
  "@google/generative-ai": "^0.24.1",
43
+ "@inquirer/prompts": "^8.3.2",
42
44
  "@octokit/graphql": "^8.2.1",
43
45
  "commander": "^14.0.3",
44
46
  "handlebars": "^4.7.9",
47
+ "isomorphic-dompurify": "^3.7.1",
48
+ "marked": "^17.0.5",
45
49
  "openai": "^6.33.0",
46
- "smol-toml": "^1.6.1"
50
+ "satori": "^0.26.0",
51
+ "sharp": "^0.34.5",
52
+ "tweetsodium": "^0.0.4",
53
+ "yaml": "^2.8.3"
47
54
  },
48
55
  "devDependencies": {
49
56
  "@eslint/js": "^9.24.0",
@@ -1,3 +1,5 @@
1
1
  <footer class="footer">
2
- <p>Generated by <a href="https://deariary.com?utm_source=github-weekly-reporter&utm_medium=footer">deariary</a></p>
2
+ {{i18n.poweredBy}} <a href="https://deariary.com?utm_source=github-weekly-reporter&utm_medium=footer" target="_blank" rel="noopener">deariary</a>
3
+ &nbsp;&middot;&nbsp;
4
+ {{i18n.generatedWith}} <a href="https://github.com/deariary/github-weekly-reporter" target="_blank" rel="noopener">github-weekly-reporter</a>
3
5
  </footer>
@@ -1,7 +1,10 @@
1
- <header class="header">
2
- <img class="avatar" src="{{avatarUrl}}" alt="{{username}}" />
3
- <div class="header-text">
4
- <h1>{{username}}'s Weekly Report</h1>
5
- <p class="date-range">{{dateRange.from}} - {{dateRange.to}}</p>
6
- </div>
7
- </header>
1
+ <div class="header-meta">
2
+ <a href="https://github.com/{{username}}" class="header-author" target="_blank" rel="noopener nofollow">
3
+ <img src="{{avatarUrl}}" alt="{{username}}" width="32" height="32" loading="lazy" />
4
+ <span>{{username}}</span>
5
+ </a>
6
+ <span class="header-sep">&middot;</span>
7
+ <span class="header-date">{{weekLabel dateRange.from dateRange.to}}</span>
8
+ </div>
9
+ <h1 class="header-title">{{aiContent.title}}</h1>
10
+ <p class="header-sub">{{aiContent.subtitle}}</p>
@@ -0,0 +1,24 @@
1
+ {{#if aiContent.highlights.length}}
2
+ <div class="section-group">
3
+ <div class="section-group-header">
4
+ <h2 class="section-group-title">{{i18n.sectionHighlights}}</h2>
5
+ <div class="section-group-line"></div>
6
+ <span class="section-group-count">{{itemsCount aiContent.highlights.length}}</span>
7
+ </div>
8
+
9
+ <div class="highlight-grid">
10
+ {{#each aiContent.highlights}}
11
+ <div class="highlight-card">
12
+ <span class="highlight-badge highlight-{{this.type}}">{{this.type}}</span>
13
+ {{#if this.url}}
14
+ <div class="highlight-title"><a href="{{this.url}}" target="_blank" rel="noopener nofollow">{{this.title}}</a></div>
15
+ {{else}}
16
+ <div class="highlight-title">{{this.title}}</div>
17
+ {{/if}}
18
+ <div class="highlight-meta">{{this.repo}} · {{this.meta}}</div>
19
+ <div class="highlight-body">{{{mdInline this.body}}}</div>
20
+ </div>
21
+ {{/each}}
22
+ </div>
23
+ </div>
24
+ {{/if}}
@@ -0,0 +1,3 @@
1
+ <div class="overview">
2
+ {{{md aiContent.overview}}}
3
+ </div>
@@ -0,0 +1,73 @@
1
+ {{#if aiContent.summaries.length}}
2
+ <div class="section-group">
3
+ <div class="section-group-header">
4
+ <h2 class="section-group-title">{{i18n.sectionSummary}}</h2>
5
+ <div class="section-group-line"></div>
6
+ <span class="section-group-count">{{sectionsCount aiContent.summaries.length}}</span>
7
+ </div>
8
+
9
+ {{#each aiContent.summaries}}
10
+ <div class="section-summary">
11
+ <div class="section-type">{{this.type}}</div>
12
+ <div class="section-heading">{{{mdInline this.heading}}}</div>
13
+ <div class="section-body">{{{mdInline this.body}}}</div>
14
+
15
+ {{! Activity pattern: mini heatmap }}
16
+ {{#eq this.type "activity-pattern"}}
17
+ {{#if @root.dailyCommits.length}}
18
+ <div class="mini-heatmap">
19
+ {{#each @root.dailyCommits}}
20
+ <div class="mh-day">
21
+ <div class="mh-block mh-level-{{this.level}}">{{this.count}}</div>
22
+ <div class="mh-label">{{weekday this.date}}</div>
23
+ </div>
24
+ {{/each}}
25
+ </div>
26
+ {{/if}}
27
+ {{/eq}}
28
+
29
+ {{! Commit summary: additions/deletions bar }}
30
+ {{#eq this.type "commit-summary"}}
31
+ {{#if @root.stats.totalAdditions}}
32
+ <div class="diff-bar">
33
+ <div class="diff-add" style="flex:{{@root.stats.totalAdditions}}"></div>
34
+ <div class="diff-del" style="flex:{{@root.stats.totalDeletions}}"></div>
35
+ </div>
36
+ <div class="diff-labels">
37
+ <span class="diff-label-add">+{{formatNumber @root.stats.totalAdditions}}</span>
38
+ <span class="diff-label-del">-{{formatNumber @root.stats.totalDeletions}}</span>
39
+ </div>
40
+ {{/if}}
41
+ {{/eq}}
42
+
43
+ {{! Repo summary: mini bar chart }}
44
+ {{#eq this.type "repo-summary"}}
45
+ {{#if @root.repositories.length}}
46
+ <div class="repo-bars">
47
+ {{#each (sortReposDesc @root.repositories)}}
48
+ <div class="repo-bar-item">
49
+ <div class="repo-bar-header">
50
+ <span class="repo-bar-label">{{this.name}}</span>
51
+ <span class="repo-bar-value">{{this.prsOpened}} PRs</span>
52
+ </div>
53
+ <div class="repo-bar-track">
54
+ <div class="repo-bar-fill" style="width:{{repoBarWidth this.prsOpened @root.repositories}}%"></div>
55
+ </div>
56
+ </div>
57
+ {{/each}}
58
+ </div>
59
+ {{/if}}
60
+ {{/eq}}
61
+
62
+ {{! Chips }}
63
+ {{#if this.chips}}
64
+ <div class="data-chips">
65
+ {{#each this.chips}}
66
+ <span class="chip"><span class="chip-label">{{this.label}}</span> <span class="chip-value chip-{{this.color}}">{{this.value}}</span></span>
67
+ {{/each}}
68
+ </div>
69
+ {{/if}}
70
+ </div>
71
+ {{/each}}
72
+ </div>
73
+ {{/if}}
@@ -1,27 +1,112 @@
1
1
  <!DOCTYPE html>
2
- <html lang="en">
2
+ <html lang="{{lang}}">
3
3
  <head>
4
- <title>{{username}}'s Weekly Report ({{dateRange.from}} - {{dateRange.to}})</title>
4
+ <title>{{aiContent.title}} - {{dateRange.from}} - {{dateRange.to}}</title>
5
5
  <meta charset="utf-8" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1" />
7
- <meta name="description" content="GitHub activity report: {{stats.totalCommits}} commits, {{stats.prsOpened}} PRs, {{stats.issuesOpened}} issues" />
8
- <meta property="og:title" content="{{username}}'s Weekly Report ({{dateRange.from}} - {{dateRange.to}})" />
9
- <meta property="og:description" content="GitHub activity report: {{stats.totalCommits}} commits, {{stats.prsOpened}} PRs, {{stats.issuesOpened}} issues" />
10
- <meta property="og:image" content="{{avatarUrl}}" />
11
- <meta property="og:type" content="website" />
7
+ <meta name="description" content="{{aiContent.subtitle}}" />
8
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
10
+ <meta property="og:title" content="{{aiContent.title}}" />
11
+ <meta property="og:description" content="{{aiContent.subtitle}}" />
12
+ <meta property="og:image" content="{{{ogImageUrl}}}" />
13
+ <meta property="og:image:width" content="1200" />
14
+ <meta property="og:image:height" content="630" />
15
+ <meta property="og:type" content="article" />
16
+ {{#if canonicalUrl}}<meta property="og:url" content="{{{canonicalUrl}}}" />
17
+ {{/if}}<meta property="og:site_name" content="{{username}} Weekly Reports" />
18
+ <meta name="twitter:card" content="summary_large_image" />
19
+ <meta name="twitter:title" content="{{aiContent.title}}" />
20
+ <meta name="twitter:description" content="{{aiContent.subtitle}}" />
21
+ <meta name="twitter:image" content="{{{ogImageUrl}}}" />
22
+ <meta name="author" content="{{username}}" />
23
+ <meta name="theme-color" content="#050505" />
24
+ <meta property="article:published_time" content="{{dateRange.to}}" />
25
+ <meta property="article:author" content="https://github.com/{{username}}" />
26
+ <link rel="icon" href="{{avatarUrl}}" />
27
+ {{#if canonicalUrl}}<link rel="canonical" href="{{{canonicalUrl}}}" />
28
+ {{/if}}<meta name="view-transition" content="same-origin" />
29
+ <script type="application/ld+json">
30
+ {
31
+ "@context": "https://schema.org",
32
+ "@type": "Article",
33
+ "headline": "{{jsonLdEscape aiContent.title}}",
34
+ "description": "{{jsonLdEscape aiContent.subtitle}}",
35
+ "author": {
36
+ "@type": "Person",
37
+ "name": "{{jsonLdEscape username}}",
38
+ "url": "https://github.com/{{jsonLdEscape username}}"
39
+ },
40
+ "image": "{{jsonLdEscape ogImageUrl}}",
41
+ "datePublished": "{{jsonLdEscape dateRange.to}}"
42
+ }
43
+ </script>
44
+ {{#if canonicalUrl}}
45
+ <script type="application/ld+json">
46
+ {
47
+ "@context": "https://schema.org",
48
+ "@type": "BreadcrumbList",
49
+ "itemListElement": [
50
+ { "@type": "ListItem", "position": 1, "name": "Home", "item": "{{jsonLdEscape baseUrl}}/" },
51
+ { "@type": "ListItem", "position": 2, "name": "{{jsonLdEscape dateRange.from}} - {{jsonLdEscape dateRange.to}}", "item": "{{jsonLdEscape canonicalUrl}}" }
52
+ ]
53
+ }
54
+ </script>
55
+ {{/if}}
12
56
  <style>{{{css}}}</style>
13
57
  </head>
14
58
  <body>
15
- <div class="container">
16
59
 
17
- {{> header}}
18
- {{> stats}}
19
- {{> heatmap}}
20
- {{> languages}}
21
- {{> repositories}}
22
- {{> narrative}}
23
- {{> footer}}
60
+ <a href="#main-content" class="skip-link">Skip to content</a>
24
61
 
62
+ <nav aria-label="Site navigation">
63
+ <div class="nav-inner">
64
+ <a href="../../" class="nav-site-title">{{siteTitle}}</a>
65
+ <a href="../../" class="nav-back">&larr; {{i18n.allWeeks}}</a>
66
+ </div>
67
+ </nav>
68
+
69
+ <div class="report-hero">
70
+ <div class="report-hero-inner">
71
+ {{> header}}
72
+ </div>
73
+ </div>
74
+
75
+ <main id="main-content">
76
+ <article class="page">
77
+ {{> overview}}
78
+ {{> summaries}}
79
+ {{> highlights}}
80
+ </article>
81
+ </main>
82
+
83
+ {{#if canonicalUrl}}
84
+ <div class="share-bar">
85
+ <span class="share-label">{{i18n.share}}</span>
86
+ <a href="https://x.com/intent/tweet?url={{{canonicalUrl}}}&text={{aiContent.title}}" target="_blank" rel="noopener nofollow" class="share-btn share-x" aria-label="Share on X">𝕏</a>
87
+ <a href="https://www.linkedin.com/sharing/share-offsite/?url={{{canonicalUrl}}}" target="_blank" rel="noopener nofollow" class="share-btn share-linkedin" aria-label="Share on LinkedIn">in</a>
88
+ <a href="https://bsky.app/intent/compose?text={{aiContent.title}}%20{{{canonicalUrl}}}" target="_blank" rel="noopener nofollow" class="share-btn share-bsky" aria-label="Share on Bluesky">🦋</a>
25
89
  </div>
90
+ {{/if}}
91
+
92
+ {{#if prevWeek}}{{#if nextWeek}}
93
+ <nav class="week-nav" aria-label="Week navigation">
94
+ <a href="{{prevWeek}}" class="week-nav-link">&larr; {{i18n.prevWeek}}</a>
95
+ <a href="{{nextWeek}}" class="week-nav-link">{{i18n.nextWeek}} &rarr;</a>
96
+ </nav>
97
+ {{else}}
98
+ <nav class="week-nav" aria-label="Week navigation">
99
+ <a href="{{prevWeek}}" class="week-nav-link">&larr; {{i18n.prevWeek}}</a>
100
+ <span></span>
101
+ </nav>
102
+ {{/if}}{{else}}{{#if nextWeek}}
103
+ <nav class="week-nav" aria-label="Week navigation">
104
+ <span></span>
105
+ <a href="{{nextWeek}}" class="week-nav-link">{{i18n.nextWeek}} &rarr;</a>
106
+ </nav>
107
+ {{/if}}{{/if}}
108
+
109
+ {{> footer}}
110
+
26
111
  </body>
27
112
  </html>
@@ -1,11 +0,0 @@
1
- export type FileConfig = {
2
- username?: string;
3
- theme?: string;
4
- output?: string;
5
- llm?: {
6
- provider?: string;
7
- model?: string;
8
- };
9
- };
10
- export declare const loadConfig: (dir?: string) => Promise<FileConfig>;
11
- //# sourceMappingURL=config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/cli/config.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE;QACJ,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH,CAAC;AAIF,eAAO,MAAM,UAAU,GAAU,MAAK,MAAsB,KAAG,OAAO,CAAC,UAAU,CAQhF,CAAC"}
@@ -1,16 +0,0 @@
1
- // Load config from .github-weekly-reporter.toml
2
- import { readFile } from "node:fs/promises";
3
- import { resolve } from "node:path";
4
- import { parse } from "smol-toml";
5
- const CONFIG_FILENAME = ".github-weekly-reporter.toml";
6
- export const loadConfig = async (dir = process.cwd()) => {
7
- const path = resolve(dir, CONFIG_FILENAME);
8
- try {
9
- const content = await readFile(path, "utf-8");
10
- return parse(content);
11
- }
12
- catch {
13
- return {};
14
- }
15
- };
16
- //# sourceMappingURL=config.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/cli/config.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAEhD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAYlC,MAAM,eAAe,GAAG,8BAA8B,CAAC;AAEvD,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE,EAAuB,EAAE;IACnF,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IAC3C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC9C,OAAO,KAAK,CAAC,OAAO,CAAe,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=config.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.test.d.ts","sourceRoot":"","sources":["../../src/cli/config.test.ts"],"names":[],"mappings":""}
@@ -1,32 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { mkdtemp, writeFile, rm } from "node:fs/promises";
3
- import { join } from "node:path";
4
- import { tmpdir } from "node:os";
5
- import { loadConfig } from "./config.js";
6
- describe("loadConfig", () => {
7
- it("loads config from .github-weekly-reporter.toml", async () => {
8
- const dir = await mkdtemp(join(tmpdir(), "gwr-config-"));
9
- try {
10
- await writeFile(join(dir, ".github-weekly-reporter.toml"), `username = "testuser"\ntheme = "dark"\n\n[llm]\nprovider = "openai"\nmodel = "gpt-4o-mini"\n`, "utf-8");
11
- const config = await loadConfig(dir);
12
- expect(config.username).toBe("testuser");
13
- expect(config.theme).toBe("dark");
14
- expect(config.llm?.provider).toBe("openai");
15
- expect(config.llm?.model).toBe("gpt-4o-mini");
16
- }
17
- finally {
18
- await rm(dir, { recursive: true, force: true });
19
- }
20
- });
21
- it("returns empty object when file does not exist", async () => {
22
- const dir = await mkdtemp(join(tmpdir(), "gwr-config-"));
23
- try {
24
- const config = await loadConfig(dir);
25
- expect(config).toEqual({});
26
- }
27
- finally {
28
- await rm(dir, { recursive: true, force: true });
29
- }
30
- });
31
- });
32
- //# sourceMappingURL=config.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.test.js","sourceRoot":"","sources":["../../src/cli/config.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,aAAa,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC;YACH,MAAM,SAAS,CACb,IAAI,CAAC,GAAG,EAAE,8BAA8B,CAAC,EACzC,8FAA8F,EAC9F,OAAO,CACR,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACzC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC5C,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAChD,CAAC;gBAAS,CAAC;YACT,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,aAAa,CAAC,CAAC,CAAC;QACzD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;YACrC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC7B,CAAC;gBAAS,CAAC;YACT,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAClD,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=aggregate.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"aggregate.test.d.ts","sourceRoot":"","sources":["../../src/collector/aggregate.test.ts"],"names":[],"mappings":""}
@@ -1,88 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { aggregateRepositories } from "./aggregate.js";
3
- describe("aggregateRepositories", () => {
4
- it("aggregates PRs and issues by repository", () => {
5
- const prs = [
6
- {
7
- title: "Fix bug",
8
- url: "https://github.com/org/repo-a/pull/1",
9
- repository: "org/repo-a",
10
- state: "merged",
11
- createdAt: "2026-04-01T00:00:00Z",
12
- mergedAt: "2026-04-02T00:00:00Z",
13
- },
14
- {
15
- title: "Add feature",
16
- url: "https://github.com/org/repo-a/pull/2",
17
- repository: "org/repo-a",
18
- state: "open",
19
- createdAt: "2026-04-02T00:00:00Z",
20
- mergedAt: null,
21
- },
22
- {
23
- title: "Update docs",
24
- url: "https://github.com/org/repo-b/pull/1",
25
- repository: "org/repo-b",
26
- state: "merged",
27
- createdAt: "2026-04-01T00:00:00Z",
28
- mergedAt: "2026-04-01T00:00:00Z",
29
- },
30
- ];
31
- const issues = [
32
- {
33
- title: "Bug report",
34
- url: "https://github.com/org/repo-a/issues/1",
35
- repository: "org/repo-a",
36
- state: "closed",
37
- createdAt: "2026-04-01T00:00:00Z",
38
- closedAt: "2026-04-02T00:00:00Z",
39
- },
40
- ];
41
- const result = aggregateRepositories(prs, issues);
42
- expect(result).toHaveLength(2);
43
- const repoA = result.find((r) => r.name === "org/repo-a");
44
- expect(repoA).toBeDefined();
45
- expect(repoA.prsOpened).toBe(2);
46
- expect(repoA.prsMerged).toBe(1);
47
- expect(repoA.issuesOpened).toBe(1);
48
- expect(repoA.issuesClosed).toBe(1);
49
- const repoB = result.find((r) => r.name === "org/repo-b");
50
- expect(repoB).toBeDefined();
51
- expect(repoB.prsOpened).toBe(1);
52
- expect(repoB.prsMerged).toBe(1);
53
- });
54
- it("sorts by total activity (PRs + issues) descending", () => {
55
- const prs = [
56
- {
57
- title: "PR1",
58
- url: "",
59
- repository: "org/less-active",
60
- state: "open",
61
- createdAt: "",
62
- mergedAt: null,
63
- },
64
- {
65
- title: "PR2",
66
- url: "",
67
- repository: "org/more-active",
68
- state: "open",
69
- createdAt: "",
70
- mergedAt: null,
71
- },
72
- {
73
- title: "PR3",
74
- url: "",
75
- repository: "org/more-active",
76
- state: "merged",
77
- createdAt: "",
78
- mergedAt: "",
79
- },
80
- ];
81
- const result = aggregateRepositories(prs, []);
82
- expect(result[0].name).toBe("org/more-active");
83
- });
84
- it("returns empty array when no activity", () => {
85
- expect(aggregateRepositories([], [])).toEqual([]);
86
- });
87
- });
88
- //# sourceMappingURL=aggregate.test.js.map