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.
@@ -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
@@ -0,0 +1,3 @@
1
+ 2�F(�^8y�*|�;���Ӧ3��8��� �% (�i<��fŌ�� ������/�z\�Q���ZO����i" 愥�N�=jy� �kȤ�� gqH 5�7�K蛵�q�*3�J�eu�?1Gk���#/OX�(��U��,o��\���[?Mn�������zw��TL*:�߹uOu�ʢ
2
+ :�����]bL%2H
3
+ ��£� K�Nv���{��i��xZ�$�MSvϵj���}t6dC9:��;