cGit-UI for Git Repositories

cGit-UI – is a web interface for Git Repositories. cGit CGI script is writen in C and therefore it's fast enough

12 Commits   0 Branches   1 Tag
     5         kx 
     5         kx function get_query_parameter( name, url = window.location.href )
     5         kx {
     5         kx   name = name.replace( /[\[\]]/g, '\\$&' );
     5         kx   var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), results = regex.exec(url);
     5         kx   if( !results ) return null;
     5         kx   if( !results[2] ) return '';
     5         kx   return decodeURIComponent( results[2].replace(/\+/g, ' ') );
     5         kx }
     5         kx 
     5         kx function removeParam( query_string, param ) {
     5         kx   if( query_string !== "" )
     5         kx   {
     5         kx     var query = "";
     5         kx     var params = decodeURIComponent(query_string).split('&');
     5         kx     var i, name;
     5         kx     for( i = 0; i < params.length; ++i ) {
     5         kx       name = params[i].split('=');
     5         kx       if( name[0] !== param ) {
     5         kx         query = query + name[0] + '=' + name[1] + '&';
     5         kx       }
     5         kx     }
     5         kx     if( query !== "" ) {
     5         kx       query = query.substring( 0, query.length - 1 );
     5         kx     }
     5         kx   }
     5         kx   return query;
     5         kx }
     5         kx 
     5         kx function search() {
     5         kx 
     5         kx   var text = document.querySelector( '.search-form input' ).value;
     5         kx 
     5         kx   if( page_type === "repo" && text )
     5         kx   {
     5         kx     var path         = window.location.pathname;
     5         kx     var query_string = window.location.search;
     5         kx     var revision     = encodeURIComponent( text );
     5         kx 
     5         kx     if( query_string ) {
     5         kx       query_string = query_string.substring( 1, query_string.length );
     5         kx       query_string = removeParam( query_string, "rev" );
     5         kx       query_string = removeParam( query_string, "op" );
     5         kx     }
     5         kx 
     5         kx     revision = revision.toLowerCase();
     5         kx     if( revision === "head" ) {
     5         kx       revision = "0";
     5         kx     }
     5         kx 
     5         kx     document.querySelector( '.search-form input' ).value = "";
     5         kx 
     5         kx     window.location.pathname = path;
     5         kx     if( query_string ) {
     5         kx       window.location.search = "?rev=" + revision + "&" + query_string;
     5         kx     } else {
     5         kx       window.location.search = "?rev=" + revision;
     5         kx     }
     5         kx   }
     5         kx   if( page_type === "repolist" && text )
     5         kx   {
     5         kx     var path         = window.location.pathname;
     5         kx     var query_string = window.location.search;
     5         kx     var repo_path    = encodeURIComponent( text );
     5         kx 
     5         kx     if( query_string ) {
     5         kx       query_string = query_string.substring( 1, query_string.length );
     5         kx       query_string = removeParam( query_string, "search" );
     5         kx     }
     5         kx 
     5         kx     document.querySelector( '.search-form input' ).value = "";
     5         kx 
     5         kx     window.location.pathname = path;
     5         kx     if( query_string ) {
     5         kx       window.location.search = "?search=" + repo_path + "&" + query_string;
     5         kx     } else {
     5         kx       window.location.search = "?search=" + repo_path;
     5         kx     }
     5         kx   }
     5         kx }
     5         kx 
     5         kx function show_hide_direction() {
     5         kx   var direction = document.querySelector( '.direction' );
     5         kx   var prev = document.querySelector( '.prev-direction' );
     5         kx   var next = document.querySelector( '.next-direction' );
     5         kx   var ofs = get_query_parameter( 'ofs' );
     5         kx 
     5         kx   if( direction )
     5         kx   {
     5         kx     if( num_of_repos < page_size ) {
     5         kx       direction.style.display = 'none';
     5         kx     }
     5         kx     else {
     5         kx       direction.style.display = 'block';
     5         kx 
     5         kx       if( (num_of_repos - ofs) < page_size ) { next.style.display = 'none';  }
     5         kx       else                                   { next.style.display = 'block'; }
     5         kx 
     5         kx       if( ofs > 0 ) { prev.style.display = 'block'; }
     5         kx       else          { prev.style.display = 'none';  }
     5         kx     }
     5         kx   }
     5         kx }
     5         kx 
     5         kx /***************************************************************
     5         kx   We dont want to use tooltips from any foreign engine.
     5         kx   NOTE:
     5         kx     All tooltips we attached to the '.pusher' element.
     5         kx  */
     5         kx function fade_out( element ) {
     5         kx   /* постепенно исчезать */
     5         kx   var op = 1;  /* initial opacity */
     5         kx   var timer = setInterval( function() {
     5         kx     if( op <= 0.1 ) {
     5         kx       clearInterval( timer );
     5         kx       element.style.display = 'none';
     5         kx     }
     5         kx     element.style.opacity = op;
     5         kx     element.style.filter = 'alpha(opacity=' + op * 100 + ")";
     5         kx     op -= op * 0.1;
     5         kx   }, 10);
     5         kx }
     5         kx 
     5         kx function fade_in( element ) {
     5         kx   /* постепенно появляться */
     5         kx   var op = 0.1;  /* initial opacity */
     5         kx   element.style.display = 'block';
     5         kx   var timer = setInterval( function() {
     5         kx     if( op >= 1 ) {
     5         kx       clearInterval( timer );
     5         kx     }
     5         kx     element.style.opacity = op;
     5         kx     element.style.filter = 'alpha(opacity=' + op * 100 + ")";
     5         kx     op += op * 0.1;
     5         kx   }, 10);
     5         kx }
     5         kx 
     5         kx function simple_tooltip( target_items, name ) {
     5         kx   var pusher = document.querySelector( '.pusher' );
     5         kx   var items = document.querySelectorAll( target_items );
     5         kx 
     5         kx   items.forEach( function( item, i, array ) {
     5         kx     var html = "<div class='" + name +
     5         kx                "' id='" + name + "-" + i +
     5         kx                "'><p>" + item.getAttribute('title') +
     5         kx                "</p></div>";
     5         kx     pusher.insertAdjacentHTML( 'beforeend', html );
     5         kx 
     5         kx     var tooltip = document.querySelector( "#" + name + "-" + i );
     5         kx 
     5         kx     item.removeAttribute( 'title' );
     5         kx     item.addEventListener( "mouseover", function( event ) {
     5         kx       fade_in( tooltip );
     5         kx     });
     5         kx     item.addEventListener( "mousemove", function( kmouse ) {
     5         kx       /***********************************************
     5         kx          c - client is a browser window;
     5         kx          o - offset from page (document) coordinate.
     5         kx          t - tooltip;
     5         kx        ***********************************************/
     5         kx       var cW  = window.innerWidth;
     5         kx       var cH  = window.innerHeight;
     5         kx       var cX  = kmouse.clientX;
     5         kx       var cY  = kmouse.clientY;
     5         kx       var tW  = tooltip.offsetWidth;
     5         kx       var tH  = tooltip.offsetHeight;
     5         kx       var oX;
     5         kx       var oY;
     5         kx       if( ( cW - cX ) < ( tW + 15) ) { oX = - 15 - tW; } else { oX = 15; }
     5         kx       if( ( cH - cY ) < ( tH + 15) ) { oY = - 15 - tH; } else { oY = 15; }
     5         kx       tooltip.style.left = kmouse.pageX + oX + 'px';
     5         kx       tooltip.style.top  = kmouse.pageY + oY - pusher.offsetTop + 'px';
     5         kx     });
     5         kx     item.addEventListener( "mouseout", function( event ) {
     5         kx       fade_out( tooltip );
     5         kx     });
     5         kx   });
     5         kx }
     5         kx 
     5         kx /*******************************************
     5         kx   Truncate descriptions or commit messages:
     5         kx  */
     5         kx function trunc(el) {
     5         kx   if( el.classList.contains('trunc') )
     5         kx   {
     5         kx     el.classList.remove('trunc');
     5         kx   }
     5         kx   else
     5         kx   {
     5         kx     el.classList.add('trunc');
     5         kx   }
     5         kx }
     5         kx 
     5         kx /*****************************
     5         kx   Show/Hide right popup menu:
     5         kx  */
     5         kx function show_sidebar(event) {
     5         kx   var sidebar = document.querySelector('.cgit-popup-menu-bars');
     5         kx   sidebar.classList.add("visible");
     5         kx 
     5         kx   /* change icon bars->times */
     5         kx   var icon = document.querySelector('.cgit-main-menu-bars .las');
     5         kx   icon.classList.remove("la-bars");
     5         kx   icon.classList.add("la-times");
     5         kx 
     5         kx   var sb = document.querySelector('.cgit-main-menu-bars');
     5         kx   sb.onclick = hide_sidebar;
     5         kx 
     5         kx   if( !event )
     5         kx     event = window.event;
     5         kx   event.stopPropagation();
     5         kx }
     5         kx 
     5         kx function hide_sidebar(event) {
     5         kx   var sidebar = document.querySelector('.cgit-popup-menu-bars');
     5         kx   sidebar.classList.remove("visible");
     5         kx 
     5         kx   /* change icon times->bars */
     5         kx   var icon = document.querySelector('.cgit-main-menu-bars .las');
     5         kx   icon.classList.remove("la-times");
     5         kx   icon.classList.add("la-bars");
     5         kx 
     5         kx   var sb = document.querySelector('.cgit-main-menu-bars');
     5         kx   sb.onclick = show_sidebar;
     5         kx 
     5         kx   if( !event )
     5         kx     event = window.event;
     5         kx   event.stopPropagation();
     5         kx }
     5         kx 
     5         kx /********************
     5         kx   on Document Ready:
     5         kx  */
     5         kx document.addEventListener('DOMContentLoaded', function() {
     5         kx 
     5         kx   /* initialy show main popup menu on click */
     5         kx   var sb = document.querySelector('.cgit-main-menu-bars');
     5         kx   sb.onclick = show_sidebar;
     5         kx 
     5         kx   var items = document.querySelectorAll('.cgit-popup-menu-bars > .item');
     5         kx   items.forEach( function(item) {
     5         kx     /* each item should hide main popup menu */
     5         kx     item.onclick = hide_sidebar;
     5         kx   });
     5         kx 
     5         kx   window.addEventListener('resize', function(event) {
     5         kx     var width = window.innerWidth;
     5         kx     if( width > 768 ) {
     5         kx       /* change icon times->bars */
     5         kx       var icon = document.querySelector('.cgit-main-menu-bars .las');
     5         kx       icon.classList.remove("la-times");
     5         kx       icon.classList.add("la-bars");
     5         kx 
     5         kx       /* hide main popup menu */
     5         kx       var sidebar = document.querySelector('.cgit-popup-menu-bars');
     5         kx       sidebar.classList.remove("visible");
     5         kx     }
     5         kx     else {
     5         kx       /* show main popup menu on click after resize */
     5         kx       var sb = document.querySelector('.cgit-main-menu-bars');
     5         kx       sb.onclick = show_sidebar;
     5         kx     }
     5         kx   });
     5         kx 
     5         kx 
     5         kx   /*************************************************
     5         kx     Skip line numbering in the Markdown content:
     5         kx    */
     5         kx   var mdcode = document.querySelectorAll('.markdown-content code');
     5         kx   mdcode.forEach( function( block ) {
     5         kx     block.classList.add('nohljsln');
     5         kx   });
     5         kx 
     5         kx   /*************************************************
     5         kx     Skip line numbering in the Blame content:
     5         kx    */
     5         kx   var blame = document.querySelectorAll('.blame code');
     5         kx   blame.forEach( function( block ) {
     5         kx     block.classList.add('nohljsln');
     5         kx   });
     5         kx 
     5         kx   /*************************************************
     5         kx     Initialize highlight.js with hljs line numbers:
     5         kx    */
     5         kx   hljs.configure({
     5         kx     useBR: false,
     5         kx     /* languages: 'Makefile Bash C Perl',*/
     5         kx     tabReplace: '<span class="tab">&lt;------&gt;</span>'
     5         kx   });
     5         kx 
     5         kx   var preformated = document.querySelectorAll('pre code');
     5         kx   preformated.forEach( function( block ) {
     5         kx     hljs.highlightBlock( block ); /* init hljs */
     5         kx     if( false === block.classList.contains('nohljsln') )
     5         kx     {
     5         kx       hljs.lineNumbersBlock( block, { /* init hljs line numbers with options: */
     5         kx         startFrom: 0,
     5         kx         singleLine: false
     5         kx       });
     5         kx     }
     5         kx   });
     5         kx 
     5         kx 
     5         kx   /***************************************************************
     5         kx     Pseudo paragraphs inserted before headers to skip the stiky
     5         kx     Main Menu Bar height when we going to anchor in a Markdown
     5         kx     document.
     5         kx    */
     5         kx   var mdheaders = document.querySelectorAll('.markdown-content h1,h2,h3,h4,h5,h6');
     5         kx   mdheaders.forEach( function( header ) {
     5         kx     var content = header.textContent;
     5         kx     var id = content.toLowerCase().replaceAll( ' ', '-' ).replaceAll( ':', '' );
     5         kx 
     5         kx     var ph = document.createElement( 'p' );
     5         kx     ph.setAttribute( 'class', 'headers-anchor' )
     5         kx     ph.setAttribute( 'id', id );
     5         kx     header.parentNode.insertBefore( ph, header );
     5         kx   });
     5         kx 
     5         kx   var input = document.querySelector( '.search-form input' );
     5         kx   input.addEventListener( "keyup", function( event ) {
     5         kx     if( event.key === "Enter" ) {
     5         kx       search();
     5         kx     }
     5         kx   });
     5         kx 
     5         kx   simple_tooltip( "[title]", "tooltip" );
     5         kx   show_hide_direction();
     5         kx });