sitediff 0.0.2 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/sitediff +9 -3
- data/lib/sitediff.rb +153 -79
- data/lib/sitediff/api.rb +265 -0
- data/lib/sitediff/cache.rb +110 -47
- data/lib/sitediff/cli.rb +219 -165
- data/lib/sitediff/config.rb +439 -58
- data/lib/sitediff/config/creator.rb +93 -99
- data/lib/sitediff/config/preset.rb +75 -0
- data/lib/sitediff/crawler.rb +108 -72
- data/lib/sitediff/diff.rb +60 -12
- data/lib/sitediff/exception.rb +3 -1
- data/lib/sitediff/fetch.rb +62 -41
- data/lib/sitediff/files/diff.html.erb +20 -2
- data/lib/sitediff/files/jquery.min.js +2 -0
- data/lib/sitediff/files/normalize.css +349 -0
- data/lib/sitediff/files/report.html.erb +171 -0
- data/lib/sitediff/files/sidebyside.html.erb +5 -2
- data/lib/sitediff/files/sitediff.css +303 -30
- data/lib/sitediff/files/sitediff.js +367 -0
- data/lib/sitediff/report.rb +254 -0
- data/lib/sitediff/result.rb +59 -23
- data/lib/sitediff/sanitize.rb +222 -150
- data/lib/sitediff/sanitize/dom_transform.rb +111 -73
- data/lib/sitediff/sanitize/regexp.rb +69 -43
- data/lib/sitediff/uriwrapper.rb +104 -34
- data/lib/sitediff/webserver.rb +89 -77
- data/lib/sitediff/webserver/resultserver.rb +113 -77
- metadata +92 -76
- data/lib/sitediff/files/html_report.html.erb +0 -63
- data/lib/sitediff/files/rules/drupal.yaml +0 -33
- data/lib/sitediff/rules.rb +0 -65
@@ -0,0 +1,367 @@
|
|
1
|
+
/**
|
2
|
+
* @file
|
3
|
+
* SiteDiff report behaviors.
|
4
|
+
*/
|
5
|
+
|
6
|
+
'use strict';
|
7
|
+
|
8
|
+
/* global $ */
|
9
|
+
/**
|
10
|
+
* SiteDiff namespace.
|
11
|
+
*/
|
12
|
+
var SiteDiff = SiteDiff || {};
|
13
|
+
|
14
|
+
/**
|
15
|
+
* SiteDiff global map of diffs.
|
16
|
+
*/
|
17
|
+
SiteDiff.diffs = SiteDiff.diffs || {};
|
18
|
+
|
19
|
+
SiteDiff.currentDiff = -1;
|
20
|
+
|
21
|
+
/**
|
22
|
+
* Scrolls the document to the said position.
|
23
|
+
*
|
24
|
+
* @param options
|
25
|
+
* Object specifying various options.
|
26
|
+
*
|
27
|
+
* x: X position.
|
28
|
+
* y: Y position.
|
29
|
+
* animate: Whether to animate.
|
30
|
+
* callback: A function to call after scrolling.
|
31
|
+
*/
|
32
|
+
SiteDiff.scrollToPosition = function (options) {
|
33
|
+
// Compute vertical and horizontal adjustments, if any.
|
34
|
+
// Example: Fixed elements, etc.
|
35
|
+
var xFix = 0;
|
36
|
+
var yFix = 0 - 100;
|
37
|
+
|
38
|
+
// Determine final x and y offsets.
|
39
|
+
var x = parseInt(options.x) + xFix;
|
40
|
+
x = Math.max(x, 0);
|
41
|
+
var y = parseInt(options.y) + yFix;
|
42
|
+
y = Math.max(y, 0);
|
43
|
+
|
44
|
+
// Perform the scroll with or without animation.
|
45
|
+
window.scrollTo(x, y);
|
46
|
+
|
47
|
+
// Trigger a callback, if any.
|
48
|
+
if (options.callback) {
|
49
|
+
options.callback();
|
50
|
+
}
|
51
|
+
};
|
52
|
+
|
53
|
+
/**
|
54
|
+
* Scrolls to a DOM element on the page.
|
55
|
+
*
|
56
|
+
* @param el
|
57
|
+
* The DOM element.
|
58
|
+
*
|
59
|
+
* @param options
|
60
|
+
* Object specifying various options.
|
61
|
+
*
|
62
|
+
* "callback" to trigger after scrolling.
|
63
|
+
*/
|
64
|
+
SiteDiff.scrollToElement = function (el, options) {
|
65
|
+
options = options || {};
|
66
|
+
var callback = options.callback || function () {};
|
67
|
+
|
68
|
+
// See if the element exists.
|
69
|
+
var $el = $(el).first();
|
70
|
+
if ($el.length == 1) {
|
71
|
+
// Inject callback to focus on the element we scroll to.
|
72
|
+
options.x = 0;
|
73
|
+
options.y = $el.offset().top;
|
74
|
+
options.callback = function () {
|
75
|
+
$el.focus();
|
76
|
+
callback.call(el);
|
77
|
+
};
|
78
|
+
SiteDiff.scrollToPosition(options);
|
79
|
+
}
|
80
|
+
};
|
81
|
+
|
82
|
+
/**
|
83
|
+
* Initialize behaviors.
|
84
|
+
*/
|
85
|
+
SiteDiff.init = function () {
|
86
|
+
// On the overview page.
|
87
|
+
switch ($(document.body).data('page')) {
|
88
|
+
case 'overview':
|
89
|
+
SiteDiff.initFilterForm();
|
90
|
+
break;
|
91
|
+
|
92
|
+
case 'diff':
|
93
|
+
SiteDiff.jumpToFirstDiff();
|
94
|
+
break;
|
95
|
+
}
|
96
|
+
};
|
97
|
+
|
98
|
+
/**
|
99
|
+
* Initializes report filters and overlay.
|
100
|
+
*/
|
101
|
+
SiteDiff.initFilterForm = function () {
|
102
|
+
SiteDiff.initDiffArray();
|
103
|
+
SiteDiff.initStatusFilter();
|
104
|
+
SiteDiff.initSearchFilter();
|
105
|
+
SiteDiff.initOverlay();
|
106
|
+
SiteDiff.initClickHandlers();
|
107
|
+
};
|
108
|
+
|
109
|
+
/**
|
110
|
+
* Initialize global diff array
|
111
|
+
*
|
112
|
+
*/
|
113
|
+
SiteDiff.initDiffArray = function() {
|
114
|
+
SiteDiff.diffs = $('.button-diff').map(function (i, element) {
|
115
|
+
var $el = $(element);
|
116
|
+
$el.data('diffindex', i);
|
117
|
+
return {
|
118
|
+
diff: $el.attr('href'),
|
119
|
+
element: $el,
|
120
|
+
index: i,
|
121
|
+
path: $el.parents('.description').find('.path').text()
|
122
|
+
};
|
123
|
+
});
|
124
|
+
};
|
125
|
+
|
126
|
+
/**
|
127
|
+
* Initializes the "status" filter.
|
128
|
+
*/
|
129
|
+
SiteDiff.initStatusFilter = function () {
|
130
|
+
$('.form-item--status input')
|
131
|
+
.on('change', function () {
|
132
|
+
// Get a list of applied filters.
|
133
|
+
var appliedFilters = $('.form-item--status input:checked')
|
134
|
+
.map(function () {
|
135
|
+
return this.getAttribute('value');
|
136
|
+
// applied.push(this.getAttribute('value'));
|
137
|
+
});
|
138
|
+
// Show only matching results, hide the rest.
|
139
|
+
$('#sitediff-report')
|
140
|
+
.find('.sitediff-result')
|
141
|
+
.each(function () {
|
142
|
+
var $row = $(this);
|
143
|
+
var status = $row.data('status');
|
144
|
+
if (
|
145
|
+
// Row matches applied filters.
|
146
|
+
$.inArray(status, appliedFilters) > -1 ||
|
147
|
+
// No filters are applied.
|
148
|
+
appliedFilters.length === 0
|
149
|
+
) {
|
150
|
+
$row.removeAttr('hidden');
|
151
|
+
}
|
152
|
+
else {
|
153
|
+
$row.attr('hidden', 'hidden');
|
154
|
+
}
|
155
|
+
});
|
156
|
+
});
|
157
|
+
};
|
158
|
+
|
159
|
+
/**
|
160
|
+
* Initializes the "search" filter.
|
161
|
+
*/
|
162
|
+
SiteDiff.initSearchFilter = function () {
|
163
|
+
$('#input-search')
|
164
|
+
.on('change keyup', function () {
|
165
|
+
var keyword = $(this).val().toLowerCase();
|
166
|
+
|
167
|
+
// Filter the records.
|
168
|
+
// TODO: Trigger one event per 250ms.
|
169
|
+
$('#sitediff-report')
|
170
|
+
.find('.sitediff-result')
|
171
|
+
.each(function () {
|
172
|
+
var $row = $(this);
|
173
|
+
var path = $row.find('.path').text();
|
174
|
+
|
175
|
+
// If keyword matches, keep the row visible.
|
176
|
+
if (path.toLowerCase().indexOf(keyword) > -1) {
|
177
|
+
$row.attr('hidden', null);
|
178
|
+
}
|
179
|
+
else {
|
180
|
+
$row.attr('hidden', 'hidden');
|
181
|
+
}
|
182
|
+
});
|
183
|
+
});
|
184
|
+
};
|
185
|
+
|
186
|
+
/**
|
187
|
+
* Set up the diff overlay to be displayed.
|
188
|
+
*/
|
189
|
+
SiteDiff.initOverlay = function () {
|
190
|
+
if (SiteDiff.diffs.length <= 0) return;
|
191
|
+
|
192
|
+
// add overlay
|
193
|
+
$('body').append($(
|
194
|
+
'<div class="overlay" style="display: none;"><div class="overlay__inner"><header>' +
|
195
|
+
'<div class="path"></div>' +
|
196
|
+
'<div class="prev"><a href="#" title="Previous diff (left arrow)">< Prev</a></div>' +
|
197
|
+
'<div class="next"><a href="#" title="Next diff (right arrow)">Next ></a></div>' +
|
198
|
+
'<div class="exit"><a href="#" title="Close diff display (Esc)">Close</a></div>' +
|
199
|
+
'</header><article></article></div></div>'));
|
200
|
+
// add header click handlers
|
201
|
+
$('.overlay header .exit').click(function (event) {
|
202
|
+
event.preventDefault();
|
203
|
+
SiteDiff.destroyOverlay();
|
204
|
+
});
|
205
|
+
$('.overlay header .prev').click(function (event) {
|
206
|
+
event.preventDefault();
|
207
|
+
SiteDiff.prevDiff();
|
208
|
+
});
|
209
|
+
$('.overlay header .next').click(function (event) {
|
210
|
+
event.preventDefault();
|
211
|
+
SiteDiff.nextDiff();
|
212
|
+
});
|
213
|
+
|
214
|
+
};
|
215
|
+
|
216
|
+
/**
|
217
|
+
* Set up click handlers for all diff buttons
|
218
|
+
*/
|
219
|
+
SiteDiff.initClickHandlers = function () {
|
220
|
+
SiteDiff.diffs.each( function (i, diff) {
|
221
|
+
diff.element.click({index: i}, function (event) {
|
222
|
+
event.preventDefault();
|
223
|
+
SiteDiff.openOverlay(event.data.index);
|
224
|
+
});
|
225
|
+
});
|
226
|
+
};
|
227
|
+
|
228
|
+
/**
|
229
|
+
* Set up key handlers for overlay.
|
230
|
+
*/
|
231
|
+
SiteDiff.initKeyHandlers = function () {
|
232
|
+
$(document).keyup(function (event) {
|
233
|
+
switch (event.which) {
|
234
|
+
case 37:
|
235
|
+
SiteDiff.prevDiff();
|
236
|
+
break;
|
237
|
+
case 39:
|
238
|
+
SiteDiff.nextDiff();
|
239
|
+
break;
|
240
|
+
case 27:
|
241
|
+
SiteDiff.destroyOverlay();
|
242
|
+
break;
|
243
|
+
}
|
244
|
+
});
|
245
|
+
};
|
246
|
+
|
247
|
+
/**
|
248
|
+
* Remove overlay key handlers.
|
249
|
+
*/
|
250
|
+
SiteDiff.removeKeyHandlers = function () {
|
251
|
+
$(document).off('keyup');
|
252
|
+
};
|
253
|
+
|
254
|
+
/**
|
255
|
+
* Open overlay for the diff identified by the `index`.
|
256
|
+
*
|
257
|
+
* @param integer index
|
258
|
+
* The index of the diff to be viewed.
|
259
|
+
*/
|
260
|
+
SiteDiff.openOverlay = function (index) {
|
261
|
+
SiteDiff.currentDiff = index;
|
262
|
+
SiteDiff.showDiff();
|
263
|
+
SiteDiff.initKeyHandlers();
|
264
|
+
$('.overlay').fadeIn(300);
|
265
|
+
};
|
266
|
+
|
267
|
+
/**
|
268
|
+
* Create the iframe to display the current diff.
|
269
|
+
*/
|
270
|
+
SiteDiff.showDiff = function () {
|
271
|
+
var diff = SiteDiff.diffs[SiteDiff.currentDiff];
|
272
|
+
var iframe = '<iframe src="' + diff.diff + '"></iframe>';
|
273
|
+
$('.overlay header .path').text(diff.path);
|
274
|
+
SiteDiff.setPrevNext();
|
275
|
+
$('.overlay article').html(iframe);
|
276
|
+
};
|
277
|
+
|
278
|
+
/**
|
279
|
+
* Hide the overlay and clean up.
|
280
|
+
*/
|
281
|
+
SiteDiff.destroyOverlay = function () {
|
282
|
+
$('.overlay article').empty();
|
283
|
+
SiteDiff.removeKeyHandlers();
|
284
|
+
$('.overlay').fadeOut(300, SiteDiff.scrollToButton);
|
285
|
+
};
|
286
|
+
|
287
|
+
/**
|
288
|
+
* Display the previous diff.
|
289
|
+
*/
|
290
|
+
SiteDiff.prevDiff = function () {
|
291
|
+
if (SiteDiff.currentDiff > 0) {
|
292
|
+
SiteDiff.currentDiff--;
|
293
|
+
SiteDiff.showDiff();
|
294
|
+
}
|
295
|
+
};
|
296
|
+
|
297
|
+
/**
|
298
|
+
* Display the next diff.
|
299
|
+
*/
|
300
|
+
SiteDiff.nextDiff = function () {
|
301
|
+
if (SiteDiff.currentDiff < SiteDiff.diffs.length - 1) {
|
302
|
+
SiteDiff.currentDiff++;
|
303
|
+
SiteDiff.showDiff();
|
304
|
+
}
|
305
|
+
};
|
306
|
+
|
307
|
+
/**
|
308
|
+
* Enable or disable prev and next buttons based on current diff.
|
309
|
+
*/
|
310
|
+
SiteDiff.setPrevNext = function () {
|
311
|
+
if (SiteDiff.currentDiff <= 0) {
|
312
|
+
// set prev disabled
|
313
|
+
$('.overlay header .prev').addClass('disabled');
|
314
|
+
}
|
315
|
+
else {
|
316
|
+
$('.overlay header .prev.disabled').removeClass('disabled');
|
317
|
+
}
|
318
|
+
if (SiteDiff.currentDiff >= SiteDiff.diffs.length - 1) {
|
319
|
+
// set next disabled
|
320
|
+
$('.overlay header .next').addClass('disabled');
|
321
|
+
}
|
322
|
+
else {
|
323
|
+
$('.overlay header .next.disabled').removeClass('disabled');
|
324
|
+
}
|
325
|
+
};
|
326
|
+
|
327
|
+
/**
|
328
|
+
* Scroll to the button associated with the current diff.
|
329
|
+
*/
|
330
|
+
SiteDiff.scrollToButton = function () {
|
331
|
+
var $diffButton = SiteDiff.diffs[SiteDiff.currentDiff].element;
|
332
|
+
if (! SiteDiff.isElementVisible($diffButton)) {
|
333
|
+
SiteDiff.scrollToElement($diffButton);
|
334
|
+
}
|
335
|
+
};
|
336
|
+
|
337
|
+
/**
|
338
|
+
* Check if an element is at least partly visible.
|
339
|
+
* @param element
|
340
|
+
*/
|
341
|
+
SiteDiff.isElementVisible = function (element) {
|
342
|
+
var topVisible = $(window).scrollTop();
|
343
|
+
var bottomVisible = topVisible + $(window).height();
|
344
|
+
var elemTop = $(element).offset().top;
|
345
|
+
var elemBottom = elemTop + $(element).height();
|
346
|
+
return ((elemBottom <= bottomVisible) && (elemTop >= topVisible));
|
347
|
+
};
|
348
|
+
|
349
|
+
/**
|
350
|
+
* Jumps to the first diff on the page.
|
351
|
+
*/
|
352
|
+
SiteDiff.jumpToFirstDiff = function () {
|
353
|
+
// Get the first diff hunk.
|
354
|
+
var $diff = $('#diff-container')
|
355
|
+
.find('.del, .ins')
|
356
|
+
.first();
|
357
|
+
if ($diff.length === 0) {
|
358
|
+
return;
|
359
|
+
}
|
360
|
+
|
361
|
+
// Scroll the window to it!
|
362
|
+
setTimeout(function () {
|
363
|
+
SiteDiff.scrollToElement($diff[0]);
|
364
|
+
}, 250);
|
365
|
+
};
|
366
|
+
|
367
|
+
$(document).ready(SiteDiff.init);
|
@@ -0,0 +1,254 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'json'
|
5
|
+
require 'minitar'
|
6
|
+
require 'sitediff'
|
7
|
+
require 'sitediff/config'
|
8
|
+
require 'zlib'
|
9
|
+
|
10
|
+
class SiteDiff
|
11
|
+
##
|
12
|
+
# SiteDiff Report Helper.
|
13
|
+
class Report
|
14
|
+
attr_reader :results, :cache
|
15
|
+
|
16
|
+
##
|
17
|
+
# Directory where diffs will be generated.
|
18
|
+
DIFFS_DIR = 'diffs'
|
19
|
+
|
20
|
+
##
|
21
|
+
# Name of file containing a list of pages with diffs.
|
22
|
+
FAILURES_FILE = 'failures.txt'
|
23
|
+
|
24
|
+
##
|
25
|
+
# Name of file containing HTML report of diffs.
|
26
|
+
REPORT_FILE_HTML = 'report.html'
|
27
|
+
|
28
|
+
##
|
29
|
+
# Name of file containing JSON report of diffs.
|
30
|
+
REPORT_FILE_JSON = 'report.json'
|
31
|
+
|
32
|
+
##
|
33
|
+
# Name of file containing exported file archive.
|
34
|
+
REPORT_FILE_TAR = 'report.tgz'
|
35
|
+
|
36
|
+
##
|
37
|
+
# Name of directory in which to build the portable report.
|
38
|
+
REPORT_BUILD_DIR = '_tmp_report'
|
39
|
+
|
40
|
+
##
|
41
|
+
# Name of the portable report directory.
|
42
|
+
REPORT_DIR = 'report'
|
43
|
+
|
44
|
+
##
|
45
|
+
# Path to settings used for report.
|
46
|
+
SETTINGS_FILE = 'settings.yaml'
|
47
|
+
|
48
|
+
##
|
49
|
+
# Creates a Reporter object.
|
50
|
+
#
|
51
|
+
# @param [Config] config.
|
52
|
+
# @param [Cache] cache.
|
53
|
+
# @param [Array] results.
|
54
|
+
def initialize(config, cache, results)
|
55
|
+
@config = config
|
56
|
+
@cache = cache
|
57
|
+
@results = results
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Generates an HTML report.
|
62
|
+
#
|
63
|
+
# @param [String] dir
|
64
|
+
# The directory in which the report is to be generated.
|
65
|
+
def generate_html(
|
66
|
+
dir,
|
67
|
+
report_before = nil,
|
68
|
+
report_after = nil
|
69
|
+
)
|
70
|
+
report_before ||= @config.before_url
|
71
|
+
report_after ||= @config.after_url
|
72
|
+
@config.before_time = get_timestamp(:before)
|
73
|
+
@config.after_time = get_timestamp(:after)
|
74
|
+
|
75
|
+
dir = SiteDiff.ensure_dir dir
|
76
|
+
|
77
|
+
write_diffs dir
|
78
|
+
write_failures dir
|
79
|
+
|
80
|
+
# Prepare report.
|
81
|
+
report = Diff.generate_html(
|
82
|
+
@results,
|
83
|
+
report_before,
|
84
|
+
report_after,
|
85
|
+
@cache,
|
86
|
+
@config
|
87
|
+
)
|
88
|
+
|
89
|
+
# Write report.
|
90
|
+
report_file = dir + REPORT_FILE_HTML
|
91
|
+
report_file.unlink if report_file.file?
|
92
|
+
report_file.open('w') { |f| f.write(report) }
|
93
|
+
|
94
|
+
write_settings dir, report_before, report_after
|
95
|
+
|
96
|
+
if @config.export
|
97
|
+
package_report(dir)
|
98
|
+
else
|
99
|
+
SiteDiff.log 'Report generated to ' + report_file.expand_path.to_s
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
##
|
104
|
+
# Generates a JSON report.
|
105
|
+
#
|
106
|
+
# @param dir
|
107
|
+
# The directory in which the report is to be generated.
|
108
|
+
def generate_json(dir)
|
109
|
+
dir = SiteDiff.ensure_dir dir
|
110
|
+
write_diffs dir
|
111
|
+
write_failures dir
|
112
|
+
|
113
|
+
# Prepare report.
|
114
|
+
report = {
|
115
|
+
paths_compared: @results.length,
|
116
|
+
paths_diffs: 0,
|
117
|
+
paths: {}
|
118
|
+
}
|
119
|
+
@results.each do |item|
|
120
|
+
report[:paths_diffs] += 1 unless item.success?
|
121
|
+
|
122
|
+
item_report = {
|
123
|
+
path: item.path,
|
124
|
+
status: item.status,
|
125
|
+
message: item.error
|
126
|
+
}
|
127
|
+
report[:paths][item.path] = item_report
|
128
|
+
end
|
129
|
+
report = JSON report
|
130
|
+
|
131
|
+
# Write report.
|
132
|
+
report_file = dir + REPORT_FILE_JSON
|
133
|
+
report_file.unlink if report_file.file?
|
134
|
+
report_file.open('w') { |f| f.write(report) }
|
135
|
+
|
136
|
+
write_settings dir
|
137
|
+
|
138
|
+
SiteDiff.log 'Report generated to ' + report_file.expand_path.to_s
|
139
|
+
end
|
140
|
+
|
141
|
+
##
|
142
|
+
# Package report for export.
|
143
|
+
def package_report(dir)
|
144
|
+
# Create temporaryreport directories.
|
145
|
+
temp_path = dir + REPORT_BUILD_DIR
|
146
|
+
temp_path.rmtree if temp_path.directory?
|
147
|
+
temp_path.mkpath
|
148
|
+
report_path = temp_path + REPORT_DIR
|
149
|
+
report_path.mkpath
|
150
|
+
files_path = report_path + 'files'
|
151
|
+
files_path.mkpath
|
152
|
+
diffs_path = dir + DIFFS_DIR
|
153
|
+
|
154
|
+
# Move files to place.
|
155
|
+
FileUtils.move(dir + REPORT_FILE_HTML, report_path)
|
156
|
+
FileUtils.move(diffs_path, files_path) if diffs_path.directory?
|
157
|
+
|
158
|
+
# Make tar file.
|
159
|
+
Dir.chdir(temp_path) do
|
160
|
+
Minitar.pack(
|
161
|
+
REPORT_DIR,
|
162
|
+
Zlib::GzipWriter.new(File.open(REPORT_FILE_TAR, 'wb'))
|
163
|
+
)
|
164
|
+
end
|
165
|
+
FileUtils.move(temp_path + REPORT_FILE_TAR, dir)
|
166
|
+
temp_path.rmtree
|
167
|
+
SiteDiff.log 'Archived report generated to ' + dir.join(REPORT_FILE_TAR).to_s
|
168
|
+
end
|
169
|
+
|
170
|
+
##
|
171
|
+
# Creates diff files in a directory named "diffs".
|
172
|
+
#
|
173
|
+
# If "dir" is /foo/bar, then diffs will be placed in /foo/bar/diffs.
|
174
|
+
#
|
175
|
+
# @param [Pathname] dir
|
176
|
+
# The directory in which a "diffs" directory is to be generated.
|
177
|
+
def write_diffs(dir)
|
178
|
+
raise Exception 'dir must be a Pathname' unless dir.is_a? Pathname
|
179
|
+
|
180
|
+
# Delete existing "diffs" dir, if exists.
|
181
|
+
diff_dir = dir + DIFFS_DIR
|
182
|
+
diff_dir.rmtree if diff_dir.exist?
|
183
|
+
|
184
|
+
# Write diffs to the diff directory.
|
185
|
+
@results.each { |r| r.dump(dir, @config.export) if r.status == Result::STATUS_FAILURE }
|
186
|
+
SiteDiff.log "All diff files written to #{diff_dir.expand_path}" unless @config.export
|
187
|
+
end
|
188
|
+
|
189
|
+
##
|
190
|
+
# Writes paths with diffs into a file.
|
191
|
+
#
|
192
|
+
# @param [Pathname] dir
|
193
|
+
# The directory in which the report is to be generated.
|
194
|
+
def write_failures(dir)
|
195
|
+
raise Exception 'dir must be a Pathname' unless dir.is_a? Pathname
|
196
|
+
|
197
|
+
failures = dir + FAILURES_FILE
|
198
|
+
SiteDiff.log "All failures written to #{failures.expand_path}"
|
199
|
+
failures.open('w') do |f|
|
200
|
+
@results.each { |r| f.puts r.path unless r.success? }
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
##
|
205
|
+
# Creates report settings.yaml file.
|
206
|
+
#
|
207
|
+
# TODO: Find a way to avoid having to create this file.
|
208
|
+
#
|
209
|
+
# @param [Pathname] dir
|
210
|
+
# The directory in which the report is to be generated.
|
211
|
+
def write_settings(dir, report_before = nil, report_after = nil)
|
212
|
+
raise Exception 'dir must be a Pathname' unless dir.is_a? Pathname
|
213
|
+
|
214
|
+
settings = {
|
215
|
+
'before' => report_before,
|
216
|
+
'after' => report_after,
|
217
|
+
'cached' => %w[before after]
|
218
|
+
}
|
219
|
+
dir.+(SETTINGS_FILE).open('w') { |f| YAML.dump(settings, f) }
|
220
|
+
end
|
221
|
+
|
222
|
+
##
|
223
|
+
# Returns CSS for HTML report.
|
224
|
+
def self.css
|
225
|
+
output = ''
|
226
|
+
output += File.read(File.join(SiteDiff::FILES_DIR, 'normalize.css'))
|
227
|
+
output += File.read(File.join(SiteDiff::FILES_DIR, 'sitediff.css'))
|
228
|
+
output
|
229
|
+
end
|
230
|
+
|
231
|
+
##
|
232
|
+
# Returns JS for HTML report.
|
233
|
+
def self.js
|
234
|
+
output = ''
|
235
|
+
output += File.read(File.join(SiteDiff::FILES_DIR, 'jquery.min.js'))
|
236
|
+
output += File.read(File.join(SiteDiff::FILES_DIR, 'sitediff.js'))
|
237
|
+
output
|
238
|
+
end
|
239
|
+
|
240
|
+
private
|
241
|
+
|
242
|
+
# Get crawl timestamps
|
243
|
+
def get_timestamp(tag)
|
244
|
+
timestamp_file = File.join(@config.directory, 'snapshot', tag.to_s, SiteDiff::Cache::TIMESTAMP_FILE)
|
245
|
+
if File.exist? timestamp_file
|
246
|
+
file = File::Stat.new(timestamp_file)
|
247
|
+
time = file.mtime
|
248
|
+
time.class == Time ? time.strftime('%Y-%m-%d %H:%M') : ''
|
249
|
+
else
|
250
|
+
'unknown'
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|