doc_repo 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 30dd0cd755d3202ed2e493d13e43283ad50be7ae
4
+ data.tar.gz: d87c1f901a3e3a63f165b8211b0e7049a48ea9be
5
+ SHA512:
6
+ metadata.gz: 18271a91e38f64eedfe8823d23fc0106953dc7e7c8f2ecb48c8f41dd54161fe46aaf164e09101c5486ad9fb8ae2a8f5a7bb2fa4ff85127d562a15eb8e0d46c97
7
+ data.tar.gz: 9e34106363f55e04f7a8e9371b08bc2b18f7862a07b77db118986707592eacd9f0dbf5b8e4328ba11ab06cdcd5af4415c165f4e008ed2a23ed6860fbafb8a25d
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in doc_repo.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Radius Networks
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # DocRepo
2
+
3
+ Store your markdown based documentation in a repo but serve it from with in your app.
4
+
5
+ This is a little project that will pull raw markdown from the GitHub API and proxy them through your app. This lets you render things in your app, customize the layout and access control -- but lets you update the docs without re-deploying.
6
+
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'doc_repo'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install doc_repo
23
+
24
+ ## Usage
25
+
26
+ Create an initializer to configure Doc Repo, in rails this would live in `config/initializers/doc_repo.rb`:
27
+
28
+ ```ruby
29
+ DocRepo.configure do |c|
30
+ # GitHub Orgnization or User:
31
+ c.org = "RadiusNetworks"
32
+
33
+ # GitHub Repo:
34
+ c.repo = "proximitykit-documentation"
35
+
36
+ # Git Branch (Optional):
37
+ c.branch = "master"
38
+ end
39
+ ```
40
+
41
+ Create a controller to render the documentation pages. In Rails you might use something like this:
42
+
43
+ ```ruby
44
+ class DocsController < ApplicationController
45
+ def index
46
+ # If you don't want to store the index view in the app, just redirect to one of the documentation pages:
47
+ redirect_to doc_path('index')
48
+ end
49
+
50
+ def show
51
+ DocRepo.respond_with(params[:slug]) do |f|
52
+ # Render the body:
53
+ f.html {|body| render text: body, layout: "docs" }
54
+
55
+ # Redirect to images and assets:
56
+ f.redirect {|url| redirect_to url }
57
+ end
58
+ rescue DocRepo::NotFound
59
+ raise ActionController::RoutingError.new('Not Found')
60
+ end
61
+
62
+ end
63
+ ```
64
+
65
+ ## Contributing
66
+
67
+ 1. Fork it
68
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
69
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
70
+ 4. Push to the branch (`git push origin my-new-feature`)
71
+ 5. Create a new Pull Request
72
+
73
+ ## License
74
+
75
+ MIT License. See the [LICENSE file](LICENSE.txt) for details.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/doc_repo.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'doc_repo/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "doc_repo"
8
+ spec.version = DocRepo::VERSION
9
+ spec.authors = ["Christopher Sexton"]
10
+ spec.email = ["github@codeography.com"]
11
+ spec.summary = "Doc Repo: Load in app documentation via an external Github repo"
12
+ spec.description = ""
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "rouge", "~> 1.6"
22
+ spec.add_dependency "redcarpet", "~> 3.1"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.6"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "webmock", "~> 1.0"
27
+ spec.add_development_dependency "rspec", "~> 3.0"
28
+ spec.add_development_dependency "pry"
29
+ end
@@ -0,0 +1,10 @@
1
+ module DocRepo
2
+ class Configuration
3
+ attr_accessor :org, :repo, :branch
4
+
5
+ def initialize
6
+ @org = "RadiusNetworks"
7
+ @branch = "master"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,58 @@
1
+ # Taken and modified from the Jekyll project under the MIT License
2
+ # https://github.com/jekyll/jekyll/blob/6849d6a/lib/jekyll/converters/markdown/redcarpet_parser.rb
3
+ # https://github.com/jekyll/jekyll/blob/6849d6a/LICENSE
4
+ require 'redcarpet'
5
+ require 'rouge'
6
+ require 'rouge/plugins/redcarpet'
7
+
8
+ module DocRepo
9
+ module Converters
10
+ class MarkdownParser
11
+ class RougeRenderer < Redcarpet::Render::HTML
12
+ include Rouge::Plugins::Redcarpet
13
+
14
+ def add_code_tags(code, lang)
15
+ code = code.to_s
16
+ code = code.sub(
17
+ /<pre>/,
18
+ "<pre><code class=\"language-#{lang}\" data-lang=\"#{lang}\">"
19
+ )
20
+ code = code.sub(/<\/pre>/, "</code></pre>")
21
+ end
22
+
23
+ def block_code(code, lang)
24
+ code = "<pre>#{super}</pre>"
25
+ "<div class=\"highlight\">#{add_code_tags(code, lang)}</div>"
26
+ end
27
+
28
+ protected
29
+
30
+ def rouge_formatter(opts = {})
31
+ Rouge::Formatters::HTML.new(opts.merge(wrap: false))
32
+ end
33
+ end
34
+
35
+ def initialize(config)
36
+ @config = config
37
+ @extensions = config.fetch(:extensions, [])
38
+ .each_with_object({}){ |e, h| h[e.to_sym] = true }
39
+ @extensions[:fenced_code_blocks] ||= !@extensions.fetch(:no_fenced_code_blocks, false)
40
+ @extensions[:fenced_code_blocks] ||= !@extensions[:no_fenced_code_blocks]
41
+
42
+ render_class = config.fetch(:render_with, RougeRenderer)
43
+ @renderer = render_class.new(@extensions)
44
+ if extensions.fetch(:smart, false)
45
+ @renderer.extend Redcarpet::Render::SmartyPants
46
+ end
47
+ end
48
+
49
+ def convert(content)
50
+ markdown = Redcarpet::Markdown.new(renderer, extensions)
51
+ markdown.render(content)
52
+ end
53
+
54
+ private
55
+ attr_reader :config, :extensions, :renderer
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,46 @@
1
+ require 'open-uri'
2
+
3
+ module DocRepo
4
+ class GithubFile
5
+
6
+ attr_reader :org, :repo, :branch, :file
7
+ def initialize(file,
8
+ org: DocRepo.configuration.org,
9
+ repo: DocRepo.configuration.repo,
10
+ branch: DocRepo.configuration.branch)
11
+ @file = file
12
+ @org = org
13
+ @repo = repo
14
+ @branch = branch
15
+ end
16
+
17
+ def redirect_url
18
+ "https://github.com/#{org}/#{repo}/raw/#{branch}/docs/#{file}"
19
+ end
20
+
21
+ def read_remote_file
22
+ open(url(file), headers).read
23
+ rescue OpenURI::HTTPError => e
24
+ raise DocRepo::NotFound
25
+ end
26
+
27
+ def headers
28
+ hash = {
29
+ "Accept" => "application/vnd.github.v3.raw",
30
+ "User-Agent" => "RadiusNetworks-ProximityKit",
31
+ }
32
+
33
+ if ENV["GITHUB_TOKEN"]
34
+ hash["Authorization"] = "token #{ENV["GITHUB_TOKEN"]}"
35
+ end
36
+
37
+ hash
38
+ end
39
+
40
+ def url(file)
41
+ "https://api.github.com/repos/#{org}/#{repo}/contents/docs/#{file}?ref=#{branch}"
42
+ end
43
+ end
44
+ end
45
+
46
+
@@ -0,0 +1,25 @@
1
+ module DocRepo
2
+ class Page
3
+ attr_accessor :body
4
+
5
+ def initialize(file)
6
+ @body = GithubFile.new("#{file}.md").read_remote_file
7
+ end
8
+
9
+ def to_html
10
+ Converters::MarkdownParser.new(
11
+ extensions: %i[
12
+ no_intra_emphasis
13
+ tables
14
+ fenced_code_blocks
15
+ autolink
16
+ strikethrough
17
+ lax_spacing
18
+ superscript
19
+ with_toc_data
20
+ ]
21
+ ).convert(body)
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ module DocRepo
2
+ class Repository
3
+ def respond(slug, &block)
4
+ if %w(.jpg .png .jpeg .svg .css .txt).include? File.extname(slug)
5
+ yield DocRepo::Response.redirect(get_redirect_url(slug))
6
+ else
7
+ yield DocRepo::Response.html(render_page(slug))
8
+ end
9
+ end
10
+
11
+ private
12
+
13
+ def render_page(slug)
14
+ DocRepo::Page.new(slug).to_html
15
+ end
16
+
17
+ def get_redirect_url(slug)
18
+ GithubFile.new(slug).redirect_url
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,25 @@
1
+ module DocRepo
2
+ class Response
3
+ attr_reader :type, :params
4
+ def initialize(type, params)
5
+ @type = type ; @params = params
6
+ end
7
+
8
+ def self.html(*params)
9
+ self.new :html, params
10
+ end
11
+
12
+ def self.redirect(*params)
13
+ self.new :redirect, params
14
+ end
15
+
16
+ def html
17
+ yield *params if type == :html
18
+ end
19
+
20
+ def redirect
21
+ yield *params if type == :redirect
22
+ end
23
+ end
24
+ end
25
+
@@ -0,0 +1,3 @@
1
+ module DocRepo
2
+ VERSION = "0.0.1"
3
+ end
data/lib/doc_repo.rb ADDED
@@ -0,0 +1,27 @@
1
+ require "doc_repo/version"
2
+
3
+ require "doc_repo/configuration"
4
+ require "doc_repo/github_file"
5
+ require "doc_repo/page"
6
+ require "doc_repo/repository"
7
+ require "doc_repo/response"
8
+ require "doc_repo/converters/markdown_parser"
9
+
10
+ module DocRepo
11
+ BadPageFormat = Class.new(StandardError)
12
+ NotFound = Class.new(StandardError)
13
+
14
+ class << self
15
+ attr_accessor :configuration
16
+ end
17
+
18
+ def self.configure
19
+ self.configuration ||= Configuration.new
20
+ yield(configuration) if block_given?
21
+ end
22
+
23
+ def self.respond_with(slug, &block)
24
+ Repository.new.respond(slug, &block)
25
+ end
26
+ end
27
+
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe DocRepo::Page do
4
+ def tempfile(body)
5
+ Tempfile.open("spec") do |f|
6
+ f.puts body
7
+ f.rewind
8
+ yield f
9
+ end
10
+ end
11
+
12
+ it "returns the markdown as html" do
13
+ body = <<-END.strip_heredoc
14
+ # A heading
15
+
16
+ Some content
17
+ END
18
+
19
+ stub_request(:get, "https://api.github.com/repos/RadiusNetworks/doc_spec/contents/docs/page.md?ref=master")
20
+ .to_return(body: body)
21
+
22
+
23
+ page = DocRepo::Page.new("page")
24
+ expect(page.to_html).to eq <<-END.strip_heredoc
25
+ <h1 id=\"a-heading\">A heading</h1>
26
+
27
+ <p>Some content</p>
28
+ END
29
+ end
30
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe DocRepo::Repository do
4
+
5
+ it "yields the file block for a jpg" do
6
+ repo = DocRepo::Repository.new
7
+
8
+ repo.respond("sonic_screwdriver.png") do |r|
9
+ expect { |b| r.redirect(&b) }.to yield_control
10
+ expect { |b| r.html(&b) }.not_to yield_control
11
+ end
12
+ end
13
+
14
+ it "determines the right mime type for a jpg" do
15
+ repo = DocRepo::Repository.new
16
+
17
+ repo.respond("sonic_screwdriver.png") do |r|
18
+ r.redirect do |url|
19
+ expect( url ).to match %r{.*raw/master/docs/sonic_screwdriver.png}
20
+ end
21
+ end
22
+ end
23
+ end
24
+
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe DocRepo::Page do
4
+ it "calls html block with 1 param" do
5
+ resp = DocRepo::Response.html 1
6
+ expect { |b| resp.html &b }.to yield_with_args(1)
7
+ end
8
+
9
+ it "calls html block with 2 params" do
10
+ resp = DocRepo::Response.html 1, 2
11
+ expect { |b| resp.html &b }.to yield_with_args(1, 2)
12
+ end
13
+
14
+ it "calls file block with 1 param" do
15
+ resp = DocRepo::Response.html "/path/to/file"
16
+ expect { |b| resp.html &b }.to yield_with_args("/path/to/file")
17
+ end
18
+ end
19
+
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe DocRepo do
4
+
5
+ around do |ex|
6
+ # Save and Reset the configuration
7
+ original_config = DocRepo.configuration
8
+ ex.run
9
+ DocRepo.instance_variable_set :@configuration, original_config
10
+ end
11
+
12
+ it "yields the configuration" do
13
+ expect { |b|
14
+ DocRepo.configure(&b)
15
+ }.to yield_control
16
+ end
17
+
18
+ end
@@ -0,0 +1,29 @@
1
+ require 'webmock/rspec'
2
+ require 'pry'
3
+ require 'doc_repo'
4
+
5
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
6
+
7
+ RSpec.configure do |config|
8
+
9
+ config.before do
10
+ DocRepo.configure do |c|
11
+ c.org = 'RadiusNetworks'
12
+ c.repo = 'doc_spec'
13
+ end
14
+ end
15
+ config.expect_with :rspec do |expectations|
16
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
17
+ end
18
+ config.mock_with :rspec do |mocks|
19
+ mocks.verify_partial_doubles = true
20
+ end
21
+ config.filter_run :focus
22
+ config.run_all_when_everything_filtered = true
23
+ config.disable_monkey_patching!
24
+ config.warnings = true
25
+ if config.files_to_run.one?
26
+ config.default_formatter = 'doc'
27
+ end
28
+ Kernel.srand config.seed
29
+ end
@@ -0,0 +1,9 @@
1
+ unless String.new.respond_to? :strip_heredoc
2
+ String.instance_eval do # self is set to String
3
+ define_method(:strip_heredoc) do # self is still String
4
+ leading_space = scan(/^[ \t]*(?=\S)/).min
5
+ indent = leading_space ? leading_space.size : 0
6
+ gsub(/^[ \t]{#{indent}}/, '')
7
+ end
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,169 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: doc_repo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Christopher Sexton
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-09-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rouge
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: redcarpet
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.6'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.6'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: webmock
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: pry
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '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'
111
+ description: ''
112
+ email:
113
+ - github@codeography.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - ".rspec"
120
+ - Gemfile
121
+ - LICENSE.txt
122
+ - README.md
123
+ - Rakefile
124
+ - doc_repo.gemspec
125
+ - lib/doc_repo.rb
126
+ - lib/doc_repo/configuration.rb
127
+ - lib/doc_repo/converters/markdown_parser.rb
128
+ - lib/doc_repo/github_file.rb
129
+ - lib/doc_repo/page.rb
130
+ - lib/doc_repo/repository.rb
131
+ - lib/doc_repo/response.rb
132
+ - lib/doc_repo/version.rb
133
+ - spec/doc_repo/page_spec.rb
134
+ - spec/doc_repo/repository_spec.rb
135
+ - spec/doc_repo/response_spec.rb
136
+ - spec/doc_repo_spec.rb
137
+ - spec/spec_helper.rb
138
+ - spec/support/string.rb
139
+ homepage: ''
140
+ licenses:
141
+ - MIT
142
+ metadata: {}
143
+ post_install_message:
144
+ rdoc_options: []
145
+ require_paths:
146
+ - lib
147
+ required_ruby_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ requirements: []
158
+ rubyforge_project:
159
+ rubygems_version: 2.2.2
160
+ signing_key:
161
+ specification_version: 4
162
+ summary: 'Doc Repo: Load in app documentation via an external Github repo'
163
+ test_files:
164
+ - spec/doc_repo/page_spec.rb
165
+ - spec/doc_repo/repository_spec.rb
166
+ - spec/doc_repo/response_spec.rb
167
+ - spec/doc_repo_spec.rb
168
+ - spec/spec_helper.rb
169
+ - spec/support/string.rb