This is a script
I wrote to render GitHub/GitLab like contributions calendar for local repositories, it should render something like this
file: git_calendar.sh
1 #!/bin/bash
2
3 PROJECTS_DIR="$( dirname $PWD )"
4 AUTHOR_EMAIL="$( git config --get --global user.email )"
5 OUTPUT_FILE="$( realpath static/images/git_calendar.svg )"
6
7 TEMP_FILE="$( mktemp )"
8
9 for REPO in $( find "${PROJECTS_DIR}" \
10 -type d -name '.git' -printf '%h\n' )
11 do
12 cd "${REPO}"
13 git log --all --format=tformat:%as --author="${AUTHOR_EMAIL}" \
14 >> "${TEMP_FILE}"
15 done
16
17 cd "${PROJECTS_DIR}"
18
19 cat << SVG_BEGIN_BLOCK > "${OUTPUT_FILE}"
20 <svg width="840" height="168" version="1.1" viewBox="0 0 840 168" xmlns="http://www.w3.org/2000/svg">
21 <style>
22 .dt { font: 12px monospace }
23 .sq { width: 12px; height: 12px; rx: 2px; ry: 2px; }
24 .f0 { fill: rgb(245,245,255); }
25 .f1 { fill: rgb(205,205,255); }
26 .f2 { fill: rgb(155,155,255); }
27 .f3 { fill: rgb(105,105,255); }
28 .f4 { fill: rgb(55,55,255); }
29 .f5 { fill: rgb(5,5,255); }
30 </style>
31 <text x="20" y="60" class="dt">Sun</text>
32 <text x="20" y="88" class="dt">Tue</text>
33 <text x="20" y="116" class="dt">Thu</text>
34 SVG_BEGIN_BLOCK
35
36 TODAY="$( date +'%w:%a, %d %B %Y' )"
37 LASTYEAR="$( date -d 'last year' +'%w:%a, %d %B %Y' )"
38 TOMORROW="$( date -d 'tomorrow' +'%w:%a, %d %B %Y' )"
39
40 DATE_POINTER="${LASTYEAR}"
41 MONTH_TAG=""
42 COLUMN=0
43 while [ "${DATE_POINTER}" != "${TOMORROW}" ]; do
44 ROW=$(( ( ${DATE_POINTER%:*} + 1 ) % 7 ))
45 MONTH="$( date -d "${DATE_POINTER#*:}" +'%b' )"
46 if [ $ROW -eq 0 ] && [ "${MONTH_TAG}" != "${MONTH}" ]; then
47 MONTH_TAG="${MONTH}"
48 printf '<text x="%s" y="32" class="dt">%s</text>' \
49 "$(( ( COLUMN * 14 ) + 48 ))" \
50 "${MONTH_TAG}" >> "${OUTPUT_FILE}"
51 fi
52 printf '<rect class="sq %s" x="%s" y="%s"><title>%s commits on %s</title></rect>\n' \
53 "f0" \
54 "$(( ( COLUMN * 14 ) + 48 ))" \
55 "$(( ( ROW * 14 ) + 36 ))" \
56 "No" \
57 "${DATE_POINTER#*:}" >> "${OUTPUT_FILE}"
58 [ $ROW -eq 6 ] && (( COLUMN++ ))
59 DATE_POINTER="$( date -d "${DATE_POINTER#*:} + 1 day" +'%w:%a, %d %B %Y' )"
60 done
61
62 sort "${TEMP_FILE}" | uniq -c | while read COMMITS DATE; do
63 LEVEL=$(( ( COMMITS / 5 ) + 1 ))
64 [ ${LEVEL} -gt 5 ] && LEVEL=5
65 LEVEL="f${LEVEL}"
66 DATE_STR="$( date -d "${DATE}" +'%a, %d %B %Y' )"
67 sed -i -E "s/(^.*)(f0)(.*)(No)(.*)(${DATE_STR})(.*$)/\1${LEVEL}\3${COMMITS}\5\6\7/" "${OUTPUT_FILE}"
68 done
69
70 cat << SVG_END_BLOCK >> "${OUTPUT_FILE}"
71 <text x="20" y="150" class="dt">Generated ${TODAY#*:}</text>
72 <text x="480" y="150" class="dt">Hover on the boxes for details</text>
73 <rect class="sq f0" x="720" y="140"><title>No commits</title></rect>
74 <rect class="sq f1" x="734" y="140"><title>1 to 5 commits</title></rect>
75 <rect class="sq f2" x="748" y="140"><title>6 to 10 commits</title></rect>
76 <rect class="sq f3" x="762" y="140"><title>11 to 15 commits</title></rect>
77 <rect class="sq f4" x="776" y="140"><title>15 to 20 commits</title></rect>
78 <rect class="sq f5" x="790" y="140"><title>21+ commits</title></rect>
79 </svg>
80 SVG_END_BLOCK
81
82 rm "${TEMP_FILE}"
83