@(branch: String,
repository: gitbucket.core.service.RepositoryService.RepositoryInfo,
pathList: List[String],
content: gitbucket.core.util.JGitUtil.ContentInfo,
latestCommit: gitbucket.core.util.JGitUtil.CommitInfo,
hasWritePermission: Boolean,
isBlame: Boolean)(implicit context: gitbucket.core.controller.Context)
@import gitbucket.core.view.helpers
@gitbucket.core.html.main(s"${(repository.name :: pathList).mkString("/")} at ${helpers.encodeRefName(branch)} - ${repository.owner}/${repository.name}", Some(repository)) {
@gitbucket.core.html.menu("files", repository){
<div class="head">
<div class="pull-right hide-if-blame"><div class="btn-group">
<a href="@helpers.url(repository)/find/@helpers.encodeRefName(branch)" class="btn btn-sm btn-default" data-hotkey="t">Find file</a>
</div></div>
<div class="line-age-legend">
<span>Newer</span>
<ol>
<li class="heat1"></li>
<li class="heat2"></li>
<li class="heat3"></li>
<li class="heat4"></li>
<li class="heat5"></li>
<li class="heat6"></li>
<li class="heat7"></li>
<li class="heat8"></li>
<li class="heat9"></li>
<li class="heat10"></li>
</ol>
<span>Older</span>
</div>
@gitbucket.core.helper.html.branchcontrol(
branch,
repository,
hasWritePermission
){
@repository.branchList.map { x =>
<li><a href="@helpers.url(repository)/blob/@helpers.encodeRefName(x)/@pathList.mkString("/")">@gitbucket.core.helper.html.checkicon(x == branch) @x</a></li>
}
}
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)">@repository.name</a> /
@pathList.zipWithIndex.map { case (section, i) =>
@if(i == pathList.length - 1){
@section
} else {
<a href="@helpers.url(repository)/tree/@helpers.encodeRefName(branch)/@pathList.take(i + 1).mkString("/")">@section</a> /
}
}
</div>
<div class="box-header">
@helpers.avatar(latestCommit, 28)
@helpers.user(latestCommit.authorName, latestCommit.authorEmailAddress, "username strong")
<span class="muted">@gitbucket.core.helper.html.datetimeago(latestCommit.commitTime)</span>
<a href="@helpers.url(repository)/commit/@latestCommit.id" class="commit-message">@helpers.link(latestCommit.summary, repository)</a>
<div class="btn-group pull-right">
@if(hasWritePermission && content.viewType == "text" && repository.branchList.contains(branch)){
<a class="btn btn-sm btn-default" href="@helpers.url(repository)/edit/@helpers.encodeRefName(branch)/@pathList.mkString("/")">Edit</a>
}
<a class="btn btn-sm btn-default" href="@helpers.url(repository)/raw/@latestCommit.id/@pathList.mkString("/")">Raw</a>
@if(content.viewType == "text"){
<a class="btn btn-sm btn-default blame-action" href="@helpers.url(repository)/blame/@latestCommit.id/@pathList.mkString("/")" data-url="@helpers.url(repository)/get-blame/@latestCommit.id/@pathList.mkString("/")" data-repository="@helpers.url(repository)">Blame</a>
}
<a class="btn btn-sm btn-default" href="@helpers.url(repository)/commits/@helpers.encodeRefName(branch)/@pathList.mkString("/")">History</a>
@if(hasWritePermission && repository.branchList.contains(branch)){
<a class="btn btn-sm btn-danger" href="@helpers.url(repository)/remove/@helpers.encodeRefName(branch)/@pathList.mkString("/")">Delete</a>
}
</div>
</div>
@if(content.viewType == "text"){
@defining(helpers.isRenderable(pathList.reverse.head)){ isRenderable =>
@if(!isBlame && isRenderable) {
<div class="box-content-bottom markdown-body" style="padding-left: 20px; padding-right: 20px;">
@helpers.renderMarkup(pathList, content.content.get, branch, repository, false, false, true)
</div>
} else {
<div class="box-content-bottom">
<pre class="prettyprint linenums blob @if(!isRenderable){ no-renderable } ">@content.content.get</pre>
</div>
}
}
}
@if(content.viewType == "image"){
<div class="box-content-bottom">
<img src="@helpers.url(repository)/raw/@helpers.encodeRefName(branch)/@pathList.mkString("/")"/>
</div>
}
@if(content.viewType == "large" || content.viewType == "binary"){
<div class="box-content-bottom" style="text-align: center; padding-top: 20px; padding-bottom: 20px;">
<a href="@helpers.url(repository)/raw/@helpers.encodeRefName(branch)/@pathList.mkString("/")">View Raw</a><br>
<br>
(Sorry about that, but we can't show files that are this big right now)
</div>
}
}
}
<script src="@helpers.assets/vendors/jquery/jquery.ba-hashchange.js"></script>
<script>
$(window).load(function(){
$(window).hashchange(function(){
updateHighlighting();
}).hashchange();
var pre = $('pre.prettyprint');
function updateSourceLineNum(){
$('.source-line-num').remove();
var pos = pre.find('ol.linenums').position();
if(pos){
$('<div class="source-line-num">').css({
height : pre.height(),
width : '48px',
cursor : 'pointer',
position: 'absolute',
top : pos.top + 'px',
left : pos.left + 'px'
}).click(function(e){
$(window).hashchange(function(){})
var pos = $(this).data("pos");
if(!pos){
pos = $('ol.linenums li').map(function(){ return { id: $(this).attr("id"), top: $(this).position().top} }).toArray();
$(this).data("pos",pos);
}
for(var i = 0; i < pos.length-1; i++){
if(pos[i + 1].top > e.pageY){
break;
}
}
var line = pos[i].id.replace(/^L/,'');
var hash = location.hash;
if(e.shiftKey == true && hash.match(/#L\d+(-L\d+)?/)){
var lines = hash.split('-');
location.hash = lines[0] + '-L' + line;
} else {
var p = $("#L"+line).attr('id',"");
location.hash = '#L' + line;
p.attr('id','L'+line);
}
}).appendTo(pre);
}
}
var repository = $('.blame-action').data('repository');
$('.blame-action').click(function(e){
if(history.pushState && $('pre.prettyprint.no-renderable').length){
e.preventDefault();
history.pushState(null, null, this.href);
updateBlame();
}
});
function updateBlame(){
var m = /\/(blame|blob)(\/.*)$/.exec(location.href);
var mode = m[1];
$('.blame-action').toggleClass("active", mode=='blame').attr('href', repository + (m[1] == 'blame' ? '/blob' : '/blame') + m[2]);
if(pre.parents("div.box-content-bottom").find(".blame").length){
pre.parents("div.container").toggleClass("blame-container", mode == 'blame');
updateSourceLineNum();
return;
}
if(mode=='blob'){
updateSourceLineNum();
return;
}
$(document.body).toggleClass('no-box-shadow', document.body.style.boxShadow===undefined);
$('.blame-action').addClass("active");
var base = $('<div class="blame">').css({height: pre.height()}).prependTo(pre.parents("div.box-content-bottom"));
base.parents("div.container").addClass("blame-container");
updateSourceLineNum();
$.get($('.blame-action').data('url')).done(function(data){
var blame = data.blame;
var index = [];
for(var i = 0; i < blame.length; i++){
for(var j = 0; j < blame[i].lines.length; j++){
index[blame[i].lines[j]] = blame[i];
}
}
var blame, lastDiv, now = new Date().getTime();
$('pre.prettyprint ol.linenums li').each(function(i, e){
var p = $(e).position();
var h = $(e).height();
if(blame == index[i]){
lastDiv.css("min-height",(p.top + h + 1) - lastDiv.position().top);
}else{
$(e).addClass('blame-sep')
blame = index[i];
var sha = $('<div class="blame-sha">')
.append($('<a>').attr("href", data.root + '/commit/' + blame.id).text(blame.id.substr(0,7)));
if(blame.prev){
sha.append($('<br />'))
.append($('<a class="muted-link">').text('prev').attr("href", data.root + '/blame/' + blame.prev + '/' + (blame.prevPath || data.path)));
}
lastDiv = $('<div class="blame-info">')
.addClass('heat' + Math.min(10, Math.max(1, Math.ceil((now - blame.commited) / (24 * 3600 * 1000 * 70)))))
.toggleClass('blame-last', blame.id == data.last)
.data('line', (i + 1))
.css({
"top" : p.top + 'px',
"min-height" : h + 'px'
})
.append(sha)
.append($(blame.avatar).addClass('avatar').css({"float": "left"}))
.append($('<div class="blame-commit-title">').text(blame.message))
.append($('<div class="muted">').html(blame.author + " authed " + blame.authed))
.appendTo(base);
}
});
});
return false;
};
updateBlame();
});
var scrolling = false;
/**
* Hightlight lines which are specified by URL hash.
*/
function updateHighlighting(){
var hash = location.hash;
if(hash.match(/#L\d+(-L\d+)?/)){
$('li.highlight').removeClass('highlight');
var lines = hash.substr(1).split('-');
if(lines.length == 1){
$('#' + lines[0]).addClass('highlight');
if(!scrolling){
$(window).scrollTop($('#' + lines[0]).offset().top - 40);
}
} else if(lines.length > 1){
var start = parseInt(lines[0].substr(1));
var end = parseInt(lines[1].substr(1));
for(var i = start; i <= end; i++){
$('#L' + i).addClass('highlight');
}
if(!scrolling){
$(window).scrollTop($('#L' + start).offset().top - 40);
}
}
scrolling = true;
}
}
</script>