blinkr 0.0.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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +13 -0
- data/README.md +56 -0
- data/Rakefile +21 -0
- data/bin/blinkr +20 -0
- data/blinkr.gemspec +27 -0
- data/lib/blinkr.rb +16 -0
- data/lib/blinkr/cache.rb +16 -0
- data/lib/blinkr/check.rb +99 -0
- data/lib/blinkr/report.html.slim +27 -0
- data/lib/blinkr/report.rb +14 -0
- data/lib/blinkr/version.rb +4 -0
- metadata +130 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e61e7418f9b5b9eed589dd944f72f2b21a0d6336
|
4
|
+
data.tar.gz: 873968583abfeeb3494065a9650f9cb363598e1a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5f05594eea95d76a50dcbb5dd634bceecde12b33e87e562314b9f8cd0aa7c71d64ba95ba7a023e6461895da21645b147d728ffd8b2d38d255084d632a41d6b37
|
7
|
+
data.tar.gz: 60e9ab67b9c54c82b6ba249a58a8fee766cf5d37505a3a06a0dc1b0f13d9094ce9ef2e0be039fd676a8942a4df5a964849bb8c42361fe0a28fdefac1c330bdc4
|
data/.gitignore
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
blink
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.1.2
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright (c) 2014 Pete Muir
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# Blinkr
|
2
|
+
|
3
|
+
A broken link checker for websites
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'blinkr'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install blinkr
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
To run blinkr against your site, assuming you have a `sitemap.xml` in the root of your site:
|
22
|
+
|
23
|
+
````
|
24
|
+
blinkr -u http://www.jboss.org
|
25
|
+
````
|
26
|
+
|
27
|
+
If you want to customize blinkr, create a config file `blinkr.yaml`. For example:
|
28
|
+
|
29
|
+
````
|
30
|
+
# Links not to check
|
31
|
+
skips:
|
32
|
+
- !ruby/regexp /^\/video\/((?!91710755).)*\/$/
|
33
|
+
- !ruby/regexp /^\/quickstarts\/((?!eap\/kitchensink).)*\/*$/
|
34
|
+
- !ruby/regexp /^\/boms\/((?!eap\/jboss-javaee-6_0).)*\/*$/
|
35
|
+
- !ruby/regexp /^\/archetypes\/((?!eap\/jboss-javaee6-webapp-archetype).)*\/*$/
|
36
|
+
# The output file to write the report to
|
37
|
+
report: _tmp/blinkr.html
|
38
|
+
# The URL to check
|
39
|
+
base_url: http://www.jboss.org
|
40
|
+
sitemap: http://www.jboss.org/my_sitemap.xml
|
41
|
+
````
|
42
|
+
|
43
|
+
Specify a custom config file on the command link:
|
44
|
+
|
45
|
+
````
|
46
|
+
blinkr -c my_blinkr.yaml
|
47
|
+
````
|
48
|
+
|
49
|
+
## Contributing
|
50
|
+
|
51
|
+
1. Fork it ( http://github.com/pmuir/blinkr/fork )
|
52
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
53
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
54
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
55
|
+
5. Create new Pull Request
|
56
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
|
3
|
+
GEMFILE = "blinkr-#{Blinkr::VERSION}.gem"
|
4
|
+
|
5
|
+
desc "Run all tests and build the gem"
|
6
|
+
task :build do
|
7
|
+
system "gem build blinkr.gemspec"
|
8
|
+
end
|
9
|
+
|
10
|
+
namespace :release do
|
11
|
+
desc "Release the gem to rubygems"
|
12
|
+
task :push => [ :build, :tag ] do
|
13
|
+
system "gem push #{GEMFILE}"
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Create tag #{Blinkr::VERSION} in git"
|
17
|
+
task :tag do
|
18
|
+
system "git tag #{Blinkr::VERSION}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
data/bin/blinkr
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'blinkr'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
|
8
|
+
OptionParser.new do |opts|
|
9
|
+
opts.banner = "Usage: blinkr [options]"
|
10
|
+
|
11
|
+
opts.on("-c", "--config FILE", "specify the config.yaml file") do |opt|
|
12
|
+
options[:config] = opt
|
13
|
+
end
|
14
|
+
opts.on("-u", "--base-url URL", "specify the URL of the site root") do |opt|
|
15
|
+
options[:base_url] = opt
|
16
|
+
end
|
17
|
+
end.parse!
|
18
|
+
|
19
|
+
Blinkr.run options[:base_url], options[:config]
|
20
|
+
|
data/blinkr.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'blinkr/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "blinkr"
|
8
|
+
spec.version = Blinkr::VERSION
|
9
|
+
spec.authors = ["Pete Muir"]
|
10
|
+
spec.email = ["pmuir@bleepbleep.org.uk"]
|
11
|
+
spec.summary = %q{A simple broken link checker}
|
12
|
+
spec.homepage = ""
|
13
|
+
spec.license = "Apache-2.0"
|
14
|
+
|
15
|
+
spec.files = `git ls-files`.split($/)
|
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.required_ruby_version = '~> 2.0'
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
23
|
+
spec.add_development_dependency 'rake', '~> 10.3'
|
24
|
+
spec.add_dependency 'nokogiri', '~> 1.5'
|
25
|
+
spec.add_dependency 'typhoeus', '~> 0.6'
|
26
|
+
spec.add_dependency 'slim', '~> 2.0'
|
27
|
+
end
|
data/lib/blinkr.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'blinkr/version'
|
2
|
+
require 'blinkr/check'
|
3
|
+
require 'blinkr/report'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
module Blinkr
|
7
|
+
def self.run(base_url, config = 'blinkr.yaml')
|
8
|
+
if !config.nil? && File.exists?(config)
|
9
|
+
config = YAML.load_file(config)
|
10
|
+
else
|
11
|
+
config = {}
|
12
|
+
end
|
13
|
+
blinkr = Blinkr::Check.new(base_url || config['base_url'], sitemap: config['sitemap'], skips: config['skips'], max_retrys: config['max_retrys'], max_page_retrys: config['max_page_retrys'])
|
14
|
+
Blinkr::Report.render(blinkr.check, config['report'])
|
15
|
+
end
|
16
|
+
end
|
data/lib/blinkr/cache.rb
ADDED
data/lib/blinkr/check.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'uri'
|
3
|
+
require 'typhoeus'
|
4
|
+
require 'blinkr/cache'
|
5
|
+
require 'ostruct'
|
6
|
+
|
7
|
+
module Blinkr
|
8
|
+
class Check
|
9
|
+
|
10
|
+
def initialize base_url, sitemap: sitemap, skips: skips, max_retrys: max_retrys, max_page_retrys: max_page_retrys
|
11
|
+
raise "Must specify base_url" if base_url.nil?
|
12
|
+
unless sitemap.nil?
|
13
|
+
@sitemap = sitemap
|
14
|
+
else
|
15
|
+
@sitemap = URI.join(base_url, 'sitemap.xml').to_s
|
16
|
+
end
|
17
|
+
@skips = skips || []
|
18
|
+
@base_url = base_url
|
19
|
+
@max_retrys = max_retrys || 3
|
20
|
+
@max_page_retrys = max_page_retrys || @max_retrys
|
21
|
+
Typhoeus::Config.cache = Blinkr::Cache.new
|
22
|
+
@hydra = Typhoeus::Hydra.new(max_concurrency: 200)
|
23
|
+
end
|
24
|
+
|
25
|
+
def check
|
26
|
+
@errors = {}
|
27
|
+
puts "Loading sitemap from #{@sitemap}"
|
28
|
+
if @sitemap =~ URI::regexp
|
29
|
+
sitemap = Nokogiri::XML(Typhoeus.get(@sitemap, followlocation: true).body)
|
30
|
+
else
|
31
|
+
sitemap = Nokogiri::XML(File.open(@sitemap))
|
32
|
+
end
|
33
|
+
sitemap.css('loc').each do |loc|
|
34
|
+
request = Typhoeus::Request.new(
|
35
|
+
loc.content,
|
36
|
+
method: :get,
|
37
|
+
followlocation: true
|
38
|
+
)
|
39
|
+
perform(request, @max_page_retrys) do |resp|
|
40
|
+
page = Nokogiri::HTML(resp.body)
|
41
|
+
page.css('a[href]').each do |a|
|
42
|
+
check_attr(a.attribute('href'), loc.content)
|
43
|
+
end
|
44
|
+
page.css('img[src]').each do |img|
|
45
|
+
check_attr(img.attribute('src'), loc.content)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
@hydra.run
|
50
|
+
@errors
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def check_attr attr, src
|
56
|
+
url = attr.value
|
57
|
+
unless url.nil?
|
58
|
+
begin
|
59
|
+
uri = URI(url)
|
60
|
+
uri = URI.join(src, url) if uri.path.nil? || uri.path.empty?
|
61
|
+
uri = URI.join(@base_url, uri) if uri.scheme.nil?
|
62
|
+
url = uri.to_s
|
63
|
+
rescue Exception => e
|
64
|
+
end
|
65
|
+
if uri.nil? || uri.is_a?(URI::HTTP)
|
66
|
+
request = Typhoeus::Request.new(
|
67
|
+
url,
|
68
|
+
method: :head,
|
69
|
+
followlocation: true
|
70
|
+
)
|
71
|
+
perform request do |resp|
|
72
|
+
unless resp.success?
|
73
|
+
@errors[request] ||= OpenStruct.new({ :url => url, :code => resp.code.to_i, :message => resp.return_message, :refs => [] })
|
74
|
+
@errors[request].refs << OpenStruct.new({:src => src, :line_no => attr.line, :snippet => attr.parent.to_s})
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def perform req, limit = @max_retrys
|
82
|
+
if @skips.none? { |regex| regex.match(req.base_url) }
|
83
|
+
req.on_complete do |resp|
|
84
|
+
if resp.timed_out?
|
85
|
+
if limit > 0
|
86
|
+
perform(Typhoeus::Request.new(req.base_url, req.options), limit - 1, &Proc.new)
|
87
|
+
else
|
88
|
+
yield OpenStruct.new({:success => false, :code => '0', :return_message => "Server timed out"})
|
89
|
+
end
|
90
|
+
else
|
91
|
+
yield resp
|
92
|
+
end
|
93
|
+
end
|
94
|
+
@hydra.queue req
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
doctype html
|
2
|
+
head
|
3
|
+
link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"
|
4
|
+
meta name="viewport" content="width=device-width, initial-scale=1"
|
5
|
+
title Blinkr
|
6
|
+
body
|
7
|
+
|
8
|
+
.container
|
9
|
+
h1 Blinkr
|
10
|
+
p.lead
|
11
|
+
| Detected broken links
|
12
|
+
- errors.each do |req, err|
|
13
|
+
.panel.panel-danger
|
14
|
+
.panel-heading
|
15
|
+
a href="#{req.base_url}" target='_blank'
|
16
|
+
| #{req.base_url}
|
17
|
+
i.glyphicon.glyphicon-new-window
|
18
|
+
.pull-right.badge
|
19
|
+
| #{err.code if err.code > 0} #{err.message}
|
20
|
+
ul.list-group
|
21
|
+
- err.refs.each do |ref|
|
22
|
+
li.list-group-item
|
23
|
+
a href="view-source:#{ref.src}" target='_blank'
|
24
|
+
| #{ref.src} (line #{ref.line_no})
|
25
|
+
i.glyphicon.glyphicon-new-window
|
26
|
+
pre #{ref.snippet}
|
27
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'slim'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
module Blinkr
|
5
|
+
class Report
|
6
|
+
|
7
|
+
TMPL = File.expand_path('report.html.slim', File.dirname(__FILE__))
|
8
|
+
|
9
|
+
def self.render(errors, out_file)
|
10
|
+
out_file ||= 'blinkr.html'
|
11
|
+
File.open(out_file, 'w') { |file| file.write(Slim::Template.new(TMPL).render(OpenStruct.new({:errors => errors}))) }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
metadata
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: blinkr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pete Muir
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-07-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.3'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: nokogiri
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.5'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: typhoeus
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.6'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.6'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: slim
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '2.0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '2.0'
|
83
|
+
description:
|
84
|
+
email:
|
85
|
+
- pmuir@bleepbleep.org.uk
|
86
|
+
executables:
|
87
|
+
- blinkr
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- ".gitignore"
|
92
|
+
- ".ruby-gemset"
|
93
|
+
- ".ruby-version"
|
94
|
+
- Gemfile
|
95
|
+
- LICENSE.txt
|
96
|
+
- README.md
|
97
|
+
- Rakefile
|
98
|
+
- bin/blinkr
|
99
|
+
- blinkr.gemspec
|
100
|
+
- lib/blinkr.rb
|
101
|
+
- lib/blinkr/cache.rb
|
102
|
+
- lib/blinkr/check.rb
|
103
|
+
- lib/blinkr/report.html.slim
|
104
|
+
- lib/blinkr/report.rb
|
105
|
+
- lib/blinkr/version.rb
|
106
|
+
homepage: ''
|
107
|
+
licenses:
|
108
|
+
- Apache-2.0
|
109
|
+
metadata: {}
|
110
|
+
post_install_message:
|
111
|
+
rdoc_options: []
|
112
|
+
require_paths:
|
113
|
+
- lib
|
114
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - "~>"
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '2.0'
|
119
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
requirements: []
|
125
|
+
rubyforge_project:
|
126
|
+
rubygems_version: 2.2.2
|
127
|
+
signing_key:
|
128
|
+
specification_version: 4
|
129
|
+
summary: A simple broken link checker
|
130
|
+
test_files: []
|