readme-score 0.0.2

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,14 @@
1
+ module ReadmeScore
2
+ module Util
3
+ module_function
4
+ def to_noko(noko_or_html, copy = false)
5
+ noko = noko_or_html
6
+ if noko_or_html.is_a?(String)
7
+ noko = Nokogiri::HTML.fragment(noko_or_html)
8
+ elsif copy && noko_or_html.is_a?(Nokogiri::XML::Node)
9
+ noko = Nokogiri::HTML.fragment(noko.to_s)
10
+ end
11
+ noko
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ module ReadmeScore
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'readme-score/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "readme-score"
8
+ spec.version = ReadmeScore::VERSION
9
+ spec.authors = ["Clay Allsopp"]
10
+ spec.email = ["clay.allsopp@gmail.com"]
11
+ spec.summary = "Gives a score for README.md"
12
+ spec.homepage = "https://github.com/clayallsopp/readme-score"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "nokogiri", ">= 1.6.0"
21
+ spec.add_dependency "unirest", ">= 1.1.0"
22
+ spec.add_dependency "redcarpet", ">= 3.1.0"
23
+ spec.add_dependency "octokit", ">= 3.2.0"
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.5"
26
+ spec.add_development_dependency "rspec"
27
+ spec.add_development_dependency "rake"
28
+ spec.add_development_dependency "webmock"
29
+ spec.add_development_dependency "dotenv"
30
+ end
@@ -0,0 +1,111 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe ReadmeScore::Document::Filter do
4
+ describe "#filtered_html!" do
5
+
6
+ describe "removing license" do
7
+ it "works" do
8
+ html = %Q{
9
+ <h2>LICENSE</h2>
10
+ <p>Some info about the license here</p>
11
+ <p>More info</p>}
12
+ filter = ReadmeScore::Document::Filter.new(html)
13
+ filter.filtered_html!.strip.empty?.should == true
14
+ end
15
+
16
+ it "works and preserves other elements" do
17
+ html = %Q{
18
+ <h2>Other thing</h2>
19
+ <p>Something</p>
20
+ <h2>LICENSE</h2>
21
+ <p>Some info about the license here</p>
22
+ <p>More info</p>
23
+ <h2>Something else</h2>
24
+ <p>Hello</p>}
25
+ filter = ReadmeScore::Document::Filter.new(html)
26
+ string = filter.filtered_html!
27
+ string.should == %Q{
28
+ <h2>Other thing</h2>
29
+ <p>Something</p>
30
+ <h2>Something else</h2>
31
+ <p>Hello</p>}
32
+ end
33
+
34
+ it "works with lesser headings afterwards" do
35
+ html = %Q{
36
+ <h2>LICENSE</h2>
37
+ <p>Some info about the license here</p>
38
+ <p>More info</p>
39
+ <h4>Something else</h4>
40
+ <p>Hello</p>}
41
+ filter = ReadmeScore::Document::Filter.new(html)
42
+ string = filter.filtered_html!
43
+ string.strip.should == ""
44
+ end
45
+ end
46
+
47
+ describe "removing contact" do
48
+ it "works" do
49
+ html = %Q{
50
+ <h2>Contact</h2>
51
+ <p>Some info about the contact here</p>
52
+ <p>More info</p>}
53
+ filter = ReadmeScore::Document::Filter.new(html)
54
+ filter.filtered_html!.strip.empty?.should == true
55
+ end
56
+
57
+ it "works and preserves other elements" do
58
+ html = %Q{
59
+ <h2>Other thing</h2>
60
+ <p>Something</p>
61
+ <h2>Contact</h2>
62
+ <p>Some info about the contact here</p>
63
+ <p>More info</p>
64
+ <h2>Something else</h2>
65
+ <p>Hello</p>}
66
+ filter = ReadmeScore::Document::Filter.new(html)
67
+ string = filter.filtered_html!
68
+ string.should == %Q{
69
+ <h2>Other thing</h2>
70
+ <p>Something</p>
71
+ <h2>Something else</h2>
72
+ <p>Hello</p>}
73
+ end
74
+
75
+ it "works with lesser headings afterwards" do
76
+ html = %Q{
77
+ <h2>Contact</h2>
78
+ <p>Some info about the contact here</p>
79
+ <p>More info</p>
80
+ <h4>Something else</h4>
81
+ <p>Hello</p>}
82
+ filter = ReadmeScore::Document::Filter.new(html)
83
+ string = filter.filtered_html!
84
+ string.strip.should == ""
85
+ end
86
+ end
87
+
88
+ describe "removing services with images" do
89
+ it "works" do
90
+ html = %Q{
91
+ <h2>Repo</h2><a href="http://travis-ci.org/thing"><img src="travis" /></a><p>Hello</p>
92
+ }.strip
93
+ filter = ReadmeScore::Document::Filter.new(html)
94
+ string = filter.filtered_html!
95
+ string.strip.should == %Q{
96
+ <h2>Repo</h2><p>Hello</p>
97
+ }.strip
98
+ end
99
+
100
+ it "keeps non-image links" do
101
+ html = %Q{
102
+ <h2>Repo</h2><a href="http://travis-ci.org/thing">Travis</a><p>Hello</p>
103
+ }.strip
104
+ filter = ReadmeScore::Document::Filter.new(html)
105
+ string = filter.filtered_html!
106
+ string.strip.should == html
107
+ end
108
+ end
109
+
110
+ end
111
+ end
@@ -0,0 +1,139 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe ReadmeScore::Document::Loader do
4
+ describe ".is_github_repo_slug?" do
5
+ it "works" do
6
+ ReadmeScore::Document::Loader.is_github_repo_slug?("usepropeller/react.backbone").should == true
7
+ ReadmeScore::Document::Loader.is_github_repo_slug?("afnetworking/afnetworking").should == true
8
+ ReadmeScore::Document::Loader.is_github_repo_slug?("afnetworking/").should == false
9
+ ReadmeScore::Document::Loader.is_github_repo_slug?("afnetworking").should == false
10
+ ReadmeScore::Document::Loader.is_github_repo_slug?("http://github.com/afnetworking/afnetworking").should == false
11
+ ReadmeScore::Document::Loader.is_github_repo_slug?("afnetworking/afnetworking/").should == false
12
+ ReadmeScore::Document::Loader.is_github_repo_slug?("afnetworking/afnetworking/z").should == false
13
+ end
14
+ end
15
+
16
+ describe ".is_url?" do
17
+ it "works" do
18
+ ReadmeScore::Document::Loader.is_url?("http://github.com/afnetworking/afnetworking").should == true
19
+ ReadmeScore::Document::Loader.is_url?("https://github.com/afnetworking/afnetworking").should == true
20
+ ReadmeScore::Document::Loader.is_url?("https://something.com/").should == true
21
+ ReadmeScore::Document::Loader.is_url?("usepropeller/react.backbone").should == false
22
+ ReadmeScore::Document::Loader.is_url?("afnetworking/afnetworking").should == false
23
+ ReadmeScore::Document::Loader.is_url?("afnetworking/").should == false
24
+ ReadmeScore::Document::Loader.is_url?("afnetworking").should == false
25
+ ReadmeScore::Document::Loader.is_url?("afnetworking/afnetworking/").should == false
26
+ ReadmeScore::Document::Loader.is_url?("afnetworking/afnetworking/z").should == false
27
+ end
28
+ end
29
+
30
+ describe "#markdown?" do
31
+ ReadmeScore::Document::Loader::MARKDOWN_EXTENSIONS.each {|extension|
32
+ describe "with .#{extension} link" do
33
+ it "is true" do
34
+ url = "http://www.test.com/readme.#{extension}"
35
+ stub_request(:get, url)
36
+
37
+ loader = ReadmeScore::Document::Loader.new(url)
38
+ loader.load!
39
+ loader.markdown?.should == true
40
+ end
41
+ end
42
+ }
43
+
44
+ describe "without .md link" do
45
+ it "is false" do
46
+ url = "http://www.test.com/readme.html"
47
+ stub_request(:get, url)
48
+
49
+ loader = ReadmeScore::Document::Loader.new(url)
50
+ loader.markdown?.should == false
51
+ end
52
+ end
53
+ end
54
+
55
+ describe "#html" do
56
+ describe "without markdown" do
57
+ it "works" do
58
+ loader = ReadmeScore::Document::Loader.new("http://something.com/thing.html")
59
+ loader.markdown = false
60
+ loader.response = double('HTTP response', body: "<h1>Hello</h1>")
61
+ loader.html.should == "<h1>Hello</h1>"
62
+ end
63
+ end
64
+
65
+ describe "with markdown" do
66
+ it "works" do
67
+ loader = ReadmeScore::Document::Loader.new("http://something.com/thing.md")
68
+ loader.markdown = true
69
+ loader.response = double('Markdown response', body: "# Hello")
70
+ expect(loader).to receive(:parse_markdown).with("# Hello")
71
+ loader.html
72
+ end
73
+ end
74
+ end
75
+
76
+
77
+ describe "#load!" do
78
+ describe "when github api is turned off" do
79
+ before do
80
+ ReadmeScore.use_github_api = false
81
+ end
82
+
83
+ after do
84
+ ReadmeScore.use_github_api = true
85
+ end
86
+
87
+ it "loads via approximation" do
88
+ loader = ReadmeScore::Document::Loader.new("http://github.com/repo/user")
89
+ expect(loader).to receive(:load_via_github_approximation!)
90
+ loader.load!
91
+ end
92
+ end
93
+
94
+ describe "with non-github links" do
95
+ it "works" do
96
+ url = "http://www.test.com/readme.md"
97
+ stub_request(:get, url).
98
+ to_return(body: "<h1>This is a test</h1>")
99
+
100
+ loader = ReadmeScore::Document::Loader.new(url)
101
+ loader.load!
102
+ loader.html.strip.should == "<h1>This is a test</h1>"
103
+ end
104
+ end
105
+
106
+ describe "with github links" do
107
+ describe "with link to repo" do
108
+ ["", "www."].each {|subdomain|
109
+ %w(http https).each {|protocol|
110
+ it "works with #{protocol}" do
111
+ repo_url = "#{protocol}://#{subdomain}github.com/repo/user"
112
+
113
+ stub_github_readme(protocol, 'repo', 'user', 'README.md').
114
+ to_return(body: "<h1>This is a hit</h1>")
115
+
116
+ loader = ReadmeScore::Document::Loader.new(repo_url)
117
+ loader.load!
118
+ loader.html.strip.should == "<h1>This is a hit</h1>"
119
+ end
120
+ }
121
+ }
122
+
123
+ end
124
+
125
+ describe "with link to some other page" do
126
+ it "works" do
127
+ url = "http://github.com/repo/user/block/thing/idk.md"
128
+ stub_request(:get, url).
129
+ to_return(body: "<h1>A markdown</h1>")
130
+
131
+ loader = ReadmeScore::Document::Loader.new(url)
132
+ loader.load!
133
+ loader.html.strip.should == "<h1>A markdown</h1>"
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+ end
@@ -0,0 +1,95 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe ReadmeScore::Document::Metrics do
4
+
5
+ describe "#number_of_links" do
6
+ it "works" do
7
+ html = %Q{
8
+ <a href="other_thing.html">Other thing</a>
9
+ <p><a href="/other_thing.html">Other thing</a></p>
10
+ <a href="http://google.com">Something there</a>}
11
+ calc = ReadmeScore::Document::Metrics.new(html)
12
+ calc.number_of_links.should == 3
13
+ end
14
+ end
15
+
16
+ describe "#number_of_code_blocks" do
17
+ it "works" do
18
+ html = %Q{
19
+ <p>You can initialize a <code>Formotion::Form</code> using either a hash (as above) or the DSL:</p>
20
+ <div class="highlight highlight-ruby"><pre><span class="n">form</span> <span class="o">=</span> <span class="no">Formotion</span><span class="o">::</span><span class="no">Form</span><span class="o">.</span><span class="n">new</span>
21
+
22
+ <span class="n">form</span><span class="o">.</span><span class="n">build_section</span> <span class="k">do</span> <span class="o">|</span><span class="n">section</span><span class="o">|</span>
23
+ <span class="n">section</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="s2">"Title"</span>
24
+
25
+ <span class="n">section</span><span class="o">.</span><span class="n">build_row</span> <span class="k">do</span> <span class="o">|</span><span class="n">row</span><span class="o">|</span>
26
+ <span class="n">row</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="s2">"Label"</span>
27
+ <span class="n">row</span><span class="o">.</span><span class="n">subtitle</span> <span class="o">=</span> <span class="s2">"Placeholder"</span>
28
+ <span class="n">row</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="ss">:string</span>
29
+ <span class="k">end</span>
30
+ <span class="k">end</span>
31
+ </pre></div>
32
+ <p>Then attach it to a <code>Formotion::FormController</code> and you're ready to rock and roll:</p>
33
+ <div class="highlight highlight-ruby"><pre><span class="vi">@controller</span> <span class="o">=</span> <span class="no">Formotion</span><span class="o">::</span><span class="no">FormController</span><span class="o">.</span><span class="n">alloc</span><span class="o">.</span><span class="n">initWithForm</span><span class="p">(</span><span class="n">form</span><span class="p">)</span>
34
+ <span class="nb">self</span><span class="o">.</span><span class="n">navigationController</span><span class="o">.</span><span class="n">pushViewController</span><span class="p">(</span><span class="vi">@controller</span><span class="p">,</span> <span class="ss">animated</span><span class="p">:</span> <span class="kp">true</span><span class="p">)</span>
35
+ </pre></div>
36
+
37
+ <p>Pretty simple, right?</p>
38
+ }
39
+ calc = ReadmeScore::Document::Metrics.new(html)
40
+ calc.number_of_code_blocks.should == 2
41
+ end
42
+ end
43
+
44
+ describe "#code_block_to_paragraph_ratio" do
45
+ it "works" do
46
+ html = %Q{
47
+ <p>You can initialize a <code>Formotion::Form</code> using either a hash (as above) or the DSL:</p>
48
+ <div class="highlight highlight-ruby"><pre><span class="n">form</span> <span class="o">=</span> <span class="no">Formotion</span><span class="o">::</span><span class="no">Form</span><span class="o">.</span><span class="n">new</span>
49
+
50
+ <span class="n">form</span><span class="o">.</span><span class="n">build_section</span> <span class="k">do</span> <span class="o">|</span><span class="n">section</span><span class="o">|</span>
51
+ <span class="n">section</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="s2">"Title"</span>
52
+
53
+ <span class="n">section</span><span class="o">.</span><span class="n">build_row</span> <span class="k">do</span> <span class="o">|</span><span class="n">row</span><span class="o">|</span>
54
+ <span class="n">row</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="s2">"Label"</span>
55
+ <span class="n">row</span><span class="o">.</span><span class="n">subtitle</span> <span class="o">=</span> <span class="s2">"Placeholder"</span>
56
+ <span class="n">row</span><span class="o">.</span><span class="n">type</span> <span class="o">=</span> <span class="ss">:string</span>
57
+ <span class="k">end</span>
58
+ <span class="k">end</span>
59
+ </pre></div>
60
+ <p>Then attach it to a <code>Formotion::FormController</code> and you're ready to rock and roll:</p>
61
+ <div class="highlight highlight-ruby"><pre><span class="vi">@controller</span> <span class="o">=</span> <span class="no">Formotion</span><span class="o">::</span><span class="no">FormController</span><span class="o">.</span><span class="n">alloc</span><span class="o">.</span><span class="n">initWithForm</span><span class="p">(</span><span class="n">form</span><span class="p">)</span>
62
+ <span class="nb">self</span><span class="o">.</span><span class="n">navigationController</span><span class="o">.</span><span class="n">pushViewController</span><span class="p">(</span><span class="vi">@controller</span><span class="p">,</span> <span class="ss">animated</span><span class="p">:</span> <span class="kp">true</span><span class="p">)</span>
63
+ </pre></div>
64
+
65
+ <p>Pretty simple, right?</p>
66
+ }
67
+ calc = ReadmeScore::Document::Metrics.new(html)
68
+ calc.code_block_to_paragraph_ratio.should == (2.0 / 3.0)
69
+ end
70
+ end
71
+
72
+ describe "#number_of_non_code_sections" do
73
+ it "works" do
74
+ html = %Q{
75
+ <p>Paragraph</p>
76
+ <p>Paragraph2</p>
77
+ <div class="highlight highlight-yaml"><pre><span class="l-Scalar-Plain">additional_guides</span><span class="p-Indicator">:</span>
78
+ <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">https://github.com/magicalpanda/MagicalRecord/wiki/Installation</span>
79
+ <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">https://github.com/CocoaPods/CocoaPods/wiki/A-pod-specification</span>
80
+ <span class="p-Indicator">-</span> <span class="l-Scalar-Plain">docs/Getting_started.md</span>
81
+ </pre></div>
82
+ <ol>
83
+ <li></li>
84
+ <li></li>
85
+ </ol>
86
+ <ul>
87
+ <li></li>
88
+ <li></li>
89
+ </ul>
90
+ }
91
+ calc = ReadmeScore::Document::Metrics.new(html)
92
+ calc.number_of_non_code_sections.should == 4
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe ReadmeScore do
4
+ describe ".use_github_api?" do
5
+ it "changes after setting" do
6
+ ReadmeScore.use_github_api = false
7
+ ReadmeScore.use_github_api?.should == false
8
+ ReadmeScore.use_github_api = true
9
+ ReadmeScore.use_github_api?.should == true
10
+ end
11
+ end
12
+
13
+ describe ".for" do
14
+ %w{http https}.each { |protocol|
15
+ it "should load a #{protocol} URL" do
16
+ url = "#{protocol}://somewhere.com/thing.md"
17
+ expect(ReadmeScore::Document).to receive(:load).with(url) { ReadmeScore::Document.new("") }
18
+ ReadmeScore.for(url)
19
+ end
20
+ }
21
+
22
+ it "should load a Github slug" do
23
+ repo = "user/repo"
24
+ expect(ReadmeScore::Document).to receive(:load).with("http://github.com/#{repo}") { ReadmeScore::Document.new("") }
25
+ ReadmeScore.for(repo)
26
+ end
27
+
28
+ it "should not load for HTML" do
29
+ html = "<h1>Sup</h1>"
30
+ expect(ReadmeScore::Document).to_not receive(:load)
31
+ ReadmeScore.for(html)
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,17 @@
1
+ ROOT = Pathname.new(File.expand_path('../../', __FILE__))
2
+
3
+ $:.unshift((ROOT + 'lib').to_s)
4
+ require 'readme-score'
5
+
6
+ require 'webmock/rspec'
7
+
8
+ module GithubSpecHelpers
9
+ def stub_github_readme(protocol, repo, user, readme_filename)
10
+ stub_request(:get, "https://api.github.com/repos/#{repo}/#{user}/readme").
11
+ with(:headers => {'Accept'=>'application/vnd.github.html', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3'})
12
+ end
13
+ end
14
+
15
+ RSpec.configure do |config|
16
+ config.include GithubSpecHelpers
17
+ end