spin_rewriter 0.1.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,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 0ffd891a5f62bc5699038efba40312dd9d453615f8045ac944bcd2ddc819386e
4
+ data.tar.gz: fcb656252eecc41a050e4a726262404f76e5b73349bf4bea065de0a4514cef52
5
+ SHA512:
6
+ metadata.gz: 064b924a77c1a96d4fd4ee5517e3f6e76d1f4222bef74b54a5a9fa0bc872f54c9a1f9f22609d2b45268ba4c87c0ced83b4eed9c327362c1944c22097881e414c
7
+ data.tar.gz: 8e421a8fc6e085e6b8384dcfeb8a51fa235326174ee34d35c008a0654a1c1b13499ac1f97d79fe717125c9d90a2558bc5698463ffbc105f099a5f2d00e1e0a7a
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.5.7
7
+ before_install: gem install bundler -v 1.17.3
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in spin_rewriter.gemspec
6
+ gemspec
@@ -0,0 +1,30 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ spin_rewriter (0.1.1)
5
+ httparty (~> 0.18.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ httparty (0.18.0)
11
+ mime-types (~> 3.0)
12
+ multi_xml (>= 0.5.2)
13
+ mime-types (3.3.1)
14
+ mime-types-data (~> 3.2015)
15
+ mime-types-data (3.2020.0425)
16
+ minitest (5.10.3)
17
+ multi_xml (0.6.0)
18
+ rake (10.5.0)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ bundler (~> 1.17)
25
+ minitest (~> 5.0)
26
+ rake (~> 10.0)
27
+ spin_rewriter!
28
+
29
+ BUNDLED WITH
30
+ 1.17.3
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Christoph Wagner
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
13
+ all 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
21
+ THE SOFTWARE.
@@ -0,0 +1,67 @@
1
+ # SpinRewriter Ruby Gem
2
+
3
+ [Spin Rewriter](http://www.spinrewriter.com/) is an online
4
+ service for spinning text (synonym substitution) that creates unique version(s)
5
+ of existing text. This package provides a way to easily interact with
6
+ [SpinRewriter API](http://www.spinrewriter.com/api). Usage requires an
7
+ account, [get one here](http://www.spinrewriter.com/registration).
8
+
9
+ This gem is basically a direct port of the official [Python client](https://github.com/niteoweb/spinrewriter), including a few idiosyncracies found in the original.
10
+ It's not exactly the greatest Ruby code, but it works.
11
+
12
+ ## Features
13
+
14
+ - Supports all available API calls (`api_quota`, `text_with_spintax`, `unique_variation`, `unique_variation_from_spintax`)
15
+ - Supports the same options as the Python module
16
+
17
+ ## Installation
18
+
19
+ Add this line to your application's `Gemfile`:
20
+
21
+ ```ruby
22
+ gem 'spin_rewriter'
23
+ ```
24
+
25
+ And then execute:
26
+
27
+ $ bundle
28
+
29
+ Or install it yourself as:
30
+
31
+ $ gem install spin_rewriter
32
+
33
+ ## Usage
34
+
35
+ After installing it, this is how you use it::
36
+
37
+ Initialize SpinRewriter.
38
+
39
+ > require 'spin_rewriter'
40
+ > rewriter = SpinRewriter::Api.new('username', 'api_key')
41
+
42
+ Request processed spun text with spintax.
43
+
44
+ > text = "This is the text we want to spin."
45
+ > rewriter.text_with_spintax(text)
46
+ "{This is|This really is|That is|This can be} some text that we'd {like to
47
+ |prefer to|want to|love to} spin."
48
+
49
+ Request a unique variation of processed given text.
50
+
51
+ > rewriter.unique_variation(text)
52
+ "This really is some text that we'd love to spin."
53
+
54
+
55
+ ## Development
56
+
57
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
58
+
59
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
60
+
61
+ ## Contributing
62
+
63
+ Bug reports and pull requests are welcome on GitHub at https://github.com/PandaWhisperer/spin_rewriter.
64
+
65
+ ## License
66
+
67
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "spin_rewriter"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,6 @@
1
+ require "spin_rewriter/errors"
2
+ require "spin_rewriter/version"
3
+ require "spin_rewriter/api"
4
+
5
+ module SpinRewriter
6
+ end
@@ -0,0 +1,299 @@
1
+ require 'httparty'
2
+ require 'json'
3
+
4
+ module SpinRewriter
5
+ class Api
6
+ include HTTParty
7
+
8
+ class << self
9
+ private
10
+
11
+ # Helper method to create named tuples
12
+ def named_tuple(name, keys, values = keys)
13
+ Struct.new(name, *keys.map(&:to_sym)).new(*values.map(&:to_s))
14
+ end
15
+ end
16
+
17
+ # URL for invoking the API
18
+ URL = 'http://www.spinrewriter.com/action/api'
19
+
20
+ # collection of possible values for the action parameter
21
+ ACTION = named_tuple('ACTION', ['api_quota', 'text_with_spintax',
22
+ 'unique_variation', 'unique_variation_from_spintax'])
23
+
24
+ # collection of possible values for the confidence_level parameter
25
+ CONFIDENCE_LVL = named_tuple('CONFIDENCE_LVL', ['low', 'medium', 'high'])
26
+
27
+ # collection of possible values for the spintax_format parameter
28
+ SPINTAX_FORMAT = named_tuple('SPINTAX_FORMAT',
29
+ ['pipe_curly', 'tilde_curly', 'pipe_square', 'spin_tag'],
30
+ ['{|}', '{~}', '[|]', '[spin]']
31
+ )
32
+
33
+ # collection of all request parameters' names
34
+ REQUEST_PARAMS = named_tuple('REQUEST_PARAMS',
35
+ ['email_address', 'api_key', 'action', 'text', 'protected_terms',
36
+ 'confidence_level', 'nested_spintax', 'spintax_format'])
37
+
38
+ # collection of all response fields' names
39
+ RESPONSE_PARAMS = named_tuple('RESP_P_NAMES',
40
+ ['status', 'response', 'api_requests_made', 'api_requests_available',
41
+ 'protected_terms', 'confidence_level'])
42
+
43
+ # possible response status strings returned by API
44
+ STATUS = named_tuple('STATUS', ['ok', 'error'], ['OK', 'ERROR'])
45
+
46
+ attr_reader :email_address, :api_key
47
+
48
+ def initialize(email_address, api_key)
49
+ @email_address = email_address
50
+ @api_key = api_key
51
+ end
52
+
53
+ # Return the number of made and remaining API calls for the 24-hour period.
54
+ # @return: remaining API quota
55
+ # @rtype: dictionary
56
+ def api_quota
57
+ params = {
58
+ REQUEST_PARAMS.email_address => self.email_address,
59
+ REQUEST_PARAMS.api_key => self.api_key,
60
+ REQUEST_PARAMS.action => ACTION.api_quota,
61
+ }
62
+ send_request(params)
63
+ end
64
+
65
+ # Return processed spun text with spintax.
66
+ #
67
+ # @param text: original text that needs to be changed
68
+ # @type text: string
69
+ # @param protected_terms: (optional) keywords and key phrases that
70
+ # should be left intact
71
+ # @type protected_terms: list of strings
72
+ # @param confidence_level: (optional) the confidence level of
73
+ # the One-Click Rewrite process
74
+ # @type confidence_level: string
75
+ # @param nested_spintax: (optional) whether or not to also spin
76
+ # single words inside already spun phrases
77
+ # @type nested_spintax: boolean
78
+ # @param spintax_format: (optional) spintax format to use in returned text
79
+ # @type spintax_format: string
80
+ # @return: processed text and some other meta info
81
+ # @rtype: dictionary
82
+ def text_with_spintax(text,
83
+ protected_terms: nil,
84
+ confidence_level: CONFIDENCE_LVL.medium,
85
+ nested_spintax: false,
86
+ spintax_format: SPINTAX_FORMAT.pipe_curly
87
+ )
88
+
89
+ response = transform_plain_text(
90
+ ACTION.text_with_spintax, text,
91
+ protected_terms: protected_terms,
92
+ confidence_level: confidence_level,
93
+ nested_spintax: nested_spintax,
94
+ spintax_format: spintax_format
95
+ )
96
+
97
+ if response[RESPONSE_PARAMS.status] == STATUS.error
98
+ raise_error(response)
99
+ else
100
+ response
101
+ end
102
+ end
103
+
104
+ # Return a unique variation of the given text.
105
+ #
106
+ # @param text: original text that needs to be changed
107
+ # @type text: string
108
+ # @param protected_terms: (optional) keywords and key phrases that
109
+ # should be left intact
110
+ # @type protected_terms: list of strings
111
+ # @param confidence_level: (optional) the confidence level of
112
+ # the One-Click Rewrite process
113
+ # @type confidence_level: string
114
+ # @param nested_spintax: (optional) whether or not to also spin
115
+ # single words inside already spun phrases
116
+ # @type nested_spintax: boolean
117
+ # @param spintax_format: (optional) (probably not relevant here?
118
+ # But API documentation not clear here ...)
119
+ # @type spintax_format: string
120
+ # @return: processed text and some other meta info
121
+ # @rtype: dictionary
122
+ def unique_variation(text,
123
+ protected_terms: nil,
124
+ confidence_level: CONFIDENCE_LVL.medium,
125
+ nested_spintax: false,
126
+ spintax_format: SPINTAX_FORMAT.pipe_curly
127
+ )
128
+ response = transform_plain_text(
129
+ ACTION.unique_variation, text,
130
+ protected_terms: protected_terms,
131
+ confidence_level: confidence_level,
132
+ nested_spintax: nested_spintax,
133
+ spintax_format: spintax_format
134
+ )
135
+
136
+ if response[RESPONSE_PARAMS.status] == STATUS.error
137
+ raise_error(response)
138
+ else
139
+ response
140
+ end
141
+ end
142
+
143
+ # Return a unique variation of an already spun text.
144
+ #
145
+ # @param text: text to process
146
+ # @type text: string
147
+ # @param nested_spintax: whether or not to also spin single words
148
+ # inside already spun phrases
149
+ # @type nested_spintax: boolean
150
+ # @param spintax_format: (probably not relevant here?
151
+ # But API documentation not clear here ...)
152
+ # @type spintax_format: string
153
+ # @return: processed text and some other meta info
154
+ # @rtype: dictionary
155
+ def unique_variation_from_spintax(text,
156
+ nested_spintax: false,
157
+ spintax_format: SPINTAX_FORMAT.pipe_curly
158
+ )
159
+ params = {
160
+ REQUEST_PARAMS.email_address => self.email_address,
161
+ REQUEST_PARAMS.api_key => self.api_key,
162
+ REQUEST_PARAMS.action => ACTION.unique_variation_from_spintax,
163
+ REQUEST_PARAMS.text => text.encode('utf-8'),
164
+ REQUEST_PARAMS.nested_spintax => nested_spintax,
165
+ REQUEST_PARAMS.spintax_format => spintax_format,
166
+ }
167
+ response = send_request(params)
168
+
169
+ if response[RESPONSE_PARAMS.status] == STATUS.error
170
+ raise_error(response)
171
+ else
172
+ response
173
+ end
174
+ end
175
+
176
+ private
177
+
178
+ # Invoke Spin Rewriter API with given parameters and return its response.
179
+ # @param params: parameters to pass along with the request
180
+ # @type params: tuple of 2-tuples
181
+ # @return: API's response (already JSON-decoded)
182
+ # @rtype: dictionary
183
+ def send_request(params)
184
+ response = self.class.post(URL, body: params)
185
+ JSON.parse response.body
186
+ end
187
+
188
+ # Examine the API response and raise exception of the appropriate type.
189
+ # NOTE: usage of this method only makes sense when API response's status
190
+ # indicates an error
191
+ # @param api_response: API's response fileds
192
+ # :type api_response: dictionary
193
+ def raise_error(api_response)
194
+ error_msg = api_response[RESPONSE_PARAMS.response]
195
+
196
+ case error_msg
197
+ when %r{Authentication failed. No user with this email address found.}i,
198
+ %r{Authentication failed. Unique API key is not valid for this user.}i,
199
+ %r{This user does not have a valid Spin Rewriter subscription.}i
200
+ raise AuthenticationError, error_msg
201
+
202
+ when %r{API quota exceeded. You can make \d+ requests per day.}i
203
+ raise QuotaLimitError, error_msg
204
+
205
+ when %r{You can only submit entirely new text for analysis once every \d+ seconds.}i
206
+ raise UsageFrequencyError, error_msg
207
+
208
+ when %r{Requested action does not exist.}i
209
+ # NOTE: This should never occur unless
210
+ # there is a bug in the API library.
211
+ raise UnknownActionError, error_msg
212
+
213
+ when %r{Email address and unique API key are both required.}i
214
+ # NOTE: This should never occur unless
215
+ # there is a bug in the API library.
216
+ raise MissingParameterError, error_msg
217
+
218
+ when %r{Original text too short.}i,
219
+ %r{Original text too long. Text can have up to 4,000 words.}i,
220
+ %r{Original text after analysis too long. Text can have up to 4,000 words.}i,
221
+ %r{
222
+ Spinning syntax invalid.
223
+ With this action you should provide text with existing valid'
224
+ {first option|second option} spintax.
225
+ }ix,
226
+ %r{
227
+ The {first|second} spinning syntax invalid.
228
+ Re-check the syntax, i.e. curly brackets and pipes\.
229
+ }ix,
230
+ %r{Spinning syntax invalid.}i
231
+ raise ParamValueError, error_msg
232
+
233
+ when
234
+ %r{Analysis of your text failed. Please inform us about this.}i,
235
+ %r{Synonyms for your text could not be loaded. Please inform us about this.}i,
236
+ %r{Unable to load your new analyzed project.}i,
237
+ %r{Unable to load your existing analyzed project.}i,
238
+ %r{Unable to find your project in the database.}i,
239
+ %r{Unable to load your analyzed project.}i,
240
+ %r{One-Click Rewrite failed.}i
241
+ raise InternalApiError, error_msg
242
+
243
+ else
244
+ raise UnknownApiError, error_msg
245
+ end # case
246
+ end # def _raise_error
247
+
248
+ # Transform plain text using SpinRewriter API.
249
+ #
250
+ # Pack parameters into format as expected by the _send_request method and
251
+ # invoke the action method to get transformed text from the API.
252
+ #
253
+ # @param action: name of the action that will be requested from API
254
+ # @type action: string
255
+ # @param text: text to process
256
+ # @type text: string
257
+ # @param protected_terms: keywords and key phrases that should be left intact
258
+ # @type protected_terms: list of strings
259
+ # @param confidence_level: the confidence level of the One-Click Rewrite
260
+ # process
261
+ # @type confidence_level: string
262
+ # @param nested_spintax: whether or not to also spin single words inside
263
+ # already spun phrases
264
+ # @type nested_spintax: boolean
265
+ # @param spintax_format: spintax format to use in returned text
266
+ # @type spintax_format: string
267
+ # @return: processed text and some other meta info
268
+ # @rtype: dictionary
269
+ def transform_plain_text(
270
+ action,
271
+ text,
272
+ protected_terms:,
273
+ confidence_level:,
274
+ nested_spintax:,
275
+ spintax_format:
276
+ )
277
+ if protected_terms
278
+ # protected_terms could be separated by other characters too, like commas
279
+ protected_terms = protected_terms.map { |term| term.encode('utf-8') }.join('\n')
280
+ else
281
+ protected_terms = ''
282
+ end
283
+
284
+ params = {
285
+ REQUEST_PARAMS.email_address => self.email_address,
286
+ REQUEST_PARAMS.api_key => self.api_key,
287
+ REQUEST_PARAMS.action => action,
288
+ REQUEST_PARAMS.text => text.encode('utf-8'),
289
+ REQUEST_PARAMS.protected_terms => protected_terms,
290
+ REQUEST_PARAMS.confidence_level => confidence_level,
291
+ REQUEST_PARAMS.nested_spintax => nested_spintax,
292
+ REQUEST_PARAMS.spintax_format => spintax_format,
293
+ }
294
+
295
+ send_request(params)
296
+ end # def transform_plain_text
297
+
298
+ end # class Api
299
+ end # module SpinRewriter
@@ -0,0 +1,78 @@
1
+ module SpinRewriter
2
+
3
+ # Base class for exceptions in Spin Rewriter module.
4
+ class ApiError < StandardError
5
+ attr_reader :api_error_msg
6
+
7
+ def initialize(api_error_msg)
8
+ super
9
+ # api_error_msg respresents raw error string as returned by API server
10
+ @api_error_msg = api_error_msg
11
+ end
12
+ end
13
+
14
+
15
+ # Raised when authentication error occurs.
16
+ class AuthenticationError < ApiError
17
+ def message
18
+ 'Authentication with Spin Rewriter API failed.'
19
+ end
20
+ end
21
+
22
+
23
+ # Raised when API quota limit is reached.
24
+ class QuotaLimitError < ApiError
25
+ def message
26
+ 'Quota limit for API calls reached.'
27
+ end
28
+ end
29
+
30
+
31
+ # Raised when subsequent API requests are made in a too short time interval.
32
+ class UsageFrequencyError < ApiError
33
+ def message
34
+ 'Not enough time passed since last API request.'
35
+ end
36
+ end
37
+
38
+
39
+ # Raised when unknown API action is requested.
40
+ class UnknownActionError < ApiError
41
+ def message
42
+ 'Unknown API action requested.'
43
+ end
44
+ end
45
+
46
+
47
+ # Raised when required parameter is not provided.
48
+ class MissingParameterError < ApiError
49
+ def message
50
+ 'Required parameter not present in API request.'
51
+ end
52
+ end
53
+
54
+
55
+ # Raised when parameter passed to API call has an invalid value.
56
+ class ParamValueError < ApiError
57
+ def message
58
+ 'Invalid parameter value passed to API.'
59
+ end
60
+ end
61
+
62
+
63
+ # Raised when unexpected error occurs on the API server when processing a request.
64
+ class InternalApiError < ApiError
65
+ def message
66
+ 'Internal error occured on API server when processing request.'
67
+ end
68
+ end
69
+
70
+
71
+ # Raised when API call results in an unrecognized error.
72
+ class UnknownApiError < ApiError
73
+ def message
74
+ "Unrecognized API error message received: #{api_error_msg}"
75
+ end
76
+ end
77
+
78
+ end
@@ -0,0 +1,3 @@
1
+ module SpinRewriter
2
+ VERSION = "0.1.1"
3
+ end
@@ -0,0 +1,31 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "spin_rewriter/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "spin_rewriter"
8
+ spec.version = SpinRewriter::VERSION
9
+ spec.authors = ["Christoph Wagner"]
10
+ spec.email = ["github@pandawhisperer.net"]
11
+
12
+ spec.summary = %q{A Ruby interface to SpinRewriter.com}
13
+ spec.description = %q{SpinRewriter API client}
14
+ spec.homepage = "https://github.com/PandaWhisperer/spin_rewriter"
15
+ spec.license = "MIT"
16
+
17
+ # Specify which files should be added to the gem when it is released.
18
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
+ end
22
+ spec.bindir = "exe"
23
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_dependency "httparty", "~> 0.18.0"
27
+
28
+ spec.add_development_dependency "bundler", "~> 1.17"
29
+ spec.add_development_dependency "rake", "~> 10.0"
30
+ spec.add_development_dependency "minitest", "~> 5.0"
31
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spin_rewriter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Christoph Wagner
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-05-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.18.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.18.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.17'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.17'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '5.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '5.0'
69
+ description: SpinRewriter API client
70
+ email:
71
+ - github@pandawhisperer.net
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".travis.yml"
78
+ - Gemfile
79
+ - Gemfile.lock
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - bin/console
84
+ - bin/setup
85
+ - lib/spin_rewriter.rb
86
+ - lib/spin_rewriter/api.rb
87
+ - lib/spin_rewriter/errors.rb
88
+ - lib/spin_rewriter/version.rb
89
+ - spin_rewriter.gemspec
90
+ homepage: https://github.com/PandaWhisperer/spin_rewriter
91
+ licenses:
92
+ - MIT
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubygems_version: 3.0.6
110
+ signing_key:
111
+ specification_version: 4
112
+ summary: A Ruby interface to SpinRewriter.com
113
+ test_files: []