-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
242 lines (217 loc) · 14.1 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
<!DOCTYPE html>
<html lang="en" class="bg-langits-bg h-full">
<head>
<meta charset="UTF-8" />
<meta name="theme-color" content="#F0EDF3">
<meta name="twitter:card" content="summary_large_image">
<meta property="og:site_name" content="langits">
<meta property="og:type" content="website">
<meta property="og:title" content="Visualize your most-used programming languages in your Github repos with Langits.">
<meta property="og:locale" content="en">
<meta property="https://langits.davejudd.dev" content="og:url">
<link rel="canonical" href="https://langits.davejudd.dev">
<meta name="description"
content="This page provides visualization of the programming languages used in a given user's public github repositories.">
<meta property="og:description"
content="This page provides visualization of the programming languages used in a given user's public github repositories.">
<meta property="og:image"
content="https://res.cloudinary.com/daev/image/upload/v1682564365/langits/_og/langits-og_o3bvux.png">
<link rel="shortcut icon" href="data:image/svg+xml,%3Csvg width='64' height='64' viewBox='0 0 64 64' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M31.9876 1.28879C15.0331 1.28879 1.28882 15.0331 1.28882 31.9875C1.28882 46.0126 10.7939 58.2544 24.3817 61.7292L28.1846 46.8584C21.3907 45.121 16.6382 39.0001 16.6382 31.9875C16.6382 23.5103 23.5103 16.6382 31.9876 16.6382V1.28879Z' fill='%233178C6' stroke='%23333333' stroke-width='2' stroke-miterlimit='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M59.81 19.012C54.768 8.20031 43.918 1.28879 31.9875 1.28879V16.6367C37.9528 16.6367 43.3778 20.0924 45.8988 25.4983L59.81 19.012Z' fill='%23C6538C' stroke='%23333333' stroke-width='2' stroke-miterlimit='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M24.0422 61.6403C40.419 66.0284 57.2522 56.3097 61.6404 39.933C63.7477 32.0686 62.6445 23.6892 58.5736 16.6382L45.2807 24.3129C47.3161 27.8384 47.8677 32.0281 46.8141 35.9603C44.62 44.1486 36.2034 49.008 28.015 46.8139L24.0423 61.6403H24.0422Z' fill='%23F1E05A' stroke='%23333333' stroke-width='2' stroke-miterlimit='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A">
<title>Visualize your most-used programming languages in your Github repos with Langits.</title>
<link rel="stylesheet" href="./styles/styles.min.css">
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="description" content="Visualize your most-used programming languages in your Github repos with Langits." />
</head>
<body class="font-firaSans text-langits-black text-lg md:text-xl flex flex-col h-full">
<header class="pt-12 mb-16">
<div class="container">
<a class="block text-5xl md:text-6xl font-bold mb-3" href="/">
<svg viewBox="0 0 64 64" class="inline-block align-bottom w-[54px] md:w-[64px]"><g style="fill-rule:evenodd;clip-rule:evenodd;fill:#3572A5;stroke:#333333;stroke-width:2;stroke-miterlimit:1.5;stroke-linecap:round;stroke-linejoin:round;"><path d="M31.9876 1.28879C15.0331 1.28879 1.28882 15.0331 1.28882 31.9875C1.28882 46.0126 10.7939 58.2544 24.3817 61.7292L28.1846 46.8584C21.3907 45.121 16.6382 39.0001 16.6382 31.9875C16.6382 23.5103 23.5103 16.6382 31.9876 16.6382V1.28879Z"/></g><g style="fill-rule:evenodd;clip-rule:evenodd;fill:#C6538C;stroke:#333333;stroke-width:2;stroke-miterlimit:1.5;stroke-linecap:round;stroke-linejoin:round;"><path d="M59.81 19.012C54.768 8.20031 43.918 1.28879 31.9875 1.28879V16.6367C37.9528 16.6367 43.3778 20.0924 45.8988 25.4983L59.81 19.012Z"/></g><g style="fill-rule:evenodd;clip-rule:evenodd;fill:#F1E05A;stroke:#333333;stroke-width:2;stroke-miterlimit:1.5;stroke-linecap:round;stroke-linejoin:round;"><path d="M24.0422 61.6403C40.419 66.0284 57.2522 56.3097 61.6404 39.933C63.7477 32.0686 62.6445 23.6892 58.5736 16.6382L45.2807 24.3129C47.3161 27.8384 47.8677 32.0281 46.8141 35.9603C44.62 44.1486 36.2034 49.008 28.015 46.8139L24.0423 61.6403H24.0422Z"/></g></svg>
Langits
</a>
<h1 class="text-xl md:text-2xl">Visualize your most-used programming languages in your GitHub repos.</h1>
</div>
</header>
<main class="grow">
<section id="user-input" class="container">
<form id="form" action="" onsubmit="">
<div>
<label>
Enter your Github username:
<input type="text" placeholder="username" class="px-3 py-1 border-2 border-langits-black"/>
</label>
</div>
<div>
<button type="submit" class="bg-langits-blue mt-2 mb-7 px-5 py-1 text-langits-white border-2 border-langits-black">Submit</button>
</div>
</form>
<p id="message"></p>
</section>
<section id="data-display" class="container">
<div style="width: 600px; max-width: 100%; margin: 40px auto;">
<canvas id="langitsDonut"></canvas>
</div>
<div id="langitsTable"></div>
</section>
<section id="how-it-works" class="container">
<h2 class="text-3xl font-bold mb-2">How It Works</h2>
<p class="mb-6">Langits shows the programming languages that make up the GitHub repositories of a given GitHub user. The languages are broken down into percentages based on their propo rtion throughout all of the user's GitHub repositories. The app queries <a href="https://docs.github.com/en/graphql" target="_blank" class="text-langits-blue underline underline-offset-2">GitHub's GraphQL API</a> to obtain the data for the given user.</p>
<h3 class="text-2xl font-bold mb-2">API Limitations</h3>
<p class="mb-4">The GitHub GraphQL API <a href="https://docs.github.com/en/graphql/overview/resource-limitations" target="_blank" class="text-langits-blue underline underline-offset-2">limits the request query</a> to 100 repositories. This is the value used by Langits; the visualization above is only representative of the given user's latest 100 repositories ordered by push time. Since GitHub allows users to have unlimited repos, this could skew and change the meaning of the data! One should keep this in the back of their mind when querying a username, and one may also check the user's GitHub page if they see that 100 repositories are visualized here.</p>
<p class="mb-6">The API also limits the number of programming languages returned by the request to 100, and this is also the value used by Langits. It is likely that very few repos have over 100 languages used in them, so this limitation should rarely show its effects.</p>
<h3 class="text-2xl font-bold mb-2">What is a Language?</h3>
<p class="mb-4">GitHub considers more than strictly just programming languages when they characterize a repository. For example, the <a href="https://github.com/vuejs/docs" target="_blank" class="text-langits-blue underline underline-offset-2">Vue.js v3 docs</a> display Vue, TypeScript, and JavaScript (among others) as its languages. Vue is not a language itself, but a JavaScript library!</p>
<figure class="w-[300px] md:w-[400px] mb-2">
<img src="/images/vuejs-percentages.png" alt="A percent line and description of language make-up of the Vue.js docs repo" class="border-2 border-langits-black" />
<figcaption class="italic text-sm p-2">A screenshot of the visualization of languages in the Vue.js docs repo on GitHub.com taken April 21, 2023.</figcaption>
</figure>
<p class="mb-4">GitHub recognizes over 960 languages, and the list is being updated quite frequently. They categorize recognized languages as data, programming, markup, prose, or nil. Check out GitHub's handy <a href="https://github.com/github/linguist/blob/master/lib/linguist/languages.yml" target="_blank" class="text-langits-blue underline underline-offset-2">linguist Gist</a> for more detail.</p>
</section>
</main>
<footer class="py-8 container">
<p class="text-center text-xl md:text-2xl">Made by Dave <a class="inline align-text-bottom" href="https://github.com/SirDaev/" target="_blank"><img class="inline-block w-7 md:w-9" alt="Github" src="data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3e%3cpath d='M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z' fill='%233572A5'/%3e%3c/svg%3e"></a></p>
</footer>
<script src="https://cdn.usefathom.com/script.js" data-site="XGRVEIJG" defer></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script type="text/javascript">
const message = document.getElementById("message");
const form = document.getElementById("form");
const langitsTable = document.getElementById("langitsTable");
let langitsChart;
form.addEventListener("submit", function(e) {
e.preventDefault();
getData(e.target[0].value);
fathom.trackGoal('ADRZKEAM', 0);
});
function putDataInTable(data) {
langitsTable.innerHTML = "";
if(data.langs.length === 0) {
message.innerHTML = "The user <a href='https://www.github.com/" + data.user + "' class='text-langits-blue underline underline-offset-2' target='_blank'>" + data.user + "</a> has no repos with languages."
return false;
}
message.innerHTML = "The user <a href='https://www.github.com/" + data.user + "' class='text-langits-blue underline underline-offset-2' target='_blank'>" + data.user + "</a> has " + data.numberOfRepos + ((data.numberOfRepos > 1) ? ' repos' : ' repo') + " containing " + data.langs.length + ((data.langs.length > 1) ? ' languages' : ' language') + ".";
const table = document.createElement('table');
table.setAttribute('style', 'border-collapse: collapse; margin-top: 20px; margin-bottom: 60px;');
const tbody = document.createElement('tbody');
data.langs.forEach(lang => {
const tr = document.createElement('tr');
const td_color = document.createElement('td');
td_color.setAttribute('style', 'border: 2px solid #333; background: '+lang.color+"; width: 30px;");
tr.appendChild(td_color);
const td_name = document.createElement('td');
td_name.appendChild(document.createTextNode(lang.name));
td_name.setAttribute('style', 'border: 2px solid #333; padding: 4px 6px;');
tr.appendChild(td_name);
const td_percent = document.createElement('td');
td_percent.appendChild(document.createTextNode(lang.percent + "%"));
td_percent.setAttribute('style', 'border: 2px solid #333; padding: 4px 6px;');
tr.appendChild(td_percent);
tbody.appendChild(tr);
});
table.appendChild(tbody);
langitsTable.appendChild(table);
}
/* ---------------- */
const ctx = document.getElementById("langitsDonut");
function createDiagonalPattern(color = 'black') {
let shape = document.createElement('canvas');
shape.width = 10;
shape.height = 10;
let c = shape.getContext("2d");
c.strokeStyle = color;
c.beginPath();
c.moveTo(2,0);
c.lineTo(10,8);
c.stroke();
c.beginPath();
c.moveTo(0,8);
c.lineTo(2,10);
c.stroke();
return c.createPattern(shape, 'repeat');
}
function createDonutChart(data) {
if(typeof langitsChart === 'object') {
langitsChart.destroy();
}
let labels = [];
let percents = [];
let bgColor = [];
let smalls = {
count: 0,
percent: 0,
ifOnlyOne: {
color: '',
name: ''
}
}
data.langs.forEach(lang => {
if(lang.percent >= 1) {
labels.push(lang.name + ' ' + lang.percent + '%');
percents.push(lang.percent);
bgColor.push(lang.color);
} else {
smalls.count = smalls.count + 1;
smalls.percent += (+lang.percent);
smalls.ifOnlyOne.color = lang.color;
smalls.ifOnlyOne.name = lang.name;
}
});
if(smalls.percent > 0 && smalls.count > 0) {
percents.push(smalls.percent.toFixed(2));
if(smalls.count > 1) {
labels.push('Other ' + smalls.percent.toFixed(2) + '%');
bgColor.push(createDiagonalPattern('rebeccaPurple'));
} else {
labels.push(smalls.ifOnlyOne.name + ' ' + smalls.percent.toFixed(2) + '%');
bgColor.push(smalls.ifOnlyOne.color);
}
}
const chartData = {
labels: labels,
datasets: [{
label: 'GitHub Languages',
data: percents,
backgroundColor: bgColor,
hoverOffset: 4
}]
}
langitsChart = new Chart(ctx, {
type: 'doughnut',
data: chartData,
options: {
elements: {
arc: {
borderWidth: 2,
borderColor: '#333'
}
}
}
})
}
async function getData(username) {
fetch("/api/getLanguages", {
method: "POST",
body: JSON.stringify({
username: username
})
})
.then((response) => {
if (response.status >= 200 && response.status <= 299) {
return response.json();
} else {
console.log(error)
throw Error(response.statusText);
}
})
.then((jsonResponse) => {
putDataInTable(jsonResponse);
createDonutChart(jsonResponse);
}).catch((error) => {
// Handle the error
console.log(error)
alert('Something went wrong. Try a different username.')
});
}
</script>
</body>
</html>