jekyll-fdroid 0.2.0 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/fdroid/App.rb +45 -48
- data/lib/fdroid/IndexV1.rb +1 -2
- data/lib/fdroid/Package.rb +12 -8
- data/lib/fdroid/Permission.rb +3 -3
- data/lib/fdroid/Repo.rb +7 -4
- data/lib/jekyll/FDroidBrowsingPage.rb +10 -11
- data/lib/jekyll/FDroidFilters.rb +153 -152
- data/lib/jekyll/FDroidLastUpdatedPackagesTag.rb +9 -11
- data/lib/jekyll/FDroidLatestPackagesTag.rb +9 -11
- data/lib/jekyll/FDroidPackageDetailGenerator.rb +41 -42
- data/lib/jekyll/FDroidPackageDetailPage.rb +1 -3
- data/lib/jekyll/FDroidRepoInfoTag.rb +16 -14
- data/lib/jekyll/FDroidSearchAutocompleteTag.rb +72 -62
- data/lib/jekyll/ReadYamlPage.rb +17 -18
- data/lib/lunr/Javascript.rb +7 -7
- data/lib/lunr/LunrIndexer.rb +14 -14
- data/lib/lunr/SearchIndexFile.rb +9 -9
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f72286c732de382d651b8377c0083ed8faeb58cab5a865dd8e72978dd84e1a60
|
4
|
+
data.tar.gz: 57873902b7c8d5249f269293afc0b2d172db25c1371f37b70ec959f00192dfcc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 551e0cba8c4add0d485a7dec9e12d95107b6be1a38620a730e58fe9174b648a861aa054dac69e9e519058adb6dc010c89843958fed78f3ba581ce1ccad4991d6
|
7
|
+
data.tar.gz: '0098617770f3bd1f3bbeddfd0278a9dcdf2cf50f1cc2ed5c8c842051210f7ea36e2f8ad6d59112237b94724bf223b97036031cfb1d271bffd602261153545b87'
|
data/lib/fdroid/App.rb
CHANGED
@@ -39,21 +39,21 @@ module FDroid
|
|
39
39
|
localized = App.localized_graphic_path(@available_locales, @app['localized'], 'icon')
|
40
40
|
if localized
|
41
41
|
"#{package_name}/#{localized}"
|
42
|
-
|
42
|
+
elsif field('icon')
|
43
43
|
"icons-640/#{field('icon')}"
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
47
|
def name
|
48
|
-
App.localized(@available_locales, @app['localized'], 'name')
|
48
|
+
field('name') || App.localized(@available_locales, @app['localized'], 'name')
|
49
49
|
end
|
50
50
|
|
51
51
|
def summary
|
52
|
-
App.localized(@available_locales, @app['localized'], 'summary')
|
52
|
+
field('summary') || App.localized(@available_locales, @app['localized'], 'summary')
|
53
53
|
end
|
54
54
|
|
55
55
|
def description
|
56
|
-
desc = App.localized(@available_locales, @app['localized'], 'description')
|
56
|
+
desc = field('description') || App.localized(@available_locales, @app['localized'], 'description')
|
57
57
|
|
58
58
|
if desc != nil
|
59
59
|
desc = App.process_app_description(desc)
|
@@ -70,7 +70,6 @@ module FDroid
|
|
70
70
|
return code
|
71
71
|
end
|
72
72
|
|
73
|
-
|
74
73
|
# Generates a hash of dumb strings to be used in templates.
|
75
74
|
# If a specific value is not present, then it will have a nil value.
|
76
75
|
# If a value can be localized, then it will choose the most appropriate
|
@@ -79,39 +78,42 @@ module FDroid
|
|
79
78
|
# @return [Hash]
|
80
79
|
def to_data
|
81
80
|
{
|
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
|
-
|
81
|
+
# These fields are taken as is from the metadata. If not present, they are
|
82
|
+
'package_name' => package_name,
|
83
|
+
'author_email' => field('authorEmail'),
|
84
|
+
'author_name' => field('authorName'),
|
85
|
+
'author_website' => field('authorWebSite'),
|
86
|
+
'translation' => field('translation'),
|
87
|
+
'bitcoin' => field('bitcoin'),
|
88
|
+
'litecoin' => field('litecoin'),
|
89
|
+
'donate' => field('donate'),
|
90
|
+
'flattrID' => field('flattrID'),
|
91
|
+
'liberapayID' => field('liberapayID'),
|
92
|
+
'categories' => field('categories'),
|
93
|
+
'anti_features' => field('anti_features'),
|
94
|
+
'suggested_version_code' => suggested_version_code,
|
95
|
+
'suggested_version_name' => @packages.detect { |p| p.version_code == suggested_version_code }&.version_name,
|
96
|
+
'issue_tracker' => field('issueTracker'),
|
97
|
+
'changelog' => field('changelog'),
|
98
|
+
'license' => field('license'),
|
99
|
+
'source_code' => field('sourceCode'),
|
100
|
+
'website' => field('webSite'),
|
101
|
+
'added' => field('added'),
|
102
|
+
'last_updated' => field('lastUpdated'),
|
103
|
+
'whats_new' => App.process_app_description(App.localized(@available_locales, @app['localized'], 'whatsNew')),
|
104
|
+
|
105
|
+
'icon' => icon,
|
106
|
+
'title' => name,
|
107
|
+
'summary' => summary,
|
108
|
+
|
109
|
+
'description' => description,
|
110
|
+
'feature_graphic' => App.localized_graphic_path(@available_locales, @app['localized'], 'featureGraphic'),
|
111
|
+
'phone_screenshots' => App.localized_graphic_list_paths(@available_locales, @app['localized'], 'phoneScreenshots'),
|
112
|
+
'seven_inch_screenshots' => App.localized_graphic_list_paths(@available_locales, @app['localized'], 'sevenInchScreenshots'),
|
113
|
+
|
114
|
+
'packages' => @packages.sort.reverse.map { |p| p.to_data },
|
115
|
+
|
116
|
+
'beautiful_url' => "/packages/#{package_name}"
|
115
117
|
}
|
116
118
|
end
|
117
119
|
|
@@ -134,11 +136,10 @@ module FDroid
|
|
134
136
|
string.gsub /fdroid\.app:([\w._]*)/, '/packages/\1'
|
135
137
|
end
|
136
138
|
|
137
|
-
# Ensure
|
139
|
+
# Ensure newlines in descriptions are preserved (converted to "<br />" tags)
|
140
|
+
# Handles UNIX, Windows and MacOS newlines, with a one-to-one replacement
|
138
141
|
def self.format_description_to_html(string)
|
139
|
-
string
|
140
|
-
.gsub("\n\n", '<br />')
|
141
|
-
.gsub(/\r?\n/, ' ')
|
142
|
+
string.gsub(/(?:\n\r?|\r\n?)/, '<br />')
|
142
143
|
end
|
143
144
|
|
144
145
|
# @param [string] available_locales
|
@@ -156,34 +157,30 @@ module FDroid
|
|
156
157
|
|
157
158
|
return nil
|
158
159
|
end
|
159
|
-
|
160
|
+
|
160
161
|
# Prefixes the result with "chosen_locale/" before returning.
|
161
162
|
# @see localized
|
162
163
|
def self.localized_graphic_path(available_locales, localized, field)
|
163
164
|
return nil unless available_locales != nil
|
164
|
-
|
165
165
|
available_locales.each do |l|
|
166
166
|
if localized[l].key?(field)
|
167
167
|
return "#{l}/#{localized[l][field]}"
|
168
168
|
end
|
169
169
|
end
|
170
|
-
|
171
170
|
return nil
|
172
171
|
end
|
173
|
-
|
172
|
+
|
174
173
|
# Similar to localized_graphic_path, but prefixes each item in the resulting array
|
175
174
|
# with "chosen_locale/field/".
|
176
175
|
# @see localized
|
177
176
|
# @see localized_graphic_path
|
178
177
|
def self.localized_graphic_list_paths(available_locales, localized, field)
|
179
178
|
return nil unless available_locales != nil
|
180
|
-
|
181
179
|
available_locales.each do |l|
|
182
180
|
if localized[l].key?(field)
|
183
181
|
return localized[l][field].map { |val| "#{l}/#{field}/#{val}" }
|
184
182
|
end
|
185
183
|
end
|
186
|
-
|
187
184
|
return nil
|
188
185
|
end
|
189
186
|
|
data/lib/fdroid/IndexV1.rb
CHANGED
data/lib/fdroid/Package.rb
CHANGED
@@ -23,7 +23,7 @@ module FDroid
|
|
23
23
|
@package = package
|
24
24
|
end
|
25
25
|
|
26
|
-
def <=>
|
26
|
+
def <=>(other)
|
27
27
|
self.version_code <=> other.version_code
|
28
28
|
end
|
29
29
|
|
@@ -42,19 +42,23 @@ module FDroid
|
|
42
42
|
end
|
43
43
|
|
44
44
|
{
|
45
|
-
'version_name' => version_name,
|
46
|
-
'version_code' => version_code,
|
47
45
|
'added' => added,
|
46
|
+
'anti_features' => @package['antiFeatures'],
|
48
47
|
'apk_name' => @package['apkName'],
|
48
|
+
'file_extension' => File.extname(@package['apkName'].to_s).strip.upcase[1..-1],
|
49
49
|
'hash' => @package['hash'],
|
50
50
|
'hash_type' => @package['hashType'],
|
51
|
-
'min_sdk_version' => @package['minSdkVersion'],
|
52
51
|
'max_sdk_version' => @package['maxSdkVersion'],
|
53
|
-
'
|
54
|
-
'
|
52
|
+
'min_sdk_version' => @package['minSdkVersion'],
|
53
|
+
'nativecode' => @package['nativecode'],
|
54
|
+
'srcname' => @package['srcname'],
|
55
55
|
'sig' => @package['sig'],
|
56
|
+
'signer' => @package['signer'],
|
56
57
|
'size' => @package['size'],
|
58
|
+
'target_sdk_version' => @package['targetSdkVersion'],
|
57
59
|
'uses_permission' => permission,
|
60
|
+
'version_name' => version_name,
|
61
|
+
'version_code' => version_code,
|
58
62
|
}
|
59
63
|
end
|
60
64
|
|
@@ -62,7 +66,7 @@ module FDroid
|
|
62
66
|
if @package['uses-permission'] == nil then
|
63
67
|
[]
|
64
68
|
else
|
65
|
-
@package['uses-permission'].map {|perm| Permission.new(perm).to_data }
|
69
|
+
@package['uses-permission'].map { |perm| Permission.new(perm).to_data }
|
66
70
|
end
|
67
71
|
end
|
68
72
|
|
@@ -72,4 +76,4 @@ module FDroid
|
|
72
76
|
@app.key?(name) ? name : nil
|
73
77
|
end
|
74
78
|
end
|
75
|
-
end
|
79
|
+
end
|
data/lib/fdroid/Permission.rb
CHANGED
data/lib/fdroid/Repo.rb
CHANGED
@@ -24,7 +24,7 @@ module FDroid
|
|
24
24
|
def name
|
25
25
|
@repo['name']
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
def address
|
29
29
|
@repo['address']
|
30
30
|
end
|
@@ -36,10 +36,13 @@ module FDroid
|
|
36
36
|
def description
|
37
37
|
@repo['description']
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
|
+
def timestamp
|
41
|
+
@repo['timestamp']
|
42
|
+
end
|
43
|
+
|
40
44
|
def date
|
41
45
|
added = Date.strptime("#{@repo['timestamp'] / 1000}", '%s')
|
42
46
|
end
|
43
|
-
|
44
47
|
end
|
45
|
-
end
|
48
|
+
end
|
@@ -16,16 +16,15 @@
|
|
16
16
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
|
18
18
|
module Jekyll
|
19
|
+
class FDroidBrowsingPage < ReadYamlPage
|
20
|
+
def initialize(site, base)
|
21
|
+
@site = site
|
22
|
+
@base = base
|
23
|
+
@dir = "packages"
|
24
|
+
@name = "index.html"
|
19
25
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
@dir = "packages"
|
25
|
-
@name = "index.html"
|
26
|
-
|
27
|
-
self.process(@name)
|
28
|
-
self.read_yaml((File.expand_path "../../_pages", File.dirname(__FILE__)), 'browse.html')
|
29
|
-
end
|
30
|
-
end
|
26
|
+
self.process(@name)
|
27
|
+
self.read_yaml((File.expand_path "../../_pages", File.dirname(__FILE__)), 'browse.html')
|
28
|
+
end
|
29
|
+
end
|
31
30
|
end
|
data/lib/jekyll/FDroidFilters.rb
CHANGED
@@ -16,164 +16,165 @@
|
|
16
16
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
|
18
18
|
module Jekyll
|
19
|
+
module Filters
|
20
|
+
# Convert an Android SDK level into an Android version.
|
21
|
+
#
|
22
|
+
# input - Android SDK Level.
|
23
|
+
#
|
24
|
+
# Returns the Android version.
|
25
|
+
def android_sdk_level_to_version(input)
|
26
|
+
sdkLevel = @@AndroidSdkLevelToVersionRelation[input]
|
27
|
+
if not sdkLevel.nil?
|
28
|
+
return sdkLevel
|
29
|
+
end
|
30
|
+
return '?'
|
31
|
+
end
|
19
32
|
|
20
|
-
|
33
|
+
# Hash with relation between Android SDK Level and Android version
|
34
|
+
# https://source.android.com/setup/build-numbers
|
35
|
+
@@AndroidSdkLevelToVersionRelation = {
|
36
|
+
'1' => '1.0',
|
37
|
+
'2' => '1.1',
|
38
|
+
'3' => '1.5',
|
39
|
+
'4' => '1.6',
|
40
|
+
'5' => '2.0',
|
41
|
+
'6' => '2.0.1',
|
42
|
+
'7' => '2.1',
|
43
|
+
'8' => '2.2',
|
44
|
+
'9' => '2.3',
|
45
|
+
'10' => '2.3.3',
|
46
|
+
'11' => '3.0',
|
47
|
+
'12' => '3.1',
|
48
|
+
'13' => '3.2',
|
49
|
+
'14' => '4.0',
|
50
|
+
'15' => '4.0.3',
|
51
|
+
'16' => '4.1',
|
52
|
+
'17' => '4.2',
|
53
|
+
'18' => '4.3',
|
54
|
+
'19' => '4.4',
|
55
|
+
'20' => '4.4W',
|
56
|
+
'21' => '5.0',
|
57
|
+
'22' => '5.1',
|
58
|
+
'23' => '6.0',
|
59
|
+
'24' => '7.0',
|
60
|
+
'25' => '7.1',
|
61
|
+
'26' => '8.0',
|
62
|
+
'27' => '8.1',
|
63
|
+
}
|
21
64
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
65
|
+
# Convert a file size to a human-readable String.
|
66
|
+
# Source: https://codereview.stackexchange.com/q/9107
|
67
|
+
#
|
68
|
+
# input - File size in Bytes.
|
69
|
+
#
|
70
|
+
# Returns human-readable String.
|
71
|
+
def file_size_human_readable(input)
|
72
|
+
input = input.to_f
|
73
|
+
i = PREFIX.length - 1
|
74
|
+
while input > 512 && i > 0
|
75
|
+
i -= 1
|
76
|
+
input /= 1024
|
77
|
+
end
|
78
|
+
return ((input > 9 || input.modulo(1) < 0.1 ? '%d' : '%.1f') % input) + ' ' + PREFIX[i]
|
79
|
+
end
|
80
|
+
PREFIX = %W(TiB GiB MiB KiB B).freeze
|
34
81
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
'20' => '4.4W',
|
57
|
-
'21' => '5.0',
|
58
|
-
'22' => '5.1',
|
59
|
-
'23' => '6.0',
|
60
|
-
'24' => '7.0',
|
61
|
-
'25' => '7.1'
|
62
|
-
}
|
82
|
+
# Convert a SPDX license identifier to its full name.
|
83
|
+
#
|
84
|
+
# input - SPDX license identifier.
|
85
|
+
#
|
86
|
+
# Returns full license name.
|
87
|
+
def get_license_name(input)
|
88
|
+
if input.nil? or input.empty?
|
89
|
+
return 'Unknown'
|
90
|
+
end
|
91
|
+
spdxLicense = @@SpdxLicenseNameToGnuUrlRelation[input]
|
92
|
+
if input.end_with? "+"
|
93
|
+
spdxLicense = @@SpdxLicenseNameToGnuUrlRelation[input.chomp('+')]
|
94
|
+
end
|
95
|
+
if not spdxLicense.nil?
|
96
|
+
if input.end_with? "+"
|
97
|
+
return spdxLicense['name'] + ' or later version'
|
98
|
+
end
|
99
|
+
return spdxLicense['name']
|
100
|
+
end
|
101
|
+
return input
|
102
|
+
end
|
63
103
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
104
|
+
# Convert a SPDX license identifier to its URL on GNU.org.
|
105
|
+
#
|
106
|
+
# input - SPDX license identifier.
|
107
|
+
#
|
108
|
+
# Returns URL on GNU.org.
|
109
|
+
def get_license_url(input)
|
110
|
+
if input.nil? or input.empty?
|
111
|
+
return ''
|
112
|
+
end
|
113
|
+
if input.end_with? "+"
|
114
|
+
input = input.chomp('+')
|
115
|
+
end
|
116
|
+
spdxLicense = @@SpdxLicenseNameToGnuUrlRelation[input]
|
117
|
+
if not spdxLicense.nil?
|
118
|
+
return spdxLicense['url']
|
119
|
+
end
|
120
|
+
return 'https://spdx.org/licenses/' + input + '.html'
|
121
|
+
end
|
80
122
|
|
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
|
-
'name' => 'BSD 2-clause "Simplified" License',
|
135
|
-
'url' => 'https://www.gnu.org/licenses/license-list.html#FreeBSD'
|
136
|
-
},
|
137
|
-
'BSD-3-Clause' => {
|
138
|
-
'name' => 'BSD 3-clause "New" or "Revised" License',
|
139
|
-
'url' => 'https://www.gnu.org/licenses/license-list.html#ModifiedBSD'
|
140
|
-
},
|
141
|
-
'GPL-2.0' => {
|
142
|
-
'name' => 'GNU General Public License v2.0',
|
143
|
-
'url' => 'https://www.gnu.org/licenses/license-list.html#GPLv2'
|
144
|
-
},
|
145
|
-
'GPL-3.0' => {
|
146
|
-
'name' => 'GNU General Public License v3.0',
|
147
|
-
'url' => 'https://www.gnu.org/licenses/license-list.html#GNUGPLv3'
|
148
|
-
},
|
149
|
-
'ISC' => {
|
150
|
-
'name' => 'ISC License',
|
151
|
-
'url' => 'https://www.gnu.org/licenses/license-list.en.html#ISC'
|
152
|
-
},
|
153
|
-
'LGPL-2.1' => {
|
154
|
-
'name' => 'GNU Lesser General Public License v2.1',
|
155
|
-
'url' => 'https://www.gnu.org/licenses/license-list.html#LGPLv2.1'
|
156
|
-
},
|
157
|
-
'LGPL-3.0' => {
|
158
|
-
'name' => 'GNU Lesser General Public License v3.0',
|
159
|
-
'url' => 'https://www.gnu.org/licenses/license-list.html#LGPLv3'
|
160
|
-
},
|
161
|
-
'MIT' => {
|
162
|
-
'name' => 'MIT License',
|
163
|
-
'url' => 'https://www.gnu.org/licenses/license-list.html#X11License'
|
164
|
-
},
|
165
|
-
'MPL-1.1' => {
|
166
|
-
'name' => 'Mozilla Public License 1.1',
|
167
|
-
'url' => 'https://www.gnu.org/licenses/license-list.html#MPL'
|
168
|
-
},
|
169
|
-
'MPL-2.0' => {
|
170
|
-
'name' => 'Mozilla Public License 2.0',
|
171
|
-
'url' => 'https://www.gnu.org/licenses/license-list.html#MPL-2.0'
|
172
|
-
}
|
173
|
-
}
|
174
|
-
end
|
123
|
+
# Hash with relation between SPDX license identifier and its full name and URL, mostly on GNU.org.
|
124
|
+
# For the beginning, I only used OSI approved and frequently used licenses.
|
125
|
+
@@SpdxLicenseNameToGnuUrlRelation = {
|
126
|
+
'AGPL-3.0' => {
|
127
|
+
'name' => 'GNU Affero General Public License v3.0',
|
128
|
+
'url' => 'https://www.gnu.org/licenses/license-list.html#AGPLv3.0'
|
129
|
+
},
|
130
|
+
'Apache-2.0' => {
|
131
|
+
'name' => 'Apache License 2.0',
|
132
|
+
'url' => 'https://www.gnu.org/licenses/license-list.html#apache2'
|
133
|
+
},
|
134
|
+
'BSD-2-Clause' => {
|
135
|
+
'name' => 'BSD 2-clause "Simplified" License',
|
136
|
+
'url' => 'https://www.gnu.org/licenses/license-list.html#FreeBSD'
|
137
|
+
},
|
138
|
+
'BSD-3-Clause' => {
|
139
|
+
'name' => 'BSD 3-clause "New" or "Revised" License',
|
140
|
+
'url' => 'https://www.gnu.org/licenses/license-list.html#ModifiedBSD'
|
141
|
+
},
|
142
|
+
'GPL-2.0' => {
|
143
|
+
'name' => 'GNU General Public License v2.0',
|
144
|
+
'url' => 'https://www.gnu.org/licenses/license-list.html#GPLv2'
|
145
|
+
},
|
146
|
+
'GPL-3.0' => {
|
147
|
+
'name' => 'GNU General Public License v3.0',
|
148
|
+
'url' => 'https://www.gnu.org/licenses/license-list.html#GNUGPLv3'
|
149
|
+
},
|
150
|
+
'ISC' => {
|
151
|
+
'name' => 'ISC License',
|
152
|
+
'url' => 'https://www.gnu.org/licenses/license-list.en.html#ISC'
|
153
|
+
},
|
154
|
+
'LGPL-2.1' => {
|
155
|
+
'name' => 'GNU Lesser General Public License v2.1',
|
156
|
+
'url' => 'https://www.gnu.org/licenses/license-list.html#LGPLv2.1'
|
157
|
+
},
|
158
|
+
'LGPL-3.0' => {
|
159
|
+
'name' => 'GNU Lesser General Public License v3.0',
|
160
|
+
'url' => 'https://www.gnu.org/licenses/license-list.html#LGPLv3'
|
161
|
+
},
|
162
|
+
'MIT' => {
|
163
|
+
'name' => 'MIT License',
|
164
|
+
'url' => 'https://www.gnu.org/licenses/license-list.html#X11License'
|
165
|
+
},
|
166
|
+
'MPL-1.1' => {
|
167
|
+
'name' => 'Mozilla Public License 1.1',
|
168
|
+
'url' => 'https://www.gnu.org/licenses/license-list.html#MPL'
|
169
|
+
},
|
170
|
+
'MPL-2.0' => {
|
171
|
+
'name' => 'Mozilla Public License 2.0',
|
172
|
+
'url' => 'https://www.gnu.org/licenses/license-list.html#MPL-2.0'
|
173
|
+
}
|
174
|
+
}
|
175
|
+
end
|
175
176
|
end
|
176
177
|
|
177
178
|
Liquid::Template.register_filter(
|
178
|
-
|
179
|
+
Jekyll::Filters
|
179
180
|
)
|
@@ -16,18 +16,16 @@
|
|
16
16
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
|
18
18
|
module Jekyll
|
19
|
+
class FDroidLastUpdatedPackagesTag < Liquid::Tag
|
20
|
+
def initialize(tag_name, text, tokens)
|
21
|
+
super
|
22
|
+
end
|
19
23
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def render(context)
|
27
|
-
template = Liquid::Template.parse(IO.read((File.expand_path "../../_layouts/sidebar-lastupdated-packages.html", File.dirname(__FILE__))))
|
28
|
-
template.render(context)
|
29
|
-
end
|
30
|
-
end
|
24
|
+
def render(context)
|
25
|
+
template = Liquid::Template.parse(IO.read((File.expand_path "../../_layouts/sidebar-lastupdated-packages.html", File.dirname(__FILE__))))
|
26
|
+
template.render(context)
|
27
|
+
end
|
28
|
+
end
|
31
29
|
end
|
32
30
|
|
33
31
|
Liquid::Template.register_tag('fdroid_show_last_updated_packages', Jekyll::FDroidLastUpdatedPackagesTag)
|
@@ -16,18 +16,16 @@
|
|
16
16
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
|
18
18
|
module Jekyll
|
19
|
+
class FDroidLatestPackagesTag < Liquid::Tag
|
20
|
+
def initialize(tag_name, text, tokens)
|
21
|
+
super
|
22
|
+
end
|
19
23
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def render(context)
|
27
|
-
template = Liquid::Template.parse(IO.read((File.expand_path "../../_layouts/sidebar-latest-packages.html", File.dirname(__FILE__))))
|
28
|
-
template.render(context)
|
29
|
-
end
|
30
|
-
end
|
24
|
+
def render(context)
|
25
|
+
template = Liquid::Template.parse(IO.read((File.expand_path "../../_layouts/sidebar-latest-packages.html", File.dirname(__FILE__))))
|
26
|
+
template.render(context)
|
27
|
+
end
|
28
|
+
end
|
31
29
|
end
|
32
30
|
|
33
31
|
Liquid::Template.register_tag('fdroid_show_latest_packages', Jekyll::FDroidLatestPackagesTag)
|
@@ -16,53 +16,52 @@
|
|
16
16
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
|
18
18
|
module Jekyll
|
19
|
+
class FDroidPackagesGenerator < Generator
|
20
|
+
attr_accessor :alreadyBuilt
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
+
safe true
|
23
|
+
priority :highest
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
+
def generate(site)
|
26
|
+
# generator will only run on first build, not because of auto-regeneration
|
27
|
+
if @alreadyBuilt != true
|
28
|
+
@alreadyBuilt = true
|
25
29
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
+
# Add plugin's SASS directory so site's list of SASS directories
|
31
|
+
if site.config["sass"].nil? || site.config["sass"].empty?
|
32
|
+
site.config["sass"] = Hash.new
|
33
|
+
end
|
34
|
+
if site.config["sass"]["load_paths"].nil? || site.config["sass"]["load_paths"].empty?
|
35
|
+
site.config["sass"]["load_paths"] = ["_sass", (File.expand_path "../../_sass", File.dirname(__FILE__))]
|
36
|
+
else
|
37
|
+
site.config["sass"]["load_paths"] << (File.expand_path "../../_sass", File.dirname(__FILE__))
|
38
|
+
end
|
30
39
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
site.config["sass"]["load_paths"] = ["_sass", (File.expand_path "../../_sass", File.dirname(__FILE__))]
|
37
|
-
else
|
38
|
-
site.config["sass"]["load_paths"] << (File.expand_path "../../_sass", File.dirname(__FILE__))
|
39
|
-
end
|
40
|
+
# Enable pagination
|
41
|
+
if site.config["pagination"].nil? || site.config["pagination"].empty?
|
42
|
+
site.config["pagination"] = Hash.new
|
43
|
+
end
|
44
|
+
site.config["pagination"]["enabled"] = true
|
40
45
|
|
41
|
-
|
42
|
-
if site.config["pagination"].nil? || site.config["pagination"].empty?
|
43
|
-
site.config["pagination"] = Hash.new
|
44
|
-
end
|
45
|
-
site.config["pagination"]["enabled"] = true
|
46
|
+
index = FDroid::IndexV1.download(site.config["fdroid-repo"], site.active_lang || 'en_US')
|
46
47
|
|
47
|
-
|
48
|
+
Jekyll::LunrJsSearch::Indexer.new.generate(site, index.apps)
|
48
49
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
end
|
67
|
-
end
|
50
|
+
# Generate detail page for every package
|
51
|
+
site.collections["packages"] = Collection.new(site, "packages")
|
52
|
+
index.apps.each do |package|
|
53
|
+
# This page needs to be created twice, once for site.pages, and once for site.collections.
|
54
|
+
# If not, then the i18n code in jekyll-polyglot will end up processing the page twice, as
|
55
|
+
# it iterates over all pages and all packages. The end result is a double prefix for "/en/en"
|
56
|
+
# for any links in the page.
|
57
|
+
# https://gitlab.com/fdroid/jekyll-fdroid/issues/38
|
58
|
+
site.pages << FDroidPackageDetailPage.new(site, site.source, package)
|
59
|
+
site.collections["packages"].docs << FDroidPackageDetailPage.new(site, site.source, package)
|
60
|
+
end
|
61
|
+
# Generate browsing pages
|
62
|
+
site.includes_load_paths << (File.expand_path "../../_includes", File.dirname(__FILE__))
|
63
|
+
site.pages << FDroidBrowsingPage.new(site, site.source)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
68
67
|
end
|
@@ -16,12 +16,10 @@
|
|
16
16
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
|
18
18
|
module Jekyll
|
19
|
-
|
20
19
|
class FDroidPackageDetailPage < ReadYamlPage
|
21
|
-
|
22
20
|
# @param [Jekyll::Site] site
|
23
21
|
# @param [string] base
|
24
|
-
# @param [
|
22
|
+
# @param [FDroid::App] package
|
25
23
|
def initialize(site, base, package)
|
26
24
|
@site = site
|
27
25
|
@base = base
|
@@ -18,22 +18,24 @@
|
|
18
18
|
require_relative '../fdroid/IndexV1'
|
19
19
|
|
20
20
|
module Jekyll
|
21
|
+
# Used to output the repo name/timestamp used to generate this F-Droid site.
|
22
|
+
class FDroidRepoInfoTag < Liquid::Tag
|
23
|
+
@@repotag = ''
|
21
24
|
|
22
|
-
|
23
|
-
|
25
|
+
def initialize(tag_name, text, tokens)
|
26
|
+
super
|
27
|
+
end
|
24
28
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
end
|
29
|
+
def render(context)
|
30
|
+
if @@repotag == ''
|
31
|
+
site = context.registers[:site]
|
32
|
+
url = site.config['fdroid-repo']
|
33
|
+
index = FDroid::IndexV1.download(url, 'en')
|
34
|
+
@@repotag = "#{index.repo.name} #{index.repo.date}"
|
35
|
+
end
|
36
|
+
return @@repotag
|
37
|
+
end
|
38
|
+
end
|
37
39
|
end
|
38
40
|
|
39
41
|
Liquid::Template.register_tag('fdroid_repo_info', Jekyll::FDroidRepoInfoTag)
|
@@ -16,71 +16,81 @@
|
|
16
16
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
|
18
18
|
module Jekyll
|
19
|
+
class SearchForm
|
20
|
+
def self.render_form(context, search_form_template_path, result_item_template_contents)
|
21
|
+
site = context.registers[:site]
|
22
|
+
repo_timestamp = FDroid::IndexV1.download(site.config['fdroid-repo'], 'en').repo.timestamp
|
19
23
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
24
|
+
context['result_item_template'] = result_item_template_contents
|
25
|
+
|
26
|
+
# If an app developer is able to guess this at the time that they write their app descriptions, then they could
|
27
|
+
# potentially try and inject a new template which hijacks the search results template. This is due to the way in
|
28
|
+
# which JS is used to find the relevant `<script type="x-tmpl-mustache" id="...-{{ search_id }}">` template.
|
29
|
+
# Thus, make it random, and include the repo timestamp. They'd need to guess a random number correctly, and it
|
30
|
+
# will change every day that the repo is republished.
|
31
|
+
context['search_id'] = "#{rand(1000000)}.#{repo_timestamp}"
|
32
|
+
|
33
|
+
context['repo_timestamp'] = repo_timestamp
|
34
|
+
|
35
|
+
template = Liquid::Template.parse(IO.read((File.expand_path(search_form_template_path, File.dirname(__FILE__)))))
|
36
|
+
template.render(context)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# As the user types, a list of results is shown below the text input (floating above other content).
|
41
|
+
# When an item is selected, it will navigate to that packages page.
|
42
|
+
# Designed to be used in a sidebar widget.
|
43
|
+
|
44
|
+
class DropDownWithTemplate < Liquid::Block
|
45
|
+
def render(context)
|
46
|
+
search_form_template_path = "../../_layouts/search-autocomplete.html"
|
47
|
+
SearchForm.render_form(context, search_form_template_path, super.to_s)
|
39
48
|
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class DefaultDropDown < Liquid::Tag
|
52
|
+
def render(context)
|
53
|
+
search_form_template_path = "../../_layouts/search-autocomplete.html"
|
54
|
+
|
55
|
+
result_item_template_path = "../../_includes/search-autocomplete-default-result-template.html"
|
56
|
+
result_item_template = IO.read((File.expand_path(result_item_template_path, File.dirname(__FILE__))))
|
40
57
|
|
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
|
-
result_item_template_path = "../../_includes/search-full-default-result-template.html"
|
78
|
-
result_item_template = IO.read((File.expand_path(result_item_template_path, File.dirname(__FILE__))))
|
79
|
-
|
80
|
-
context['empty_search_id'] = @empty_search_id
|
81
|
-
SearchForm.render_form(context, search_form_template_path, result_item_template)
|
82
|
-
end
|
83
|
-
end
|
58
|
+
SearchForm.render_form(context, search_form_template_path, result_item_template)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# As the user types, a div is populated with search results.
|
63
|
+
# Differs from DropDownAutocomplete in that once you move focus away from the text input, the results
|
64
|
+
# are still displayed.
|
65
|
+
# Designed for a fully fledged search form on its own page.
|
66
|
+
|
67
|
+
# For each result result, this will render the template found between
|
68
|
+
# the {% fdroid_search_full_with_template %}{% endfdroid_search_full_with_template %} tags.
|
69
|
+
class FullSearchWithTemplate < Liquid::Block
|
70
|
+
def render(context)
|
71
|
+
search_form_template_path = "../../_layouts/search-full.html"
|
72
|
+
SearchForm.render_form(context, search_form_template_path, super.to_s)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# For each search result, this will render the contents of
|
77
|
+
# "_includes/search-full-default-result-template.html" from this plugin.
|
78
|
+
class DefaultFullSearch < Liquid::Tag
|
79
|
+
def initialize(tag_name, argument, tokens)
|
80
|
+
super
|
81
|
+
@empty_search_id = argument.strip
|
82
|
+
end
|
83
|
+
|
84
|
+
def render(context)
|
85
|
+
search_form_template_path = "../../_layouts/search-full.html"
|
86
|
+
|
87
|
+
result_item_template_path = "../../_includes/search-full-default-result-template.html"
|
88
|
+
result_item_template = IO.read((File.expand_path(result_item_template_path, File.dirname(__FILE__))))
|
89
|
+
|
90
|
+
context['empty_search_id'] = @empty_search_id
|
91
|
+
SearchForm.render_form(context, search_form_template_path, result_item_template)
|
92
|
+
end
|
93
|
+
end
|
84
94
|
end
|
85
95
|
|
86
96
|
Liquid::Template.register_tag('fdroid_search_autocomplete', Jekyll::DefaultDropDown)
|
data/lib/jekyll/ReadYamlPage.rb
CHANGED
@@ -18,23 +18,22 @@
|
|
18
18
|
# Found at https://github.com/ggreer/jekyll-gallery-generator/blob/master/lib/jekyll-gallery-generator.rb#L69
|
19
19
|
|
20
20
|
module Jekyll
|
21
|
+
class ReadYamlPage < Page
|
22
|
+
# We need do define it ourself because the templates are in the plugin's directory
|
23
|
+
def read_yaml(base, name, opts = {})
|
24
|
+
begin
|
25
|
+
self.content = File.read(File.join(base.to_s, name.to_s), (site ? site.file_read_opts : {}).merge(opts))
|
26
|
+
if content =~ /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m
|
27
|
+
self.content = $POSTMATCH
|
28
|
+
self.data = SafeYAML.load($1)
|
29
|
+
end
|
30
|
+
rescue SyntaxError => e
|
31
|
+
Jekyll.logger.warn "YAML Exception reading #{File.join(base.to_s, name.to_s)}: #{e.message}"
|
32
|
+
rescue Exception => e
|
33
|
+
Jekyll.logger.warn "Error reading file #{File.join(base.to_s, name.to_s)}: #{e.message}"
|
34
|
+
end
|
21
35
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
begin
|
26
|
-
self.content = File.read(File.join(base.to_s, name.to_s), (site ? site.file_read_opts : {}).merge(opts))
|
27
|
-
if content =~ /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m
|
28
|
-
self.content = $POSTMATCH
|
29
|
-
self.data = SafeYAML.load($1)
|
30
|
-
end
|
31
|
-
rescue SyntaxError => e
|
32
|
-
Jekyll.logger.warn "YAML Exception reading #{File.join(base.to_s, name.to_s)}: #{e.message}"
|
33
|
-
rescue Exception => e
|
34
|
-
Jekyll.logger.warn "Error reading file #{File.join(base.to_s, name.to_s)}: #{e.message}"
|
35
|
-
end
|
36
|
-
|
37
|
-
self.data ||= {}
|
38
|
-
end
|
39
|
-
end
|
36
|
+
self.data ||= {}
|
37
|
+
end
|
38
|
+
end
|
40
39
|
end
|
data/lib/lunr/Javascript.rb
CHANGED
@@ -8,11 +8,11 @@ require "v8"
|
|
8
8
|
require "json"
|
9
9
|
|
10
10
|
class V8::Object
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
def to_json
|
12
|
+
@context['JSON']['stringify'].call(self)
|
13
|
+
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
15
|
+
def to_hash
|
16
|
+
JSON.parse(to_json, :max_nesting => false)
|
17
|
+
end
|
18
|
+
end
|
data/lib/lunr/LunrIndexer.rb
CHANGED
@@ -15,7 +15,6 @@ require 'v8'
|
|
15
15
|
module Jekyll
|
16
16
|
module LunrJsSearch
|
17
17
|
class Indexer
|
18
|
-
|
19
18
|
# @param [Jekyll::Site] site
|
20
19
|
# @param [Array<App>] packages
|
21
20
|
# @return [Object]
|
@@ -44,11 +43,11 @@ module Jekyll
|
|
44
43
|
|
45
44
|
packages.each_with_index do |package, i|
|
46
45
|
doc = {
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
46
|
+
'id' => i,
|
47
|
+
'packageName' => package.package_name,
|
48
|
+
'icon' => package.icon,
|
49
|
+
'name' => package.name,
|
50
|
+
'summary' => package.summary
|
52
51
|
}
|
53
52
|
|
54
53
|
ctx['builder'].add(doc)
|
@@ -63,22 +62,23 @@ module Jekyll
|
|
63
62
|
filename = File.join(@js_dir, 'index.json')
|
64
63
|
|
65
64
|
total = {
|
66
|
-
|
67
|
-
|
65
|
+
"docs" => @docs,
|
66
|
+
"index" => @index.to_hash
|
68
67
|
}
|
69
68
|
|
70
69
|
filepath = File.join(site.dest, filename)
|
71
|
-
File.open(filepath, "w") {|f| f.write(JSON.dump(total))}
|
70
|
+
File.open(filepath, "w") { |f| f.write(JSON.dump(total)) }
|
72
71
|
Jekyll.logger.info "Lunr:", "Index ready (lunr.js v#{@lunr_version})"
|
73
72
|
added_files = [filename]
|
74
73
|
|
75
74
|
site_js = File.join(site.dest, @js_dir)
|
76
75
|
extras = [
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
76
|
+
'assets/fdroid-search-autocomplete.js',
|
77
|
+
'assets/fdroid-search-autocomplete-init.js',
|
78
|
+
'bower_components/lunr.js/lunr.js',
|
79
|
+
'bower_components/mustache.js/mustache.min.js',
|
80
|
+
'bower_components/awesomplete/awesomplete.min.js',
|
81
|
+
'bower_components/awesomplete/awesomplete.css'
|
82
82
|
]
|
83
83
|
Jekyll.logger.info "Lunr:", "Added required assets to #{@js_dir}"
|
84
84
|
extras.each do |path|
|
data/lib/lunr/SearchIndexFile.rb
CHANGED
@@ -5,12 +5,12 @@
|
|
5
5
|
#
|
6
6
|
|
7
7
|
module Jekyll
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
8
|
+
module LunrJsSearch
|
9
|
+
class SearchIndexFile < Jekyll::StaticFile
|
10
|
+
# Override write as the index.json index file has already been created
|
11
|
+
def write(dest)
|
12
|
+
true
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jekyll-fdroid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: '1.1'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nico Alt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jekyll-include-cache
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.50.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.50.0
|
97
111
|
description: Browse packages of a F-Droid repository.
|
98
112
|
email: nicoalt@posteo.org
|
99
113
|
executables: []
|
@@ -138,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
152
|
version: '0'
|
139
153
|
requirements: []
|
140
154
|
rubyforge_project:
|
141
|
-
rubygems_version: 2.
|
155
|
+
rubygems_version: 2.7.7
|
142
156
|
signing_key:
|
143
157
|
specification_version: 4
|
144
158
|
summary: F-Droid - Free and Open Source Android App Repository
|