floss_funding 1.0.0.pre.alpha.1
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
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +25 -0
- data/CODE_OF_CONDUCT.md +135 -0
- data/CONTRIBUTING.md +134 -0
- data/LICENSE.txt +19 -0
- data/README.md +507 -0
- data/SECURITY.md +21 -0
- data/lib/floss_funding/check.rb +197 -0
- data/lib/floss_funding/config.rb +215 -0
- data/lib/floss_funding/poke.rb +111 -0
- data/lib/floss_funding/under_bar.rb +57 -0
- data/lib/floss_funding/version.rb +10 -0
- data/lib/floss_funding.rb +301 -0
- data.tar.gz.sig +0 -0
- metadata +267 -0
- metadata.gz.sig +3 -0
@@ -0,0 +1,301 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# std libs
|
4
|
+
require "openssl"
|
5
|
+
require "thread" # For Mutex
|
6
|
+
|
7
|
+
# external gems
|
8
|
+
require "month/serializer"
|
9
|
+
Month.include(Month::Serializer)
|
10
|
+
|
11
|
+
# Just the version from this gem
|
12
|
+
require "floss_funding/version"
|
13
|
+
|
14
|
+
# Now declare some constants
|
15
|
+
module FlossFunding
|
16
|
+
# Base error class for all FlossFunding-specific failures.
|
17
|
+
class Error < StandardError; end
|
18
|
+
|
19
|
+
# Unpaid activation option intended for open-source and not-for-profit use.
|
20
|
+
# @return [String]
|
21
|
+
FREE_AS_IN_BEER = "Free-as-in-beer"
|
22
|
+
|
23
|
+
# Unpaid activation option acknowledging commercial use without payment.
|
24
|
+
# @return [String]
|
25
|
+
BUSINESS_IS_NOT_GOOD_YET = "Business-is-not-good-yet"
|
26
|
+
|
27
|
+
# Activation option to explicitly opt out of funding prompts for a namespace.
|
28
|
+
# @return [String]
|
29
|
+
NOT_FINANCIALLY_SUPPORTING = "Not-financially-supporting"
|
30
|
+
|
31
|
+
# First month index against which base words are validated.
|
32
|
+
# Do not change once released as it would invalidate existing activation keys.
|
33
|
+
# @return [Integer]
|
34
|
+
START_MONTH = Month.new(2025, 7).to_i # Don't change this, not ever!
|
35
|
+
|
36
|
+
# Absolute path to the base words list used for paid activation validation.
|
37
|
+
# @return [String]
|
38
|
+
BASE_WORDS_PATH = File.expand_path("../../base.txt", __FILE__)
|
39
|
+
|
40
|
+
# Number of hex characters required for a paid activation key (64 = 256 bits).
|
41
|
+
# @return [Integer]
|
42
|
+
EIGHT_BYTES = 64
|
43
|
+
|
44
|
+
# Format for a paid activation key (64 hex chars).
|
45
|
+
# @return [Regexp]
|
46
|
+
HEX_LICENSE_RULE = /\A[0-9a-fA-F]{#{EIGHT_BYTES}}\z/
|
47
|
+
|
48
|
+
# Footer text appended to messages shown to users when activation is missing
|
49
|
+
# or invalid. Includes gem version and attribution.
|
50
|
+
# @return [String]
|
51
|
+
FOOTER = <<-FOOTER
|
52
|
+
=====================================================================================
|
53
|
+
- Please buy FLOSS "peace-of-mind" activation keys to support open source developers.
|
54
|
+
floss_funding v#{::FlossFunding::Version::VERSION} is made with ❤️ in 🇺🇸 & 🇮🇩 by Galtzo FLOSS (galtzo.com)
|
55
|
+
FOOTER
|
56
|
+
|
57
|
+
# Thread-safe access to activated and unactivated libraries
|
58
|
+
# These track which modules/gems have included the Poke module
|
59
|
+
# and whether they have valid activation keys or not
|
60
|
+
# rubocop:disable ThreadSafety/MutableClassInstanceVariable
|
61
|
+
@mutex = Mutex.new
|
62
|
+
@activated = [] # List of libraries with valid activation
|
63
|
+
@unactivated = [] # List of libraries without valid activation
|
64
|
+
@configurations = {} # Hash to store configurations for each library
|
65
|
+
@env_var_names = {} # Map of namespace => ENV var name used during setup
|
66
|
+
@activation_occurrences = [] # Tracks every successful activation occurrence (may include duplicates per namespace)
|
67
|
+
# rubocop:enable ThreadSafety/MutableClassInstanceVariable
|
68
|
+
|
69
|
+
class << self
|
70
|
+
# Provides access to the mutex for thread synchronization
|
71
|
+
attr_reader :mutex
|
72
|
+
|
73
|
+
# New name: activated (preferred)
|
74
|
+
# @return [Array<String>]
|
75
|
+
def activated
|
76
|
+
mutex.synchronize { @activated.dup }
|
77
|
+
end
|
78
|
+
|
79
|
+
# New name: activated= (preferred)
|
80
|
+
# @param value [Array<String>]
|
81
|
+
def activated=(value)
|
82
|
+
mutex.synchronize { @activated = value }
|
83
|
+
end
|
84
|
+
|
85
|
+
# New name: unactivated (preferred)
|
86
|
+
# @return [Array<String>]
|
87
|
+
def unactivated
|
88
|
+
mutex.synchronize { @unactivated.dup }
|
89
|
+
end
|
90
|
+
|
91
|
+
# New name: unactivated= (preferred)
|
92
|
+
# @param value [Array<String>]
|
93
|
+
def unactivated=(value)
|
94
|
+
mutex.synchronize { @unactivated = value }
|
95
|
+
end
|
96
|
+
|
97
|
+
# Thread-safely adds a library to the activated list
|
98
|
+
# Ensures no duplicates are added
|
99
|
+
# @param library [String] Namespace of the library to add
|
100
|
+
def add_activated(library)
|
101
|
+
mutex.synchronize { @activated << library unless @activated.include?(library) }
|
102
|
+
end
|
103
|
+
|
104
|
+
# Thread-safely adds a library to the unactivated list
|
105
|
+
# Ensures no duplicates are added
|
106
|
+
# @param library [String] Namespace of the library to add
|
107
|
+
def add_unactivated(library)
|
108
|
+
mutex.synchronize { @unactivated << library unless @unactivated.include?(library) }
|
109
|
+
end
|
110
|
+
|
111
|
+
# Thread-safe accessor for the configurations hash
|
112
|
+
# Returns a duplicate to prevent external modification
|
113
|
+
# @return [Hash] Hash of library configurations
|
114
|
+
def configurations
|
115
|
+
mutex.synchronize { @configurations.dup }
|
116
|
+
end
|
117
|
+
|
118
|
+
# Thread-safe getter for a specific library's configuration
|
119
|
+
# @param library [String] Namespace of the library
|
120
|
+
# @return [Hash, nil] Configuration for the library or nil if not found
|
121
|
+
def configuration(library)
|
122
|
+
mutex.synchronize do
|
123
|
+
value = @configurations[library]
|
124
|
+
value ? value.dup : nil
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Thread-safe setter for a library's configuration
|
129
|
+
# @param library [String] Namespace of the library
|
130
|
+
# @param config [Hash] Configuration for the library
|
131
|
+
def set_configuration(library, config)
|
132
|
+
mutex.synchronize do
|
133
|
+
existing = @configurations[library] || {}
|
134
|
+
merged = {}
|
135
|
+
# Ensure all known keys are arrays and merged
|
136
|
+
keys = (existing.keys + config.keys).uniq
|
137
|
+
keys.each do |k|
|
138
|
+
merged[k] = []
|
139
|
+
merged[k].concat(Array(existing[k])) if existing.key?(k)
|
140
|
+
merged[k].concat(Array(config[k])) if config.key?(k)
|
141
|
+
merged[k] = merged[k].compact.flatten.uniq
|
142
|
+
end
|
143
|
+
@configurations[library] = merged
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Thread-safe setter for ENV var name used by a library
|
148
|
+
# @param library [String]
|
149
|
+
# @param env_var_name [String]
|
150
|
+
def set_env_var_name(library, env_var_name)
|
151
|
+
mutex.synchronize { @env_var_names[library] = env_var_name }
|
152
|
+
end
|
153
|
+
|
154
|
+
# Thread-safe getter for ENV var name used by a library
|
155
|
+
# @param library [String]
|
156
|
+
# @return [String, nil]
|
157
|
+
def env_var_name_for(library)
|
158
|
+
mutex.synchronize { @env_var_names[library] }
|
159
|
+
end
|
160
|
+
|
161
|
+
# Thread-safe getter for all ENV var names
|
162
|
+
# @return [Hash{String=>String}]
|
163
|
+
def env_var_names
|
164
|
+
mutex.synchronize { @env_var_names.dup }
|
165
|
+
end
|
166
|
+
|
167
|
+
# Thread-safe getter for all activation occurrences (each successful activation event)
|
168
|
+
# @return [Array<String>] list of namespaces for each activation occurrence
|
169
|
+
def activation_occurrences
|
170
|
+
mutex.synchronize { @activation_occurrences.dup }
|
171
|
+
end
|
172
|
+
|
173
|
+
# Record a single activation occurrence (may include duplicates per namespace)
|
174
|
+
# @param namespace [String]
|
175
|
+
def add_activation_occurrence(namespace)
|
176
|
+
mutex.synchronize { @activation_occurrences << namespace }
|
177
|
+
end
|
178
|
+
|
179
|
+
# Reads the first N lines from the base words file to validate paid activation keys.
|
180
|
+
#
|
181
|
+
# @param num_valid_words [Integer] number of words to read from the word list
|
182
|
+
# @return [Array<String>] the first N words; empty when N is nil or zero
|
183
|
+
def base_words(num_valid_words)
|
184
|
+
return [] if num_valid_words.nil? || num_valid_words.zero?
|
185
|
+
File.open(::FlossFunding::BASE_WORDS_PATH, "r") do |file|
|
186
|
+
lines = []
|
187
|
+
num_valid_words.times do
|
188
|
+
line = file.gets
|
189
|
+
break if line.nil?
|
190
|
+
lines << line.chomp
|
191
|
+
end
|
192
|
+
lines
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# Finally, the core of this gem
|
199
|
+
require "floss_funding/under_bar"
|
200
|
+
require "floss_funding/config"
|
201
|
+
require "floss_funding/poke"
|
202
|
+
# require "floss_funding/check" # Lazy loaded at runtime
|
203
|
+
|
204
|
+
# Dog Food
|
205
|
+
FlossFunding.send(:include, FlossFunding::Poke.new(__FILE__, "FlossFunding"))
|
206
|
+
|
207
|
+
# :nocov:
|
208
|
+
# Add END hook to display summary and a consolidated blurb for usage without activation key
|
209
|
+
# This hook runs when the Ruby process terminates
|
210
|
+
at_exit {
|
211
|
+
activated = FlossFunding.activated
|
212
|
+
unactivated = FlossFunding.unactivated
|
213
|
+
activated_count = activated.size
|
214
|
+
unactivated_count = unactivated.size
|
215
|
+
occurrences_count = FlossFunding.activation_occurrences.size
|
216
|
+
|
217
|
+
# Compute how many distinct gem names are covered by funding.
|
218
|
+
# Only consider namespaces that ended up ACTIVATED; unactivated are excluded by design.
|
219
|
+
# Shared namespaces (e.g., final 10) will still contribute all gem names because configs merge per-namespace.
|
220
|
+
configs = FlossFunding.configurations
|
221
|
+
observed_namespaces = activated.uniq
|
222
|
+
funded_gem_names = observed_namespaces.flat_map { |ns|
|
223
|
+
cfg = configs[ns]
|
224
|
+
cfg.is_a?(Hash) ? Array(cfg["gem_name"]) : []
|
225
|
+
}.compact.uniq
|
226
|
+
funded_gem_count = funded_gem_names.size
|
227
|
+
|
228
|
+
# Summary section
|
229
|
+
if activated_count > 0 || unactivated_count > 0
|
230
|
+
stars = ("⭐️" * activated_count)
|
231
|
+
mimes = ("🫥" * unactivated_count)
|
232
|
+
summary_lines = []
|
233
|
+
summary_lines << "\nFLOSS Funding Summary:"
|
234
|
+
summary_lines << "Activated libraries (#{activated_count}): #{stars}" if activated_count > 0
|
235
|
+
# Also show total successful inclusions (aka per-gem activations), which may exceed unique namespaces
|
236
|
+
summary_lines << "Activated gems (#{occurrences_count})" if occurrences_count > 0
|
237
|
+
# Show how many distinct gem names are covered by funding
|
238
|
+
summary_lines << "Gems covered by funding (#{funded_gem_count})" if funded_gem_count > 0
|
239
|
+
summary_lines << "Unactivated libraries (#{unactivated_count}): #{mimes}" if unactivated_count > 0
|
240
|
+
summary = summary_lines.join("\n") + "\n\n"
|
241
|
+
puts summary
|
242
|
+
end
|
243
|
+
|
244
|
+
# Emit a single, consolidated blurb for all unactivated namespaces
|
245
|
+
if unactivated_count > 0
|
246
|
+
# Gather data needed for each namespace
|
247
|
+
configs = FlossFunding.configurations
|
248
|
+
env_map = FlossFunding.env_var_names
|
249
|
+
|
250
|
+
details = +""
|
251
|
+
details << <<-HEADER
|
252
|
+
==============================================================
|
253
|
+
Unremunerated use of the following namespaces was detected:
|
254
|
+
HEADER
|
255
|
+
|
256
|
+
unactivated.each do |ns|
|
257
|
+
config = configs[ns] || {}
|
258
|
+
funding_url = Array(config["floss_funding_url"]).first || "https://floss-funding.dev"
|
259
|
+
suggested_amount = Array(config["suggested_donation_amount"]).first || 5
|
260
|
+
env_name = env_map[ns] || "FLOSS_FUNDING_#{ns.gsub(/[^A-Za-z0-9]+/, "_").upcase}"
|
261
|
+
opt_out = "#{FlossFunding::NOT_FINANCIALLY_SUPPORTING}-#{ns}"
|
262
|
+
details << <<-NS
|
263
|
+
- Namespace: #{ns}
|
264
|
+
ENV Variable: #{env_name}
|
265
|
+
Suggested donation amount: $#{suggested_amount}
|
266
|
+
Funding URL: #{funding_url}
|
267
|
+
Opt-out key: "#{opt_out}"
|
268
|
+
|
269
|
+
NS
|
270
|
+
end
|
271
|
+
|
272
|
+
details << <<-BODY
|
273
|
+
FLOSS Funding relies on empathy, respect, honor, and annoyance of the most extreme mildness.
|
274
|
+
👉️ No network calls. 👉️ No tracking. 👉️ No oversight. 👉️ Minimal crypto hashing.
|
275
|
+
|
276
|
+
Options:
|
277
|
+
1. 🌐 Donate or sponsor at the funding URLs above, and affirm on your honor your donor or sponsor status.
|
278
|
+
a. Receive ethically-sourced, buy-once, activation key for each namespace.
|
279
|
+
b. Suggested donation amounts are listed above.
|
280
|
+
|
281
|
+
2. 🪄 If open source, or not-for-profit, continue to use for free, with activation key: "#{FlossFunding::FREE_AS_IN_BEER}".
|
282
|
+
|
283
|
+
3. 🏦 If commercial, continue to use for free, & feel a bit naughty, with activation key: "#{FlossFunding::BUSINESS_IS_NOT_GOOD_YET}".
|
284
|
+
|
285
|
+
4. ✖️ Disable activation key checks using the per-namespace opt-out keys listed above.
|
286
|
+
|
287
|
+
Then, before loading the gems, set the ENV variables listed above to your chosen key.
|
288
|
+
Or in shell / dotenv / direnv, e.g.:
|
289
|
+
BODY
|
290
|
+
|
291
|
+
unactivated.each do |ns|
|
292
|
+
env_name = env_map[ns] || "FLOSS_FUNDING_#{ns.gsub(/[^A-Za-z0-9]+/, "_").upcase}"
|
293
|
+
details << " export #{env_name}=\"<your key>\"\n"
|
294
|
+
end
|
295
|
+
|
296
|
+
details << FlossFunding::FOOTER
|
297
|
+
|
298
|
+
puts details
|
299
|
+
end
|
300
|
+
}
|
301
|
+
# :nocov:
|
data.tar.gz.sig
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,267 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: floss_funding
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0.pre.alpha.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Peter H. Boling
|
8
|
+
bindir: exe
|
9
|
+
cert_chain:
|
10
|
+
- |
|
11
|
+
-----BEGIN CERTIFICATE-----
|
12
|
+
MIIEgDCCAuigAwIBAgIBATANBgkqhkiG9w0BAQsFADBDMRUwEwYDVQQDDAxwZXRl
|
13
|
+
ci5ib2xpbmcxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkW
|
14
|
+
A2NvbTAeFw0yNTA1MDQxNTMzMDlaFw00NTA0MjkxNTMzMDlaMEMxFTATBgNVBAMM
|
15
|
+
DHBldGVyLmJvbGluZzEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPy
|
16
|
+
LGQBGRYDY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAruUoo0WA
|
17
|
+
uoNuq6puKWYeRYiZekz/nsDeK5x/0IEirzcCEvaHr3Bmz7rjo1I6On3gGKmiZs61
|
18
|
+
LRmQ3oxy77ydmkGTXBjruJB+pQEn7UfLSgQ0xa1/X3kdBZt6RmabFlBxnHkoaGY5
|
19
|
+
mZuZ5+Z7walmv6sFD9ajhzj+oIgwWfnEHkXYTR8I6VLN7MRRKGMPoZ/yvOmxb2DN
|
20
|
+
coEEHWKO9CvgYpW7asIihl/9GMpKiRkcYPm9dGQzZc6uTwom1COfW0+ZOFrDVBuV
|
21
|
+
FMQRPswZcY4Wlq0uEBLPU7hxnCL9nKK6Y9IhdDcz1mY6HZ91WImNslOSI0S8hRpj
|
22
|
+
yGOWxQIhBT3fqCBlRIqFQBudrnD9jSNpSGsFvbEijd5ns7Z9ZMehXkXDycpGAUj1
|
23
|
+
to/5cuTWWw1JqUWrKJYoifnVhtE1o1DZ+LkPtWxHtz5kjDG/zR3MG0Ula0UOavlD
|
24
|
+
qbnbcXPBnwXtTFeZ3C+yrWpE4pGnl3yGkZj9SMTlo9qnTMiPmuWKQDatAgMBAAGj
|
25
|
+
fzB9MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQE8uWvNbPVNRXZ
|
26
|
+
HlgPbc2PCzC4bjAhBgNVHREEGjAYgRZwZXRlci5ib2xpbmdAZ21haWwuY29tMCEG
|
27
|
+
A1UdEgQaMBiBFnBldGVyLmJvbGluZ0BnbWFpbC5jb20wDQYJKoZIhvcNAQELBQAD
|
28
|
+
ggGBAJbnUwfJQFPkBgH9cL7hoBfRtmWiCvdqdjeTmi04u8zVNCUox0A4gT982DE9
|
29
|
+
wmuN12LpdajxZONqbXuzZvc+nb0StFwmFYZG6iDwaf4BPywm2e/Vmq0YG45vZXGR
|
30
|
+
L8yMDSK1cQXjmA+ZBKOHKWavxP6Vp7lWvjAhz8RFwqF9GuNIdhv9NpnCAWcMZtpm
|
31
|
+
GUPyIWw/Cw/2wZp74QzZj6Npx+LdXoLTF1HMSJXZ7/pkxLCsB8m4EFVdb/IrW/0k
|
32
|
+
kNSfjtAfBHO8nLGuqQZVH9IBD1i9K6aSs7pT6TW8itXUIlkIUI2tg5YzW6OFfPzq
|
33
|
+
QekSkX3lZfY+HTSp/o+YvKkqWLUV7PQ7xh1ZYDtocpaHwgxe/j3bBqHE+CUPH2vA
|
34
|
+
0V/FwdTRWcwsjVoOJTrYcff8pBZ8r2MvtAc54xfnnhGFzeRHfcltobgFxkAXdE6p
|
35
|
+
DVjBtqT23eugOqQ73umLcYDZkc36vnqGxUBSsXrzY9pzV5gGr2I8YUxMqf6ATrZt
|
36
|
+
L9nRqA==
|
37
|
+
-----END CERTIFICATE-----
|
38
|
+
date: 2025-08-10 00:00:00.000000000 Z
|
39
|
+
dependencies:
|
40
|
+
- !ruby/object:Gem::Dependency
|
41
|
+
name: month-serializer
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.0'
|
47
|
+
- - '='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: 1.0.1
|
50
|
+
type: :runtime
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - "~>"
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '1.0'
|
57
|
+
- - '='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 1.0.1
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: stone_checksums
|
62
|
+
requirement: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '1.0'
|
67
|
+
type: :development
|
68
|
+
prerelease: false
|
69
|
+
version_requirements: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '1.0'
|
74
|
+
- !ruby/object:Gem::Dependency
|
75
|
+
name: appraisal2
|
76
|
+
requirement: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '3.0'
|
81
|
+
type: :development
|
82
|
+
prerelease: false
|
83
|
+
version_requirements: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '3.0'
|
88
|
+
- !ruby/object:Gem::Dependency
|
89
|
+
name: rspec
|
90
|
+
requirement: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - "~>"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '3.13'
|
95
|
+
type: :development
|
96
|
+
prerelease: false
|
97
|
+
version_requirements: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - "~>"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '3.13'
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: rspec-block_is_expected
|
104
|
+
requirement: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - "~>"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '1.0'
|
109
|
+
type: :development
|
110
|
+
prerelease: false
|
111
|
+
version_requirements: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - "~>"
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '1.0'
|
116
|
+
- !ruby/object:Gem::Dependency
|
117
|
+
name: rspec_junit_formatter
|
118
|
+
requirement: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - "~>"
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0.6'
|
123
|
+
type: :development
|
124
|
+
prerelease: false
|
125
|
+
version_requirements: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - "~>"
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0.6'
|
130
|
+
- !ruby/object:Gem::Dependency
|
131
|
+
name: rspec-stubbed_env
|
132
|
+
requirement: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - "~>"
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '1.0'
|
137
|
+
type: :development
|
138
|
+
prerelease: false
|
139
|
+
version_requirements: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - "~>"
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '1.0'
|
144
|
+
- !ruby/object:Gem::Dependency
|
145
|
+
name: silent_stream
|
146
|
+
requirement: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - "~>"
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '1.0'
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: 1.0.11
|
154
|
+
type: :development
|
155
|
+
prerelease: false
|
156
|
+
version_requirements: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - "~>"
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '1.0'
|
161
|
+
- - ">="
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: 1.0.11
|
164
|
+
- !ruby/object:Gem::Dependency
|
165
|
+
name: timecop
|
166
|
+
requirement: !ruby/object:Gem::Requirement
|
167
|
+
requirements:
|
168
|
+
- - "~>"
|
169
|
+
- !ruby/object:Gem::Version
|
170
|
+
version: '0.9'
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: 0.9.10
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0.9'
|
181
|
+
- - ">="
|
182
|
+
- !ruby/object:Gem::Version
|
183
|
+
version: 0.9.10
|
184
|
+
- !ruby/object:Gem::Dependency
|
185
|
+
name: rake
|
186
|
+
requirement: !ruby/object:Gem::Requirement
|
187
|
+
requirements:
|
188
|
+
- - "~>"
|
189
|
+
- !ruby/object:Gem::Version
|
190
|
+
version: '13.0'
|
191
|
+
type: :development
|
192
|
+
prerelease: false
|
193
|
+
version_requirements: !ruby/object:Gem::Requirement
|
194
|
+
requirements:
|
195
|
+
- - "~>"
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: '13.0'
|
198
|
+
description: Help overlooked open source projects - the ones at the bottom of the
|
199
|
+
stack, and the dev dependencies - by funding them.
|
200
|
+
email:
|
201
|
+
- floss@galtzo.com
|
202
|
+
executables: []
|
203
|
+
extensions: []
|
204
|
+
extra_rdoc_files:
|
205
|
+
- CHANGELOG.md
|
206
|
+
- CODE_OF_CONDUCT.md
|
207
|
+
- CONTRIBUTING.md
|
208
|
+
- LICENSE.txt
|
209
|
+
- README.md
|
210
|
+
- SECURITY.md
|
211
|
+
files:
|
212
|
+
- CHANGELOG.md
|
213
|
+
- CODE_OF_CONDUCT.md
|
214
|
+
- CONTRIBUTING.md
|
215
|
+
- LICENSE.txt
|
216
|
+
- README.md
|
217
|
+
- SECURITY.md
|
218
|
+
- lib/floss_funding.rb
|
219
|
+
- lib/floss_funding/check.rb
|
220
|
+
- lib/floss_funding/config.rb
|
221
|
+
- lib/floss_funding/poke.rb
|
222
|
+
- lib/floss_funding/under_bar.rb
|
223
|
+
- lib/floss_funding/version.rb
|
224
|
+
homepage: https://github.com/galtzo-floss/floss_funding
|
225
|
+
licenses:
|
226
|
+
- MIT
|
227
|
+
metadata:
|
228
|
+
homepage_uri: https://floss-funding.galtzo.com/
|
229
|
+
source_code_uri: https://github.com/galtzo-floss/floss_funding/tree/v1.0.0.pre.alpha.1
|
230
|
+
changelog_uri: https://github.com/galtzo-floss/floss_funding/blob/v1.0.0.pre.alpha.1/CHANGELOG.md
|
231
|
+
bug_tracker_uri: https://github.com/galtzo-floss/floss_funding/issues
|
232
|
+
documentation_uri: https://www.rubydoc.info/gems/floss_funding/1.0.0.pre.alpha.1
|
233
|
+
funding_uri: https://github.com/sponsors/pboling
|
234
|
+
wiki_uri: https://github.com/galtzo-floss/floss_funding/wiki
|
235
|
+
news_uri: https://www.railsbling.com/tags/floss_funding
|
236
|
+
discord_uri: https://discord.gg/3qme4XHNKN
|
237
|
+
rubygems_mfa_required: 'true'
|
238
|
+
rdoc_options:
|
239
|
+
- "--title"
|
240
|
+
- floss_funding - Help overlooked open source projects by funding them.
|
241
|
+
- "--main"
|
242
|
+
- CHANGELOG.md
|
243
|
+
- CODE_OF_CONDUCT.md
|
244
|
+
- CONTRIBUTING.md
|
245
|
+
- LICENSE.txt
|
246
|
+
- README.md
|
247
|
+
- SECURITY.md
|
248
|
+
- "--line-numbers"
|
249
|
+
- "--inline-source"
|
250
|
+
- "--quiet"
|
251
|
+
require_paths:
|
252
|
+
- lib
|
253
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
254
|
+
requirements:
|
255
|
+
- - ">="
|
256
|
+
- !ruby/object:Gem::Version
|
257
|
+
version: 1.9.2
|
258
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
259
|
+
requirements:
|
260
|
+
- - ">="
|
261
|
+
- !ruby/object:Gem::Version
|
262
|
+
version: '0'
|
263
|
+
requirements: []
|
264
|
+
rubygems_version: 3.7.1
|
265
|
+
specification_version: 4
|
266
|
+
summary: Help overlooked open source projects by funding them.
|
267
|
+
test_files: []
|
metadata.gz.sig
ADDED