readme-score 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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