feat color-coded conventional commit type pills in commit lists

Parse commit summaries for conventional commit types (feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert). When detected, display a color-coded pill between the timestamp and the commit title. On narrow screens, the timestamp is hidden to prioritize showing the commit type pill, truncated title, and relative ago time.

Commit
5da2ed5e86becb97164019e1aac39676916d784d
Author
Marius Peter <dev@marius-peter.com>
Author date
Committer
Marius Peter <dev@marius-peter.com>
Committer date
Changed files
lib/static/styles.css
index ffad5477..2634215c 100644..100644
@@ -201,6 +201,80 @@
201 201 color: #555;
202 202 }
203 203
204 Added: .commit-pill {
205 Added: display: inline-block;
206 Added: padding: 0.15em 0.5em;
207 Added: border-radius: 1em;
208 Added: font-size: 0.75em;
209 Added: font-weight: 600;
210 Added: text-transform: uppercase;
211 Added: letter-spacing: 0.03em;
212 Added: margin-right: 0.5em;
213 Added: vertical-align: middle;
214 Added: flex-shrink: 0;
215 Added: }
216 Added:
217 Added: .commit-pill-feat {
218 Added: background-color: #1a4d2e;
219 Added: color: #6ee7a0;
220 Added: }
221 Added:
222 Added: .commit-pill-fix {
223 Added: background-color: #4d1a1a;
224 Added: color: #f87171;
225 Added: }
226 Added:
227 Added: .commit-pill-docs {
228 Added: background-color: #1a3a4d;
229 Added: color: #7dd3fc;
230 Added: }
231 Added:
232 Added: .commit-pill-style {
233 Added: background-color: #3d1a4d;
234 Added: color: #d8b4fe;
235 Added: }
236 Added:
237 Added: .commit-pill-refactor {
238 Added: background-color: #4d3a1a;
239 Added: color: #fbbf24;
240 Added: }
241 Added:
242 Added: .commit-pill-perf {
243 Added: background-color: #4d2d1a;
244 Added: color: #fb923c;
245 Added: }
246 Added:
247 Added: .commit-pill-test {
248 Added: background-color: #1a2e4d;
249 Added: color: #93c5fd;
250 Added: }
251 Added:
252 Added: .commit-pill-build {
253 Added: background-color: #2d2d2d;
254 Added: color: #a3a3a3;
255 Added: }
256 Added:
257 Added: .commit-pill-ci {
258 Added: background-color: #2d2d2d;
259 Added: color: #a3a3a3;
260 Added: }
261 Added:
262 Added: .commit-pill-chore {
263 Added: background-color: #2d2d2d;
264 Added: color: #a3a3a3;
265 Added: }
266 Added:
267 Added: .commit-pill-revert {
268 Added: background-color: #4d1a3a;
269 Added: color: #f9a8d4;
270 Added: }
271 Added:
272 Added: .commit-title {
273 Added: overflow: hidden;
274 Added: text-overflow: ellipsis;
275 Added: white-space: nowrap;
276 Added: }
277 Added:
204 278 h1 {
205 279 padding: 0;
206 280 }
@@ -404,6 +478,10 @@
404 478
405 479 div#main {
406 480 padding: 0 0.5em;
481 Added: }
482 Added:
483 Added: .timestamp {
484 Added: display: none;
407 485 }
408 486
409 487 footer {
lib/views/repo.ml
index 60111426..2c098546 100644..100644
@@ -33,6 +33,41 @@
33 33 let body = String.concat "\n" rest |> String.trim in
34 34 body)
35 35
36 Added: let conventional_commit_types =
37 Added: [
38 Added: "feat";
39 Added: "fix";
40 Added: "docs";
41 Added: "style";
42 Added: "refactor";
43 Added: "perf";
44 Added: "test";
45 Added: "build";
46 Added: "ci";
47 Added: "chore";
48 Added: "revert";
49 Added: ]
50 Added:
51 Added: let parse_conventional summary =
52 Added: match String.index_opt summary ':' with
53 Added: | None -> (None, summary)
54 Added: | Some colon_pos ->
55 Added: let prefix = String.sub summary 0 colon_pos in
56 Added: let type_name =
57 Added: match String.index_opt prefix '(' with
58 Added: | Some paren_pos -> String.sub prefix 0 paren_pos
59 Added: | None -> prefix
60 Added: in
61 Added: let type_lower = String.lowercase_ascii type_name in
62 Added: if List.mem type_lower conventional_commit_types then
63 Added: let rest =
64 Added: String.sub summary (colon_pos + 1)
65 Added: (String.length summary - colon_pos - 1)
66 Added: |> String.trim
67 Added: in
68 Added: (Some type_lower, rest)
69 Added: else (None, summary)
70 Added:
36 71 let li_of_commit repo (commit : Resolvers.Commit.t) =
37 72 let timestamp (date, _) =
38 73 let tm = date |> Int64.to_float |> Unix.localtime in
@@ -68,12 +103,22 @@
68 103 Printf.sprintf "%d year%s ago" years
69 104 (if years = 1 then "" else "s")
70 105 in
106 Added: let summary = commit_summary commit.message in
107 Added: let commit_type, title = parse_conventional summary in
71 108 let timestamp_span =
72 109 HTML.(
73 110 span [ class_ "timestamp" ] [ txt "%s" (timestamp commit.author.date) ])
74 111 in
75 Removed: let summary = commit_summary commit.message in
76 Removed: let description = if summary = "" then HTML.null [] else txt " %s" summary in
112 Added: let pill =
113 Added: match commit_type with
114 Added: | None -> HTML.null []
115 Added: | Some t ->
116 Added: HTML.(
117 Added: span
118 Added: [ class_ (Printf.sprintf "commit-pill commit-pill-%s" t) ]
119 Added: [ txt "%s" t ])
120 Added: in
121 Added: let title_span = HTML.(span [ class_ "commit-title" ] [ txt "%s" title ]) in
77 122 let ago_span =
78 123 HTML.(
79 124 span [ class_ "commit-ago" ] [ txt "%s" (time_ago commit.author.date) ])
@@ -83,7 +128,7 @@
83 128 HTML.(
84 129 null
85 130 [
86 Removed: span [ class_ "commit-left" ] [ timestamp_span; description ];
131 Added: span [ class_ "commit-left" ] [ timestamp_span; pill; title_span ];
87 132 ago_span;
88 133 ])
89 134 in