cSvn-UI for SVN Repositories

cGit-UI – is a web interface for Subversion (SVN) Repositories. cSvn CGI script is writen in C and therefore it's fast enough

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