github-polyglot 0.1.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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +32 -0
- data/exe/github-polyglot +11 -0
- data/lib/github_polyglot/cli.rb +55 -0
- data/lib/github_polyglot/svg/language_stats.rb +69 -0
- data/lib/github_polyglot/svg.css +25 -0
- data/lib/github_polyglot/svg.rb +161 -0
- data/lib/github_polyglot.rb +93 -0
- metadata +146 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: f117581b34a8275e8eeb3f1a08b0fb91bf9c00b2b58f3d13b97976d3bbeeb78c
|
|
4
|
+
data.tar.gz: 07b3a83f37124c1f46a5d4ef5be17d576276ed4ec12b55374473eea7fae60624
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: ceb3101add8014191e60d18d3adfc1cf894540ea95d5d8f548140699bbe789c8b2495976fda33ccc16a1c5d745561c825ffeba962b7c6d97e4f47f61a4e731c3
|
|
7
|
+
data.tar.gz: 473fb8f6d833d5b8c54051a27ceb98a79362c99d3ddbb01766971342eff082d774212d0d8532c573fa2717b5c90d7b23abd19a277ea860006d58d0232720443b
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Spenser Black
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# github-polyglot
|
|
2
|
+
|
|
3
|
+
[](https://github.com/spenserblack/github-polyglot/actions/workflows/ci.yml)
|
|
4
|
+
|
|
5
|
+
Linguist, but for the user instead of the repository.
|
|
6
|
+
|
|
7
|
+
This scans all of the repositories that the user has and compiles the language stats.
|
|
8
|
+
The stats can be output as...
|
|
9
|
+
|
|
10
|
+
- A human-readable terminal output
|
|
11
|
+
- JSON
|
|
12
|
+
- An SVG file resembling the language bar
|
|
13
|
+
|
|
14
|
+
If the `GITHUB_TOKEN` environment variable is set, it can use that token to get more
|
|
15
|
+
accurate stats and avoid rate-limiting. You can also avoid needing to pass `--username`
|
|
16
|
+
if you have the token set.
|
|
17
|
+
|
|
18
|
+
## Building
|
|
19
|
+
|
|
20
|
+
### Prerequisites
|
|
21
|
+
|
|
22
|
+
This project depends on [Linguist][github-linguist], which has some dependencies that
|
|
23
|
+
may require extra steps. Read their documentation for more details.
|
|
24
|
+
|
|
25
|
+
#### On Ubuntu
|
|
26
|
+
|
|
27
|
+
```shell
|
|
28
|
+
sudo apt install build-essential cmake pkg-config libicu-dev zlib1g-dev libcurl4-openssl-dev libssl-dev ruby-dev
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
[dotenv-gem]: https://github.com/bkeepers/dotenv
|
|
32
|
+
[github-linguist]: https://github.com/github-linguist/linguist
|
data/exe/github-polyglot
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'dotenv'
|
|
4
|
+
require 'optparse'
|
|
5
|
+
|
|
6
|
+
class GithubPolyglot
|
|
7
|
+
# Class for the command-line interface
|
|
8
|
+
class CLI
|
|
9
|
+
FORMAT_OPTIONS = %i[print json pretty-json svg].freeze
|
|
10
|
+
|
|
11
|
+
def initialize
|
|
12
|
+
parser.parse!
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Runs the CLI
|
|
16
|
+
def run
|
|
17
|
+
Dotenv.load
|
|
18
|
+
|
|
19
|
+
token = ENV.fetch(GithubPolyglot::TOKEN_ENV_VAR, nil)
|
|
20
|
+
token = nil if token&.empty?
|
|
21
|
+
@polyglot = GithubPolyglot.new(username: @username, token: token)
|
|
22
|
+
output_format
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def output_format
|
|
28
|
+
case format
|
|
29
|
+
when :print then @polyglot.print
|
|
30
|
+
when :json then puts @polyglot.json(pretty: false)
|
|
31
|
+
when :'pretty-json' then puts @polyglot.json(pretty: true)
|
|
32
|
+
when :svg then puts @polyglot.svg
|
|
33
|
+
else
|
|
34
|
+
throw NotImplementedError, "Unexpected format: #{format}"
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def parser
|
|
39
|
+
parser = OptionParser.new
|
|
40
|
+
parser.on('-u USERNAME', '-l', '--username', '--login', 'The username/login of the GitHub user') do |value|
|
|
41
|
+
@username = value
|
|
42
|
+
end
|
|
43
|
+
parser.on('-F FORMAT', '--format', FORMAT_OPTIONS,
|
|
44
|
+
"The format to output in (#{FORMAT_OPTIONS.join('/')})") do |value|
|
|
45
|
+
@format = value
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
parser
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def format
|
|
52
|
+
@format ||= :print
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class GithubPolyglot
|
|
4
|
+
class SVG
|
|
5
|
+
# Helper for language stats
|
|
6
|
+
module LanguageStats
|
|
7
|
+
# The number of the most popular languages to show. If there are more than this
|
|
8
|
+
# amount of languages, the least common get grouped under "Other" languages.
|
|
9
|
+
TOP_LANGUAGES = 6
|
|
10
|
+
|
|
11
|
+
# The number of columns in the language stats area.
|
|
12
|
+
STATS_COLUMNS = 2
|
|
13
|
+
|
|
14
|
+
# The height of a language stat row.
|
|
15
|
+
STAT_ROW_HEIGHT = 20
|
|
16
|
+
|
|
17
|
+
# Classes for the language name in language stats.
|
|
18
|
+
LANGUAGE_NAME_CLASS = 'text-bold'
|
|
19
|
+
|
|
20
|
+
# Class for the language percentage.
|
|
21
|
+
LANGUAGE_PERCENTAGE_CLASS = 'muted'
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
# Builds the language stats entries
|
|
26
|
+
def language_stats(xml)
|
|
27
|
+
summarized_languages.each_with_index do |(language, amount), index|
|
|
28
|
+
language_stat(xml, language, amount, index)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Adds the language stat to the SVG
|
|
33
|
+
def language_stat(xml, language, amount, index)
|
|
34
|
+
x, y = language_stats_coordinates(index)
|
|
35
|
+
language_stat_circle(xml, language, x, y)
|
|
36
|
+
x += radius * 4
|
|
37
|
+
y += radius
|
|
38
|
+
language_stat_text(xml, language, amount, x, y)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Adds the circle for the language stat
|
|
42
|
+
def language_stat_circle(xml, language, x_coord, y_coord)
|
|
43
|
+
fill = color(language)
|
|
44
|
+
xml.circle(cx: x_coord + radius, cy: y_coord + radius, r: radius, fill: fill)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Adds the text for the language stat
|
|
48
|
+
def language_stat_text(xml, language, amount, x_coord, y_coord)
|
|
49
|
+
percentage = (amount * 100.0 / total_amount).round(1)
|
|
50
|
+
xml.text_(x: x_coord, y: y_coord, 'dominant-baseline': 'middle') do
|
|
51
|
+
xml.tspan(class: LANGUAGE_NAME_CLASS) do
|
|
52
|
+
xml.text language.to_s
|
|
53
|
+
end
|
|
54
|
+
xml.tspan(class: LANGUAGE_PERCENTAGE_CLASS) { xml.text " #{percentage}%" }
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Gets coordinates for where the language stats should be.
|
|
59
|
+
def language_stats_coordinates(index)
|
|
60
|
+
y_offset = BAR_HEIGHT + BAR_PADDING
|
|
61
|
+
row_num = index / STATS_COLUMNS
|
|
62
|
+
col_num = index % STATS_COLUMNS
|
|
63
|
+
x = (width.to_f / STATS_COLUMNS) * col_num
|
|
64
|
+
y = y_offset + (row_num * STAT_ROW_HEIGHT)
|
|
65
|
+
[x, y]
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
font-family: "Noto Sans", Helvetica, Arial, system-ui, sans-serif;
|
|
3
|
+
font-size: 12px;
|
|
4
|
+
font-weight: 400;
|
|
5
|
+
--text-color: #1F2328;
|
|
6
|
+
--text-color-muted: #59636E;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
@media (prefers-color-scheme: dark) {
|
|
10
|
+
:root {
|
|
11
|
+
--text-color: #D1D7E0;
|
|
12
|
+
--text-color-muted: #9198A1;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
text, tspan {
|
|
17
|
+
fill: var(--text-color);
|
|
18
|
+
}
|
|
19
|
+
tspan.muted {
|
|
20
|
+
fill: var(--text-color-muted);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.text-bold {
|
|
24
|
+
font-weight: 600;
|
|
25
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'linguist'
|
|
4
|
+
require 'nokogiri'
|
|
5
|
+
require 'github_polyglot/svg/language_stats'
|
|
6
|
+
|
|
7
|
+
class GithubPolyglot
|
|
8
|
+
# Generates SVG for language stats
|
|
9
|
+
class SVG
|
|
10
|
+
include LanguageStats
|
|
11
|
+
|
|
12
|
+
# Width of the SVG image
|
|
13
|
+
WIDTH = 300
|
|
14
|
+
|
|
15
|
+
# Height of the language bar
|
|
16
|
+
BAR_HEIGHT = 8
|
|
17
|
+
|
|
18
|
+
# Padding underneath the language bar
|
|
19
|
+
BAR_PADDING = 8
|
|
20
|
+
|
|
21
|
+
# Radii of rounded elements
|
|
22
|
+
RADII = 5
|
|
23
|
+
|
|
24
|
+
# The name of the entry for remaining languages.
|
|
25
|
+
OTHER_LANGUAGES = :Other
|
|
26
|
+
|
|
27
|
+
# The default color to use if a language doesn't have a color
|
|
28
|
+
DEFAULT_COLOR = '#EDEDED'
|
|
29
|
+
|
|
30
|
+
# The CSS text that gets applied to the SVG.
|
|
31
|
+
CSS = File.read(File.expand_path('svg.css', __dir__))
|
|
32
|
+
|
|
33
|
+
# @param [Hash] languages Maps language name symbols to amounts.
|
|
34
|
+
def initialize(languages)
|
|
35
|
+
@languages = languages
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Creates an SVG string
|
|
39
|
+
def generate
|
|
40
|
+
mask_id = 'mask'
|
|
41
|
+
builder = Nokogiri::XML::Builder.new do |xml|
|
|
42
|
+
xml.svg(xmlns: 'http://www.w3.org/2000/svg', width: width, height: height, viewBox: view_box) do
|
|
43
|
+
xml.style(type: 'text/css') { xml.cdata(CSS) }
|
|
44
|
+
body(xml, mask_id)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
builder.to_xml
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Gets the width of the SVG
|
|
52
|
+
def width
|
|
53
|
+
WIDTH
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Gets the height of the SVG
|
|
57
|
+
def height
|
|
58
|
+
BAR_HEIGHT + BAR_PADDING + stats_height
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Gets the radii of rounded elements
|
|
62
|
+
def radii
|
|
63
|
+
RADII
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Alias for radii
|
|
67
|
+
def radius
|
|
68
|
+
RADII
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
# The view box for the SVG
|
|
74
|
+
def view_box
|
|
75
|
+
[0, 0, width, height].map(&:to_s).join(' ')
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Builds the xml body
|
|
79
|
+
def body(xml, mask_id)
|
|
80
|
+
xml.defs do
|
|
81
|
+
mask(xml, mask_id)
|
|
82
|
+
end
|
|
83
|
+
language_group(xml, mask_id)
|
|
84
|
+
language_stats(xml)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Builds the mask for the rounded corners.
|
|
88
|
+
def mask(xml, id)
|
|
89
|
+
xml.mask('mask-type': 'luminance', id: id) do
|
|
90
|
+
xml.rect(x: 0, y: 0, width: width, height: BAR_HEIGHT, rx: radius, ry: radius, fill: 'white')
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Builds the language bar
|
|
95
|
+
def language_group(xml, mask_id)
|
|
96
|
+
xml.g(mask: "url(##{mask_id})") do
|
|
97
|
+
language_x = 0.0
|
|
98
|
+
summarized_languages.each do |language, amount|
|
|
99
|
+
language_x = language_entry(xml, language_x, language, amount)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Builds a single language entry for the language bar
|
|
105
|
+
# @return [Integer, Float] The new offset on the X-axis for the next language entry
|
|
106
|
+
def language_entry(xml, x_offset, language, amount)
|
|
107
|
+
ratio = amount / total_amount
|
|
108
|
+
language_width = width * ratio
|
|
109
|
+
fill = color(language)
|
|
110
|
+
|
|
111
|
+
xml.rect(x: x_offset, y: 0, width: language_width, height: BAR_HEIGHT, fill: fill)
|
|
112
|
+
|
|
113
|
+
x_offset + language_width
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Returns the languages sorted by amount.
|
|
117
|
+
def sorted_languages
|
|
118
|
+
@sorted_languages ||= @languages.sort_by { |_, amount| -amount }
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# Returns the language entries, but groups the least popular under `:Other`.
|
|
122
|
+
def summarized_languages
|
|
123
|
+
return @summarized_languages if @summarized_languages
|
|
124
|
+
|
|
125
|
+
languages = sorted_languages
|
|
126
|
+
return @summarized_languages = languages if languages.length <= TOP_LANGUAGES
|
|
127
|
+
|
|
128
|
+
@summarized_languages = languages.slice(0, TOP_LANGUAGES)
|
|
129
|
+
@summarized_languages << [OTHER_LANGUAGES, languages[TOP_LANGUAGES..].inject(0) do |total, (_, amount)|
|
|
130
|
+
total + amount
|
|
131
|
+
end]
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# Gets the total amount for languages.
|
|
135
|
+
def total_amount
|
|
136
|
+
@total_amount ||= @languages.values.sum.to_f
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Gets the color as a hex code string or CSS color for a language.
|
|
140
|
+
#
|
|
141
|
+
# @param [String, Symbol] language The name of the language.
|
|
142
|
+
def color(language)
|
|
143
|
+
return DEFAULT_COLOR if language == OTHER_LANGUAGES
|
|
144
|
+
|
|
145
|
+
language = language.to_s
|
|
146
|
+
|
|
147
|
+
Linguist::Language[language]&.color || DEFAULT_COLOR
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# Gets the height of the language stats entries.
|
|
151
|
+
def stats_height
|
|
152
|
+
stats_rows * STAT_ROW_HEIGHT
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Gets the number of rows for language stats entries.
|
|
156
|
+
def stats_rows
|
|
157
|
+
# NOTE: + 1 because of the potential extra "Other" entry
|
|
158
|
+
((TOP_LANGUAGES + 1) / STATS_COLUMNS.to_f).ceil
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'github_polyglot/svg'
|
|
4
|
+
require 'json'
|
|
5
|
+
require 'octokit'
|
|
6
|
+
|
|
7
|
+
# Gets language usage stats for a GitHub user.
|
|
8
|
+
class GithubPolyglot
|
|
9
|
+
TOKEN_ENV_VAR = 'GITHUB_TOKEN'
|
|
10
|
+
|
|
11
|
+
# @param [String, Nil] username The username to look up.
|
|
12
|
+
# @param [String, Nil] token The GitHub token to use in requests.
|
|
13
|
+
def initialize(username: nil, token: nil)
|
|
14
|
+
@username = username
|
|
15
|
+
@token = token
|
|
16
|
+
@client = Octokit::Client.new(access_token: token)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Gets the username to use.
|
|
20
|
+
def username
|
|
21
|
+
return @username unless @username.nil?
|
|
22
|
+
|
|
23
|
+
@username = token_username
|
|
24
|
+
@username
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Gets language stats for the user.
|
|
28
|
+
def languages
|
|
29
|
+
compiled = Hash.new(0)
|
|
30
|
+
each_repo do |repo|
|
|
31
|
+
next if repo[:fork]
|
|
32
|
+
|
|
33
|
+
languages = repo_languages(repo.name)
|
|
34
|
+
languages.to_h.each_pair do |language, size|
|
|
35
|
+
compiled[language] += size
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
compiled
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Gets the language stats for the user as JSON.
|
|
42
|
+
def json(pretty: false)
|
|
43
|
+
options = pretty ? { indent: ' ', space: ' ' } : { indent: '', space: '', array_nl: '', object_nl: '' }
|
|
44
|
+
JSON.pretty_generate(languages, options)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Prints the languages
|
|
48
|
+
def print
|
|
49
|
+
languages.each_pair do |language, amount|
|
|
50
|
+
puts "#{language}: #{amount}"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Generates an SVG string for the languages
|
|
55
|
+
def svg
|
|
56
|
+
generator = SVG.new(languages)
|
|
57
|
+
generator.generate
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
# Gets the language stats for a single repository from the GitHub API.
|
|
63
|
+
#
|
|
64
|
+
# @param [String] repository The name of the owner's repository.
|
|
65
|
+
def repo_languages(repository_name)
|
|
66
|
+
@client.languages(repo_qualifier(repository_name))
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Returns the repository path (`owner/repository`) using the username as the owner.
|
|
70
|
+
def repo_qualifier(repository_name)
|
|
71
|
+
"#{username}/#{repository_name}"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Yields each repository
|
|
75
|
+
def each_repo(&block)
|
|
76
|
+
page = 1
|
|
77
|
+
loop do
|
|
78
|
+
repos = @client.repos(username, query: { page: page })
|
|
79
|
+
break unless repos && !repos.empty?
|
|
80
|
+
|
|
81
|
+
repos.each(&block)
|
|
82
|
+
page += 1
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Gets the username for the authenticated token.
|
|
87
|
+
# @return [String, Nil] The authenticated user.
|
|
88
|
+
def token_username
|
|
89
|
+
return nil if @token.nil?
|
|
90
|
+
|
|
91
|
+
@client.user.login
|
|
92
|
+
end
|
|
93
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: github-polyglot
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Spenser Black
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-06-10 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: dotenv
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '3.2'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '3.2'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: faraday-retry
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '2.4'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '2.4'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: github-linguist
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '9.3'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '9.3'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: json
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - "~>"
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '2.18'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - "~>"
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '2.18'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: nokogiri
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - "~>"
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '1.18'
|
|
76
|
+
- - ">="
|
|
77
|
+
- !ruby/object:Gem::Version
|
|
78
|
+
version: 1.18.10
|
|
79
|
+
type: :runtime
|
|
80
|
+
prerelease: false
|
|
81
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
82
|
+
requirements:
|
|
83
|
+
- - "~>"
|
|
84
|
+
- !ruby/object:Gem::Version
|
|
85
|
+
version: '1.18'
|
|
86
|
+
- - ">="
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: 1.18.10
|
|
89
|
+
- !ruby/object:Gem::Dependency
|
|
90
|
+
name: octokit
|
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - "~>"
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '10.0'
|
|
96
|
+
type: :runtime
|
|
97
|
+
prerelease: false
|
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - "~>"
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '10.0'
|
|
103
|
+
description: "(Unofficial) Fetches and aggregates language usage statistics for a
|
|
104
|
+
GitHub user"
|
|
105
|
+
email:
|
|
106
|
+
executables:
|
|
107
|
+
- github-polyglot
|
|
108
|
+
extensions: []
|
|
109
|
+
extra_rdoc_files: []
|
|
110
|
+
files:
|
|
111
|
+
- LICENSE
|
|
112
|
+
- README.md
|
|
113
|
+
- exe/github-polyglot
|
|
114
|
+
- lib/github_polyglot.rb
|
|
115
|
+
- lib/github_polyglot/cli.rb
|
|
116
|
+
- lib/github_polyglot/svg.css
|
|
117
|
+
- lib/github_polyglot/svg.rb
|
|
118
|
+
- lib/github_polyglot/svg/language_stats.rb
|
|
119
|
+
homepage: https://github.com/spenserblack/github-polyglot
|
|
120
|
+
licenses:
|
|
121
|
+
- MIT
|
|
122
|
+
metadata:
|
|
123
|
+
homepage_uri: https://github.com/spenserblack/github-polyglot
|
|
124
|
+
source_code_uri: https://github.com/spenserblack/github-polyglot
|
|
125
|
+
github_repo: https://github.com/spenserblack/github-polyglot
|
|
126
|
+
rubygems_mfa_required: 'true'
|
|
127
|
+
post_install_message:
|
|
128
|
+
rdoc_options: []
|
|
129
|
+
require_paths:
|
|
130
|
+
- lib
|
|
131
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
132
|
+
requirements:
|
|
133
|
+
- - ">="
|
|
134
|
+
- !ruby/object:Gem::Version
|
|
135
|
+
version: '3.2'
|
|
136
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
137
|
+
requirements:
|
|
138
|
+
- - ">="
|
|
139
|
+
- !ruby/object:Gem::Version
|
|
140
|
+
version: '0'
|
|
141
|
+
requirements: []
|
|
142
|
+
rubygems_version: 3.5.22
|
|
143
|
+
signing_key:
|
|
144
|
+
specification_version: 4
|
|
145
|
+
summary: "(Unofficial) Language stats for the GitHub user"
|
|
146
|
+
test_files: []
|