ndd-url_checker 0.2.1 → 0.3.0

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +2 -1
  4. data/Gemfile.lock +57 -44
  5. data/README.md +5 -2
  6. data/VERSION +1 -1
  7. data/lib/ndd/url_checker.rb +2 -0
  8. data/lib/ndd/url_checker/blocking_url_checker.rb +7 -4
  9. data/lib/ndd/url_checker/forked_url_checker.rb +4 -2
  10. data/lib/ndd/url_checker/reporting_url_checker.csv.erb +2 -2
  11. data/lib/ndd/url_checker/reporting_url_checker.html.erb +171 -80
  12. data/lib/ndd/url_checker/reporting_url_checker.json.erb +16 -9
  13. data/lib/ndd/url_checker/reporting_url_checker.rb +22 -11
  14. data/lib/ndd/url_checker/status.rb +1 -1
  15. data/lib/ndd/url_checker/status_decorator.rb +64 -0
  16. data/ndd-url_checker.gemspec +6 -4
  17. data/spec/ndd/url_checker/abstract_url_checker_spec.rb +1 -1
  18. data/spec/ndd/url_checker/blocking_url_checker_spec.rb +1 -1
  19. data/spec/ndd/url_checker/forked_url_checker_spec.rb +1 -1
  20. data/spec/ndd/url_checker/parallel_url_checker_spec.rb +1 -1
  21. data/spec/ndd/url_checker/reporting_url_checker/custom.txt.erb +2 -2
  22. data/spec/ndd/url_checker/reporting_url_checker/multiple_urls.csv +5 -3
  23. data/spec/ndd/url_checker/reporting_url_checker/multiple_urls.html +227 -92
  24. data/spec/ndd/url_checker/reporting_url_checker/multiple_urls.json +29 -10
  25. data/spec/ndd/url_checker/reporting_url_checker/multiple_urls.txt +12 -2
  26. data/spec/ndd/url_checker/reporting_url_checker/single_url.csv +1 -1
  27. data/spec/ndd/url_checker/reporting_url_checker/single_url.html +163 -78
  28. data/spec/ndd/url_checker/reporting_url_checker/single_url.json +14 -7
  29. data/spec/ndd/url_checker/reporting_url_checker_spec.rb +29 -12
  30. data/spec/ndd/url_checker/status_decorator_spec.rb +208 -0
  31. data/spec/ndd/url_checker/status_spec.rb +10 -10
  32. data/spec/ndd/url_checker/threaded_url_checker_spec.rb +1 -1
  33. data/spec/spec_helper.rb +1 -3
  34. data/spec/support/multiple_url_checker_spec.rb +4 -4
  35. data/spec/support/single_url_checker_spec.rb +74 -21
  36. metadata +5 -3
@@ -1,20 +1,27 @@
1
1
  {
2
2
  "benchmark": {
3
- "utime": "<%= benchmark.utime %>",
4
- "stime": "<%= benchmark.stime %>",
5
- "total": "<%= benchmark.total %>",
6
- "real": "<%= benchmark.real %>",
7
- "size": "<%= results.size %>",
8
- "throughput": "<%= benchmark.real/results.size %>"
3
+ "total_duration": <%= benchmark.total_duration %>,
4
+ "average_duration": <%= benchmark.average_duration %>,
5
+ "average_throughput": <%= benchmark.average_throughput %>
6
+ },
7
+ "statistics": {
8
+ "count": <%= urls.count %>,
9
+ "valid_count": <%= urls.valid_count %>,
10
+ "direct_count": <%= urls.direct_count %>,
11
+ "redirected_count": <%= urls.redirected_count %>,
12
+ "invalid_count": <%= urls.invalid_count %>,
13
+ "failed_count": <%= urls.failed_count %>,
14
+ "too_many_redirects_count": <%= urls.too_many_redirects_count %>,
15
+ "unknown_host_count": <%= urls.unknown_host_count %>
9
16
  },
10
17
  "results": [
11
- <% results.each_with_index do |status, index| %>
18
+ <% statuses.each_with_index do |status, index| %>
12
19
  {
13
20
  "index": <%= index+1 %>,
14
21
  "url": "<%= status.uri %>",
15
22
  "code": "<%= status.code %>",
16
- "comment": "<% if status.invalid? %><%= status.error %><% end %>"
17
- }<% if index < results.size - 1 %>,<% end %>
23
+ "details": "<% if status.invalid? %><%= status.error %><% end %>"
24
+ }<% if index < statuses.size - 1 %>,<% end %>
18
25
  <% end %>
19
26
  ]
20
27
  }
@@ -24,22 +24,33 @@ module NDD
24
24
  def check(*urls)
25
25
  results = nil
26
26
  benchmark = Benchmark.measure { results = @delegate.check(*urls) }
27
- @logger.debug "Checking #{urls.size} URL(s) benchmark: #{benchmark}"
27
+ @logger.debug "Checked #{urls.size} URL(s) benchmark: #{benchmark}"
28
28
 
29
29
  if urls.size > 1
30
- @context = OpenStruct.new(
31
- {
32
- benchmark: benchmark,
33
- results: results.sort_by { |status| status.uri }
34
- })
30
+ statuses = results.map { |status| StatusDecorator.new(status) }.sort_by { |status| status.uri }
35
31
  else
36
- @context = OpenStruct.new(
37
- {
38
- benchmark: benchmark,
39
- results: [results]
40
- })
32
+ statuses = [results].map { |status| StatusDecorator.new(status) }
41
33
  end
42
34
 
35
+ @context = OpenStruct.new
36
+ @context.statuses = statuses
37
+
38
+ @context.urls = OpenStruct.new
39
+ @context.urls.count = urls.size
40
+ @context.urls.valid_count = statuses.select { |status| status.valid? }.size
41
+ @context.urls.direct_count = statuses.select { |status| status.code == :direct }.size
42
+ @context.urls.redirected_count = statuses.select { |status| status.code == :redirected }.size
43
+ @context.urls.invalid_count = statuses.select { |status| status.invalid? }.size
44
+ @context.urls.failed_count = statuses.select { |status| status.code == :failed }.size
45
+ @context.urls.too_many_redirects_count = statuses.select { |status| status.code == :too_many_redirects }.size
46
+ @context.urls.unknown_host_count = statuses.select { |status| status.code == :unknown_host }.size
47
+
48
+ @context.benchmark = OpenStruct.new
49
+ @context.benchmark.raw = benchmark
50
+ @context.benchmark.total_duration = benchmark.real
51
+ @context.benchmark.average_duration = benchmark.real / urls.size
52
+ @context.benchmark.average_throughput= urls.size / benchmark.real
53
+
43
54
  results
44
55
  end
45
56
 
@@ -49,7 +49,7 @@ module NDD
49
49
  end
50
50
 
51
51
  # When a generic error is raised.
52
- # @param error [StandardError|String] the generic error.
52
+ # @param error [StandardError] the generic error.
53
53
  # @return [self]
54
54
  def failed(error)
55
55
  @error = error
@@ -0,0 +1,64 @@
1
+ require 'delegate'
2
+
3
+ module NDD
4
+ module UrlChecker
5
+
6
+ # Decorate a [Status] for reporting.
7
+ # @author David DIDIER
8
+ class StatusDecorator < SimpleDelegator
9
+
10
+ def code_as_css
11
+ code.to_s.gsub(/_/, '-')
12
+ end
13
+
14
+ def details_title
15
+ case code
16
+ when :direct then
17
+ nil
18
+ when :redirected then
19
+ uris.size - 1
20
+ when :failed then
21
+ return nil unless error
22
+ return error.class.to_s
23
+ when :too_many_redirects then
24
+ uris.size - 1
25
+ when :unknown_host then
26
+ return uris.last
27
+ end
28
+ end
29
+
30
+ def details_body
31
+ case code
32
+ when :direct then
33
+ nil
34
+ when :redirected then
35
+ uris.map { |uri| "- #{uri}\n" }.join
36
+ when :failed then
37
+ return nil unless error
38
+ return error.body if error.kind_of?(Net::HTTPResponse)
39
+ return error.to_s
40
+ when :too_many_redirects then
41
+ uris.map { |uri| "- #{uri}\n" }.join
42
+ when :unknown_host then
43
+ uris.map { |uri| "- #{uri}\n" }.join
44
+ end
45
+ end
46
+
47
+ def details_body_as_html
48
+ body = <<-HTML.gsub(/^ +/, '')
49
+ <p><em>Status:</em> #{code}</p>
50
+ <p><em>URIs:</em><p>
51
+ <ol>#{uris.map { |uri| "<li>#{uri}</li>" }.join}</ol>
52
+ HTML
53
+
54
+ if error
55
+ body += "<p><em>Error:</em> #{error.class.to_s}</p>"
56
+ body += "<p><pre>#{error.body}</pre></p>" if error.kind_of?(Net::HTTPResponse)
57
+ end
58
+
59
+ body
60
+ end
61
+ end
62
+
63
+ end
64
+ end
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: ndd-url_checker 0.2.1 ruby lib
5
+ # stub: ndd-url_checker 0.3.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "ndd-url_checker"
9
- s.version = "0.2.1"
9
+ s.version = "0.3.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
13
13
  s.authors = ["David DIDIER"]
14
- s.date = "2014-12-15"
14
+ s.date = "2015-06-09"
15
15
  s.description = "Validate URLs"
16
16
  s.email = "c_inconnu2@yahoo.fr"
17
17
  s.extra_rdoc_files = [
@@ -42,6 +42,7 @@ Gem::Specification.new do |s|
42
42
  "lib/ndd/url_checker/reporting_url_checker.json.erb",
43
43
  "lib/ndd/url_checker/reporting_url_checker.rb",
44
44
  "lib/ndd/url_checker/status.rb",
45
+ "lib/ndd/url_checker/status_decorator.rb",
45
46
  "lib/ndd/url_checker/threaded_url_checker.rb",
46
47
  "ndd-url_checker.gemspec",
47
48
  "spec/ndd/url_checker/abstract_url_checker_spec.rb",
@@ -58,6 +59,7 @@ Gem::Specification.new do |s|
58
59
  "spec/ndd/url_checker/reporting_url_checker/single_url.json",
59
60
  "spec/ndd/url_checker/reporting_url_checker/single_url.txt",
60
61
  "spec/ndd/url_checker/reporting_url_checker_spec.rb",
62
+ "spec/ndd/url_checker/status_decorator_spec.rb",
61
63
  "spec/ndd/url_checker/status_spec.rb",
62
64
  "spec/ndd/url_checker/threaded_url_checker_spec.rb",
63
65
  "spec/spec_helper.rb",
@@ -66,7 +68,7 @@ Gem::Specification.new do |s|
66
68
  ]
67
69
  s.homepage = "http://github.com/ddidier/ndd-url_checker"
68
70
  s.licenses = ["MIT"]
69
- s.rubygems_version = "2.4.4"
71
+ s.rubygems_version = "2.4.8"
70
72
  s.summary = "Validate URLs"
71
73
 
72
74
  if s.respond_to? :specification_version then
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe NDD::UrlChecker::AbstractUrlChecker do
3
+ RSpec.describe NDD::UrlChecker::AbstractUrlChecker do
4
4
 
5
5
  context '#check' do
6
6
  it 'is not implemented' do
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe NDD::UrlChecker::BlockingUrlChecker do
3
+ RSpec.describe NDD::UrlChecker::BlockingUrlChecker do
4
4
 
5
5
  before(:all) do
6
6
  # Logging.logger.root.level = :debug
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe NDD::UrlChecker::ForkedUrlChecker do
3
+ RSpec.describe NDD::UrlChecker::ForkedUrlChecker do
4
4
 
5
5
  before(:all) do
6
6
  # Logging.logger.root.level = :debug
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe NDD::UrlChecker::ParallelUrlChecker do
3
+ RSpec.describe NDD::UrlChecker::ParallelUrlChecker do
4
4
 
5
5
  before(:all) do
6
6
  # Logging.logger.root.level = :debug
@@ -1,6 +1,6 @@
1
- count = <%= results.size %>
1
+ count = <%= statuses.size %>
2
2
 
3
- <% results.each_with_index do |status, index| %>
3
+ <% statuses.each_with_index do |status, index| %>
4
4
  - index = <%= index+1 %>
5
5
  - uri = <%= status.uri %>
6
6
  - valid = <%= status.valid? %>
@@ -1,4 +1,6 @@
1
- Index,URL,Result,Code,Comment
2
- 1,http://www.google.com,valid,direct,
1
+ Index,URL,Result,Code,Details
2
+ 1,http://www.google.com,valid,redirected,
3
3
  2,http://www.google.de,invalid,failed,some error
4
- 3,http://www.google.fr,valid,direct,
4
+ 3,http://www.google.es,invalid,too_many_redirects,
5
+ 4,http://www.google.fr,valid,direct,
6
+ 5,http://www.google.it,invalid,unknown_host,
@@ -2,110 +2,245 @@
2
2
  <html lang="en">
3
3
 
4
4
  <head>
5
- <meta charset="UTF-8">
6
- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
7
- <style>
8
- body {
9
- padding: 1em;
5
+ <meta charset="UTF-8" />
6
+
7
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
8
+ <style type="text/css">
9
+ .popover-title {
10
+ font-weight: bold;
11
+ }
12
+
13
+ .popover-content em {
14
+ font-style: normal;
15
+ font-weight: bold;
16
+ }
17
+
18
+ .popover-content ol {
19
+ margin-left: -20px;
10
20
  }
11
21
  </style>
12
22
 
13
- <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
14
- <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
23
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
24
+ <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
15
25
  <script language="JavaScript">
16
- $(document).ready(function() {
17
- $('input[type=radio][name=urlsFilter]').change(function() {
18
- if (this.value == 'all') {
19
- $('tr').show();
20
- }
21
- else if (this.value == 'invalid') {
22
- $('tr').not('.danger').hide();
23
- }
26
+ if (!window.ndd_url_checker) {
27
+ window.ndd_url_checker = {};
28
+ }
29
+
30
+ ndd_url_checker.STATES = ['direct', 'redirected', 'failed', 'too-many-redirects', 'unknown-host'];
31
+
32
+ ndd_url_checker.displayStates = function () {
33
+ var displayStates = {};
34
+ $.each(ndd_url_checker.STATES, function (_, state) {
35
+ var checked = $('.display-' + state).is(':checked');
36
+ displayStates[state] = checked;
37
+ });
38
+ return displayStates;
39
+ }
40
+
41
+ ndd_url_checker.filter = function () {
42
+ var displayStates = ndd_url_checker.displayStates();
43
+
44
+ $.each(displayStates, function (state, display) {
45
+ $('.result-' + state).toggle(display);
24
46
  });
47
+ }
48
+
49
+ $(document).ready(function () {
50
+ // show or hide results depending on their state
51
+ $.each(ndd_url_checker.STATES, function (_, state) {
52
+ $('.display-' + state).change(function () {
53
+ ndd_url_checker.filter();
54
+ });
55
+ });
56
+
57
+ // activate all tooltips
58
+ $('[data-toggle="popover"]')
59
+ .popover()
60
+ .click(function (e) {
61
+ e.preventDefault();
62
+ });
25
63
  });
26
64
  </script>
27
65
  </head>
28
66
 
67
+
29
68
  <body>
30
69
 
31
- <h1>URL Checker Report</h1>
32
-
33
- <table class="table table-condensed table-hover" style="width: auto">
34
- <tbody>
35
- <tr>
36
- <td>User CPU time</td>
37
- <td>XXX second(s)</td>
38
- </tr>
39
- <tr>
40
- <td>System CPU time</td>
41
- <td>XXX second(s)</td>
42
- </tr>
43
- <tr>
44
- <td>Total time</td>
45
- <td>XXX second(s)</td>
46
- </tr>
47
- <tr>
48
- <td>Elapsed real time</td>
49
- <td>XXX second(s)</td>
50
- </tr>
51
- <tr>
52
- <td>Number of URLs</td>
53
- <td>3</td>
54
- </tr>
55
- <tr>
56
- <td>Average time for 1 URL</td>
57
- <td>XXX second(s)</td>
58
- </tr>
59
- </tbody>
60
- </table>
61
-
62
- <div class="radio">
63
- <label>
64
- <input type="radio" name="urlsFilter" id="showAllUrls" value="all" checked="true" />
65
- Show all URLs
66
- </label>
67
- </div>
68
- <div class="radio">
69
- <label>
70
- <input type="radio" name="urlsFilter" id="showInvalidUrls" value="invalid" />
71
- Show invalid URLs
72
- </label>
73
- </div>
70
+ <div class="container">
71
+
72
+ <div class="page-header">
73
+ <h1>
74
+ <span class="glyphicon glyphicon-list-alt" aria-hidden="true"></span>
75
+ URL Checker Report
76
+ </h1>
77
+ </div>
78
+
79
+
80
+ <div class="row">
81
+ <div class="col-md-4">
82
+ <dl class="page-info dl-horizontal">
83
+ <dt>Number of URLs</dt>
84
+ <dd>5</dd>
85
+ <dt>Duration</dt>
86
+ <dd>123.456 s</dd>
87
+ <dt>Average duration</dt>
88
+ <dd>123.456 s/URL</dd>
89
+ <dt>Average throughput</dt>
90
+ <dd>123.456 URL/s</dd>
91
+ </dl>
92
+ </div>
93
+ <div class="col-md-4">
94
+ <dl class="page-info dl-horizontal">
95
+ <dt>Valid URLS</dt>
96
+ <dd>2</dd>
97
+ <dt>direct</dt>
98
+ <dd>1</dd>
99
+ <dt>redirected</dt>
100
+ <dd>1</dd>
101
+ </dl>
102
+ </div>
103
+ <div class="col-md-4">
104
+ <dl class="page-info dl-horizontal">
105
+ <dt>Invalid URLS</dt>
106
+ <dd>3</dd>
107
+ <dt>failed</dt>
108
+ <dd>1</dd>
109
+ <dt>too many redirects</dt>
110
+ <dd>1</dd>
111
+ <dt>unknown host</dt>
112
+ <dd>1</dd>
113
+ </dl>
114
+ </div>
115
+ </div>
116
+ <hr />
117
+
118
+
119
+ <div class="row page-controls hidden-print">
120
+ <div class="col-md-6">
121
+ <span>Valid URLs:</span>
122
+
123
+ <div class="btn-group page-display" data-toggle="buttons">
124
+ <label class="btn btn-default active">
125
+ <input type="checkbox" autocomplete="off" class="display-direct" checked="true" />
126
+ Direct (1)
127
+ </label>
128
+ <label class="btn btn-default active">
129
+ <input type="checkbox" autocomplete="off" class="display-redirected" checked="true" />
130
+ Redirected (1)
131
+ </label>
132
+ </div>
133
+ </div>
134
+ <div class="col-md-6">
135
+ <span>Invalid URLs:</span>
136
+
137
+ <div class="btn-group page-display" data-toggle="buttons">
138
+ <label class="btn btn-default active">
139
+ <input type="checkbox" autocomplete="off" class="display-failed" checked="true" />
140
+ Failed (1)
141
+ </label>
142
+ <label class="btn btn-default active">
143
+ <input type="checkbox" autocomplete="off" class="display-too-many-redirects" checked="true" />
144
+ Too many redirects (1)
145
+ </label>
146
+ <label class="btn btn-default active">
147
+ <input type="checkbox" autocomplete="off" class="display-unknown-host" checked="true" />
148
+ Unknown host (1)
149
+ </label>
150
+ </div>
151
+ </div>
152
+ </div>
153
+ <hr />
154
+
74
155
 
75
- <table class="table table-condensed table-hover" style="width: auto">
76
- <thead>
77
- <tr>
78
- <th>#</th>
79
- <th>URL</th>
80
- <th>Code</th>
81
- <th>Comment</th>
82
- </tr>
83
- </thead>
84
- <tbody>
85
-
86
- <tr class="">
87
- <td>1</td>
88
- <td><a href="http://www.google.com" target="_blank">http://www.google.com</a></td>
89
- <td>direct</td>
90
- <td></td>
91
- </tr>
92
-
93
- <tr class="danger">
94
- <td>2</td>
95
- <td><a href="http://www.google.de" target="_blank">http://www.google.de</a></td>
96
- <td>failed</td>
97
- <td>some error</td>
98
- </tr>
99
-
100
- <tr class="">
101
- <td>3</td>
102
- <td><a href="http://www.google.fr" target="_blank">http://www.google.fr</a></td>
103
- <td>direct</td>
104
- <td></td>
105
- </tr>
106
-
107
- </tbody>
108
- </table>
156
+ <table id="results" class="table table-condensed table-hover">
157
+ <thead>
158
+ <tr>
159
+ <th>#</th>
160
+ <th>URL</th>
161
+ <th>Code</th>
162
+ <th>Details</th>
163
+ </tr>
164
+ </thead>
165
+ <tbody>
166
+
167
+ <tr class="result result-redirected ">
168
+ <td>1</td>
169
+ <td><a href="http://www.google.com" target="_blank">http://www.google.com</a></td>
170
+ <td>redirected</td>
171
+ <td>1</td>
172
+ <td>
173
+ <a href="#" data-toggle="popover" data-placement="left" data-trigger="focus"
174
+ data-html="true" title="http://www.google.com" data-content="<p><em>Status:</em> redirected</p>
175
+ <p><em>URIs:</em><p>
176
+ <ol><li>http://www.google.com</li><li>http://www.google.fr</li></ol>
177
+ ">
178
+ <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
179
+ </a>
180
+ </td>
181
+ </tr>
182
+
183
+ <tr class="result result-failed danger">
184
+ <td>2</td>
185
+ <td><a href="http://www.google.de" target="_blank">http://www.google.de</a></td>
186
+ <td>failed</td>
187
+ <td>StandardError</td>
188
+ <td>
189
+ <a href="#" data-toggle="popover" data-placement="left" data-trigger="focus"
190
+ data-html="true" title="http://www.google.de" data-content="<p><em>Status:</em> failed</p>
191
+ <p><em>URIs:</em><p>
192
+ <ol><li>http://www.google.de</li></ol>
193
+ <p><em>Error:</em> StandardError</p>">
194
+ <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
195
+ </a>
196
+ </td>
197
+ </tr>
198
+
199
+ <tr class="result result-too-many-redirects danger">
200
+ <td>3</td>
201
+ <td><a href="http://www.google.es" target="_blank">http://www.google.es</a></td>
202
+ <td>too_many_redirects</td>
203
+ <td>1</td>
204
+ <td>
205
+ <a href="#" data-toggle="popover" data-placement="left" data-trigger="focus"
206
+ data-html="true" title="http://www.google.es" data-content="<p><em>Status:</em> too_many_redirects</p>
207
+ <p><em>URIs:</em><p>
208
+ <ol><li>http://www.google.es</li><li>http://www.google.fr</li></ol>
209
+ ">
210
+ <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
211
+ </a>
212
+ </td>
213
+ </tr>
214
+
215
+ <tr class="result result-direct ">
216
+ <td>4</td>
217
+ <td><a href="http://www.google.fr" target="_blank">http://www.google.fr</a></td>
218
+ <td>direct</td>
219
+ <td></td>
220
+ <td>
221
+ </td>
222
+ </tr>
223
+
224
+ <tr class="result result-unknown-host danger">
225
+ <td>5</td>
226
+ <td><a href="http://www.google.it" target="_blank">http://www.google.it</a></td>
227
+ <td>unknown_host</td>
228
+ <td>http://www.google.it</td>
229
+ <td>
230
+ <a href="#" data-toggle="popover" data-placement="left" data-trigger="focus"
231
+ data-html="true" title="http://www.google.it" data-content="<p><em>Status:</em> unknown_host</p>
232
+ <p><em>URIs:</em><p>
233
+ <ol><li>http://www.google.it</li></ol>
234
+ ">
235
+ <span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
236
+ </a>
237
+ </td>
238
+ </tr>
239
+
240
+ </tbody>
241
+ </table>
242
+
243
+ </div>
109
244
 
110
245
  </body>
111
246
  </html>