Page Menu
Home
Software Heritage
Search
Configure Global Search
Log In
Files
F8391561
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
22 KB
Subscribers
None
View Options
diff --git a/swh/web/templates/revision.html b/swh/web/templates/revision.html
index 5af4fdeb..61afeaae 100644
--- a/swh/web/templates/revision.html
+++ b/swh/web/templates/revision.html
@@ -1,540 +1,559 @@
{% extends "browse.html" %}
{% load static %}
{% block header %}
{% include "includes/content-scripts.html" %}
<script src="{% static 'js/jquery-waypoints/jquery.waypoints.min.js' %}"></script>
{% endblock %}
{% block swh-browse-before-panels %}
{% if origin_context %}
{% include "includes/origin-visit-snapshot.html" %}
{% endif %}
{% endblock %}
{% block swh-browse-main-panel-content %}
<div style="height: 35px;margin: 4px;">
<i class="octicon octicon-git-commit fa-fw"></i>Revision <b>{{ swh_object_metadata.id }}</b>
authored by {{ swh_object_metadata.author }} on <b>{{ swh_object_metadata.date }}</b>
</div>
-<pre style="white-space: pre-wrap">
-<h2>{{ message_header }}</h2>{{ message_body }}
-</pre>
+
+<div class="panel panel-default" style="overflow-x: auto;">
+ <div class="panel-heading" style="padding: 10px">
+ <a data-toggle="collapse" id="swh-collapse-revision-message" href="#swh-revision-message">
+ <div class="pull-left">
+ <pre style="white-space: pre-wrap; background-color: inherit; padding: 0px; margin: 0px; border: none;"><h2 style="padding-bottom: 0px;">{{ message_header }}</h2></pre>
+ </div>
+ <div class="clearfix"></div>
+ </a>
+ </div>
+
+ <div id="swh-revision-message" class="panel-collapse collapse">
+ <pre style="white-space: pre-wrap; margin: 0px; border: none; border-radius: 0px;">{{ message_body }}</pre>
+ </div>
+</div>
+
<div style="margin: 4px; padding-bottom: 5px;">
{{ parents_links }}
</div>
<ul class="nav nav-tabs" style="padding-left: 5px;">
<li class="active"><a data-toggle="tab" href="#swh-revision-tree">Files</a></li>
<li><a data-toggle="tab" href="#swh-revision-changes">Changes</a></li>
</ul>
<div class="tab-content">
<div id="swh-revision-tree" class="tab-pane active">
{% include "includes/top-navigation.html" %}
{% if content_size %}
{% include "includes/content-display.html" %}
{% else %}
{% include "includes/directory-display.html" %}
{% endif %}
</div>
<div id="swh-revision-changes" class="tab-pane">
<div class="panel-group" style="padding: 5px;">
<div class="panel panel-default" style="overflow-x: auto;">
<div class="panel-heading">
<a data-toggle="collapse" href="#swh-revision-changes-list">
<div class="pull-left">
Showing <strong id="swh-revision-changed-files"></strong>
with <strong id="swh-revision-lines-added" style="color:green">0 additions</strong>
and <strong id="swh-revision-lines-deleted" style="color:red">0 deletions</strong>
(<span id="swh-nb-diffs-computed">0</span> / {{ changes|length }} diffs computed)
</div>
<div class="pull-right">
<button class="btn btn-md btn-swh" type="button" onclick="compute_all_diffs(event)" id="swh-compute-all-diffs"
title="By default, diffs will be computed as the view is scrolled.
Pushing that button will request the immediate computation of all diffs.">Compute all diffs</button>
</div>
<div class="clearfix"></div>
</a>
</div>
<div id="swh-revision-changes-list" class="panel-collapse collapse">
<pre style="background: none; border: none;">{{ changes_msg }}</pre>
</div>
</div>
{% for change in changes %}
<div id="panel_{{ change.id }}" class="panel panel-default swh-file-diff-panel" style="overflow-x: auto;">
<div class="panel-heading">
<a data-toggle="collapse" href="#panel_{{ change.id }}_content">
<div class="pull-left swh-title-color">
{% if change.type != 'rename' %}
<strong>{{ change.path }}</strong>
{% else %}
<strong>{{ change.from_path }} → {{ change.to_path }}</strong>
{% endif %}
</div>
</a>
<div class="pull-right">
{% if change.type != 'rename' %}
<div class="btn-group diff-styles" data-toggle="buttons" style="visibility: hidden;">
<button class="btn btn-md btn-swh active unified-diff-button" type="button" onclick="show_unified_diff(event, '{{ change.id }}')">Unified</button>
<button class="btn btn-md btn-swh splitted-diff-button" type="button" onclick="show_splitted_diff(event, '{{ change.id }}')">Side-by-side</button>
</div>
{% endif %}
<a href="{{ change.content_url }}" class="btn btn-md btn-swh" role="button">View file</a>
</div>
<div class="clearfix"></div>
</div>
<div id="panel_{{ change.id }}_content" class="panel-collapse collapse in">
<div class="swh-diff-loading" id="{{ change.id }}-loading" style="text-align: center;visibility: hidden;">
<img src="{% static 'img/swh-spinner.gif' %}"></img>
<p>Loading diff ...</p>
</div>
<div class="highlightjs swh-content" style="display: none;" id="{{ change.id }}-highlightjs">
<div id="{{ change.id }}-unified-diff">
<pre><code class="{{ change.id }}" id="{{ change.id }}"></code></pre>
</div>
<div style="width: 100%; display: none;" id="{{ change.id }}-splitted-diff">
<pre style="width: 50%; float: left;"><code class="{{ change.id }}" id="{{ change.id }}-from"></code></pre>
<pre style="width: 50%"><code class="{{ change.id }}" id="{{ change.id }}-to"></code></pre>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<script>
// number of changed files in the revision
var nb_changed_files = {{ changes|length }};
// to track the number of already computed files diffs
var nb_diffs_computed = 0;
// the no newline at end of file marker from Github
var no_nl_marker = '<span class="no-nl-marker" title="No newline at end of file">' +
'<svg aria-hidden="true" height="16" version="1.1" viewBox="0 0 16 16" width="16">' +
' <path fill-rule="evenodd" d="M16 5v3c0 .55-.45 1-1 1h-3v2L9 8l3-3v2h2V5h2zM8 8c0 2.2-1.8 4-4 4s-4-1.8-4-4 1.8-4 4-4 4 1.8 4 4zM1.5 9.66L5.66 5.5C5.18 5.19 4.61 5 4 5 2.34 5 1 6.34 1 8c0 .61.19 1.17.5 1.66zM7 8c0-.61-.19-1.17-.5-1.66L2.34 10.5c.48.31 1.05.5 1.66.5 1.66 0 3-1.34 3-3z"></path>' +
'</svg>' +
'</span>';
// to track the total number of added lines in files diffs
var nb_additions = 0;
// to track the total number of deleted lines in files diffs
var nb_deletions = 0;
// to track the already computed diffs by id
var computed_diffs = {};
// map a diff id to its computation url
var diffs_urls = {};
// to check if a DOM element is in the viewport
function is_in_viewport(elt) {
var elementTop = $(elt).offset().top;
var elementBottom = elementTop + $(elt).outerHeight();
var viewportTop = $(window).scrollTop();
var viewportBottom = viewportTop + $(window).height();
return elementBottom > viewportTop && elementTop < viewportBottom;
}
// to format the diffs line numbers
function format_ln_diff(from_line, to_line, max_number_chars) {
var ret = '';
if (from_line != null) {
for (var i = 0 ; i < (max_number_chars - from_line.length); ++i) {
ret += ' ';
}
ret += from_line;
}
if (from_line != null && to_line != null) {
ret += ' ';
}
if (to_line != null) {
for (var i = 0 ; i < (max_number_chars - to_line.length); ++i) {
ret += ' ';
}
ret += to_line;
}
return ret;
}
// callback to switch from side-by-side diff to unified one
function show_unified_diff(event, diff_id) {
$('#' + diff_id + '-splitted-diff').css('display', 'none');
$('#' + diff_id + '-unified-diff').css('display', 'block');
$(event.target).parent().find('.splitted-diff-button').removeClass('active');
$(event.target).parent().find('.unified-diff-button').addClass('active');
}
// callback to switch from unified diff to side-by-side one
function show_splitted_diff(event, diff_id) {
$('#' + diff_id + '-unified-diff').css('display', 'none');
$('#' + diff_id + '-splitted-diff').css('display', 'block');
$(event.target).parent().find('.unified-diff-button').removeClass('active');
$(event.target).parent().find('.splitted-diff-button').addClass('active');
}
// to compute diff and process it for display
function compute_diff(diff_url, diff_id) {
// force diff computation ?
var force = diff_url.indexOf('force=true') != -1;
// it no forced computation and diff already computed, do nothing
if (!force && computed_diffs.hasOwnProperty(diff_id)) {
return;
}
// mark diff computation as already requested
computed_diffs[diff_id] = true;
$('#' + diff_id + '-loading').css('visibility', 'visible');
// set spinner visible while requesting diff
$('#' + diff_id + '-loading').css('display', 'block');
$('#' + diff_id + '-highlightjs').css('display', 'none');
// request diff computation and process it
$.ajax({
url: diff_url,
dataType: 'json',
success: function (data) {
// increment number of computed diffs
++nb_diffs_computed;
// toggle the 'Compute all diffs' button if all diffs have been computed
if (nb_diffs_computed == nb_changed_files) {
$('#swh-compute-all-diffs').addClass('active');
}
// Large diff (> threshold) are not automatically computed,
// add a button to force its computation
if (data.diff_str.indexOf('Large diff') == 0) {
$('#' + diff_id)[0].innerHTML = data.diff_str +
'<br/><button class="btn btn-md btn-swh" type="button" onclick="compute_diff(\'' +
diff_url + '&force=true\', \'' + diff_id + '\')">Request diff</button>'
} else {
// prepare code highlighting
$('.' + diff_id).removeClass('nohighlight-swh');
$('.' + diff_id).addClass(data.language);
// set unified diff text
$('#' + diff_id).text(data.diff_str);
// code highlighting for unified diff
$('#' + diff_id).each(function(i, block) {
hljs.highlightBlock(block);
hljs.lineNumbersBlock(block);
});
// process unified diff lines in order to generate side-by-side diffs text
// but also compute line numbers for unified and side-by-side difss
var lines_info_regexp = new RegExp(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/g);
var base_from_line = '';
var base_to_line = '';
var from_to_lines = [];
var from_lines = [];
var to_lines = [];
var max_number_chars = 0;
var diff_from_str = '';
var diff_to_str = '';
var lines_offset = 0;
$('#' + diff_id + ' .hljs-ln-numbers').each(function(i, ln_elt) {
var ln_text = ln_elt.nextSibling.innerText;
var lines_info = lines_info_regexp.exec(ln_text);
var from_line = '';
var to_line = '';
// parsed lines info from the diff output
if (lines_info) {
base_from_line = parseInt(lines_info[1]) - 1;
base_to_line = parseInt(lines_info[3]) - 1;
lines_offset = 0;
diff_from_str += (ln_text + '\n');
diff_to_str += (ln_text + '\n');
from_lines.push('');
to_lines.push('');
// line removed in the from file
} else if (ln_text.length > 0 && ln_text[0] == '-') {
base_from_line = base_from_line + 1;
from_line = base_from_line.toString();
from_lines.push(from_line);
++nb_deletions;
diff_from_str += (ln_text + '\n');
++lines_offset;
// line added in the from file
} else if (ln_text.length > 0 && ln_text[0] == '+') {
base_to_line = base_to_line + 1;
to_line = base_to_line.toString();
to_lines.push(to_line);
++nb_additions;
diff_to_str += (ln_text + '\n');
--lines_offset;
// line present in both files
} else {
base_from_line = base_from_line + 1;
base_to_line = base_to_line + 1;
from_line = base_from_line.toString();
to_line = base_to_line.toString();
for (var j = 0 ; j < Math.abs(lines_offset) ; ++j) {
if (lines_offset > 0) {
diff_to_str += '\n';
to_lines.push('');
} else {
diff_from_str += '\n';
from_lines.push('');
}
}
lines_offset = 0;
diff_from_str += (ln_text + '\n');
diff_to_str += (ln_text + '\n');
to_lines.push(to_line);
from_lines.push(from_line);
}
if (!base_from_line) {
from_line = '';
}
if (!base_to_line) {
to_line = '';
}
from_to_lines[i] = [from_line, to_line];
max_number_chars = Math.max(max_number_chars, from_line.length);
max_number_chars = Math.max(max_number_chars, to_line.length);
});
// set side-by-side diffs text
$('#' + diff_id + '-from').text(diff_from_str);
$('#' + diff_id + '-to').text(diff_to_str);
// code highlighting for side-by-side diffs
$('#' + diff_id + '-from, #' + diff_id + '-to').each(function(i, block) {
hljs.highlightBlock(block);
hljs.lineNumbersBlock(block);
});
// diff highlighting for added/removed lines on top of code highlighting
$('.' + diff_id + ' .hljs-ln-numbers').each(function(i, ln_elt) {
var ln_text = ln_elt.nextSibling.innerText;
var lines_info = lines_info_regexp.exec(ln_text);
if (lines_info) {
$(ln_elt).parent().addClass('swh-diff-lines-info');
} else if (ln_text.length > 0 && ln_text[0] == '-') {
$(ln_elt).parent().addClass('swh-diff-removed-line');
} else if (ln_text.length > 0 && ln_text[0] == '+') {
$(ln_elt).parent().addClass('swh-diff-added-line');
}
});
// set line numbers for unified diff
$('#' + diff_id + ' .hljs-ln-numbers').each(function(i, ln_elt) {
$(ln_elt).children().attr('data-line-number',
format_ln_diff(from_to_lines[i][0], from_to_lines[i][1],
max_number_chars));
});
// set line numbers for the from side-by-side diff
$('#' + diff_id + '-from .hljs-ln-numbers').each(function(i, ln_elt) {
$(ln_elt).children().attr('data-line-number',
format_ln_diff(from_lines[i], null,
max_number_chars));
});
// set line numbers for the to side-by-side diff
$('#' + diff_id + '-to .hljs-ln-numbers').each(function(i, ln_elt) {
$(ln_elt).children().attr('data-line-number',
format_ln_diff(null, to_lines[i],
max_number_chars));
});
// last processings:
// - remove the '+' and '-' at the beginning of the diff lines
// from code highlighting
// - add the "no new line at end of file marker" if needed
$('.' + diff_id + ' .hljs-ln-line').each(function(i, ln_elt) {
if (ln_elt.firstChild) {
if (ln_elt.firstChild.nodeName != "#text") {
var line_text = ln_elt.firstChild.innerHTML;
if (line_text[0] == '-' || line_text[0] == '+') {
ln_elt.firstChild.innerHTML = line_text.substr(1);
var new_text_node = document.createTextNode(line_text[0]);
$(ln_elt).prepend(new_text_node);
}
}
$(ln_elt).contents().filter(function() {
return this.nodeType === 3; //Node.TEXT_NODE
}).each(function(i, textNode) {
var swh_no_nl_marker = '[swh-no-nl-marker]';
if (textNode.textContent.indexOf(swh_no_nl_marker) != -1) {
textNode.textContent = textNode.textContent.replace(swh_no_nl_marker, '');
$(ln_elt).append($(no_nl_marker));
}
});
}
});
// remove empty last line added by highlight.js
$('#' + diff_id + ' tr:last').remove();
$('#' + diff_id + '-from tr:last').remove();
$('#' + diff_id + '-to tr:last').remove();
$('#' + diff_id + '-from tr:last').remove();
$('#' + diff_id + '-to tr:last').remove();
// hide the diff mode switch button in case of not generated diffs
if (data.diff_str.indexOf('Diffs are not generated for non textual content') != 0) {
$('#panel_' + diff_id + ' .diff-styles').css('visibility', 'visible');
}
}
// set the unified diff visible by default
$('#' + diff_id + '-loading').css('display', 'none');
$('#' + diff_id + '-highlightjs').css('display', 'block');
// update displayed counters
$('#swh-revision-lines-added').text(nb_additions + ' additions');
$('#swh-revision-lines-deleted').text(nb_deletions + ' deletions');
$('#swh-nb-diffs-computed').text(nb_diffs_computed);
// refresh the waypoints triggering diffs computation as
// the DOM layout has been updated
Waypoint.refreshAll();
}
});
}
// callback when the 'Changes' tab is activated
$(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) {
if (e.target.text == 'Changes') {
// iterate on list of file changes
{% for change in changes %}
// map diff id to diff computation url
diffs_urls['{{ change.id }}'] = '{{ change.diff_url }}';
// in order to not send too much diff computation requests
// (as the file changes list can be large),
// diffs computation will be requested on the fly
// as the view is scrolled
// create a waypoint that will trigger diff computation when
// the top of the diff panel hits the bottom of the viewport
$('#panel_{{ change.id }}').waypoint({
handler: function() {
if (is_in_viewport($('#panel_{{ change.id }}'))) {
compute_diff('{{ change.diff_url }}', '{{ change.id }}');
this.destroy();
}
},
offset: '100%'
});
// create a waypoint that will trigger diff computation when
// the bottom of the diff panel hits the top of the viewport
$('#panel_{{ change.id }}').waypoint({
handler: function() {
if (is_in_viewport($('#panel_{{ change.id }}'))) {
compute_diff('{{ change.diff_url }}', '{{ change.id }}');
this.destroy();
}
},
offset: function() {
return -$('#panel_{{ change.id }}').height();
}
});
{% endfor %}
// compute visible diffs when navigating to the 'Changes' tab
compute_visible_diffs();
$('#readme-panel').css('display', 'none');
} else if (e.target.text == 'Files') {
$('#readme-panel').css('display', 'block');
}
});
// to compute all visible diffs in the viewport
function compute_visible_diffs() {
$('.swh-file-diff-panel').each(function(i, elt) {
if (is_in_viewport(elt)) {
diff_id = elt.id.replace('panel_', '');
compute_diff(diffs_urls[diff_id], diff_id);
}
});
}
// callback when the user clicks on the 'Compute all diffs' button
function compute_all_diffs(event) {
$(event.target).addClass('active');
for (var diff_id in diffs_urls) {
if (diffs_urls.hasOwnProperty(diff_id)) {
compute_diff(diffs_urls[diff_id], diff_id);
}
}
event.stopPropagation();
}
$(document).ready(function() {
var changed_files_text = nb_changed_files + ' changed file';
if (nb_changed_files != 1) {
changed_files_text += 's';
}
$('#swh-revision-changed-files').text(changed_files_text);
+ {% if message_body|length > 0 %}
+ $('#swh-revision-message').addClass('in');
+ {% else %}
+ $('#swh-collapse-revision-message').attr('data-toggle', '');
+ {% endif %}
+
var $root = $('html, body');
// callback when the user requests to scroll on a specific diff or back to top
$('#swh-revision-changes-list a[href^="#"], #back-to-top a[href^="#"]').click(function() {
var href = $.attr(this, 'href');
// disable waypoints while scrolling as we do not want to
// launch computation of diffs the user is not interested in
// (file changes list can be large)
Waypoint.disableAll();
$root.animate(
{
scrollTop: $(href).offset().top
},
{
duration: 500,
complete: function () {
window.location.hash = href;
// enable waypoints back after scrolling
Waypoint.enableAll();
// compute diffs visible in the viewport
compute_visible_diffs();
}
});
return false;
});
});
</script>
{% endblock %}
{% block swh-browse-after-panels %}
{% include "includes/readme-display.html" %}
{% endblock %}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Jun 4 2025, 6:46 PM (14 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3277731
Attached To
rDWAPPS Web applications
Event Timeline
Log In to Comment