~dupunkto/gitz

Awesome PHP-based Git frontend.

Refactor blob view

Commited on by Robin.

- Render markdown using Parsedown in blob view
- Render images properly by extending Parsedown with code for generating appropriate data: URLs
diff --git a/ext/sitdown.php b/ext/sitdown.php
new file mode 100644
index 0000000..63bfa3e
--- /dev/null
+++ b/ext/sitdown.php
@@ -0,0 +1,28 @@
+<?php
+
+class Sitdown extends Parsedown {
+  function __construct($repo, $hash, $base) {
+    $this->repo = $repo;
+    $this->hash = $hash;
+    $this->base = $base;
+  }
+
+  function inlineImage($excerpt) {
+      $image = parent::inlineImage($excerpt);
+
+      if (!isset($image)) return null;
+
+      $path = $image['element']['attributes']['src'];
+
+      if(!is_absolute($path)) {
+        $path = trim(path_join($this->base, $path), '/');
+        $blob = \core\getBlob($this->repo, $path, $this->hash);
+        $mime = \core\detectMimeType($this->repo, $path, $this->hash);
+
+        $image['element']['attributes']['src'] =
+          "data:{$mime};base64," . base64_encode($blob);
+      }
+
+      return $image;
+  }
+}
\ No newline at end of file
diff --git a/gui/blob.php b/gui/blob.php
index 7bd9fc6..d38ae26 100644
--- a/gui/blob.php
+++ b/gui/blob.php
@@ -20,28 +20,7 @@
 <?php
   $blob = \core\getBlob($repo, $request_path, $hash);
   $ext = pathinfo($request_path, PATHINFO_EXTENSION);
-  $mime = \core\getMimeType($repo, $request_path, $hash);
-  
-  // CodeMirror doesn't like text/x-shellscript :|
-  if($mime == 'text/x-shellscript') $mode = 'text/x-sh';
-
-  // If the file info is being useless, try to match using
-  // file extension instead.
-  else if($mime == 'text/plain') {
-    $mode = match($ext) {
-      'md' => 'text/x-markdown',
-      'json' => 'application/json',
-      'jsonld' => 'application/ld+json',
-      'ts' => 'application/typescript',
-      default => $ext
-    };
-
-    if(str_ends_with($ext, 'js')) $mode = 'text/javascript';
-    if(str_ends_with($ext, 'html')) $mode = 'text/html';
-  }
-
-  // For all other cases, let CodeMirror decide.
-  else $mode = $mime;
+  $mime = \core\detectMimeType($repo, $request_path, $hash);
 ?>
 
 <div class="container blob">
@@ -49,9 +28,21 @@
     <img src="data:<?= $mime ?>;base64,<?= base64_encode($blob) ?>">
   <?php elseif($mime == 'application/octet-stream'): ?>
     <p>Cannot render binary data.</p>
+  <?php elseif($ext == 'md'): ?>
+    <article class="readme">
+      <?php
+        $parser = new Sitdown($repo, $hash, path_parent($request_path));
+        echo $parser->text($blob);
+      ?>
+    </article>
   <?php else: ?>
     <pre class="code"><code><?= htmlspecialchars($blob) ?></code></pre>
 
+    <?php
+      // CodeMirror is not a fan of text/x-shellscript.
+      $mode = $mime == 'text/x-shellscript' ? 'text/x-sh' : $mime;
+    ?>
+
     <script>
       // Mime-Type: <?= $mime ?>
       // Extension: <?= $ext ?>
diff --git a/gui/raw.php b/gui/raw.php
new file mode 100644
index 0000000..e69de29
diff --git a/gui/summary.php b/gui/summary.php
index 5dc6208..db85d01 100644
--- a/gui/summary.php
+++ b/gui/summary.php
@@ -45,10 +45,12 @@
 <main class="container">
   <article class="readme">
     <?php
-      $markdown = \core\getREADME($repo);
-      $parser = new Parsedown();
+      $blob = \core\getREADME($repo);
+      $hash = \core\getLatestHash($repo, $branch);
 
-      echo $parser->text($markdown);
+      $parser = new Sitdown($repo, $hash, '/');
+
+      echo $parser->text($blob);
     ?>
   </article>
 </main>
\ No newline at end of file
diff --git a/index.php b/index.php
index a73fb1f..4e1dbc6 100644
--- a/index.php
+++ b/index.php
@@ -3,6 +3,7 @@
 
 require_once __DIR__ . "/src/core.php";
 require_once __DIR__ . '/vendor/autoload.php';
+require_once __DIR__ . "/ext/sitdown.php";
 
 $git = new CzProject\GitPhp\Git;
 
@@ -82,12 +83,8 @@ switch(true) {
         case route("@/tree/{$alnum}(.*)$@"):
           $page ??= "tree";
 
-          if(\core\isCommitHash($params[1])) {
-            $hash = $params[1];
-          } else {
-            $branch = $params[1];
-            $hash = \core\getLatestCommits($repo, $branch, 1)[0]['hash'];
-          }
+          if(\core\isCommitHash($params[1])) $hash = $params[1];
+          else $hash = \core\getLatestHash($repo, $params[1]);
 
           $request_path = trim($params[2], "/");
           break;
@@ -95,32 +92,11 @@ switch(true) {
         case route("@/blob/{$alnum}(.*)$@"):
           $page ??= "blob";
 
-          if(\core\isCommitHash($params[1])) {
-            $hash = $params[1];
-          } else {
-            $branch = $params[1];
-            $hash = \core\getLatestCommits($repo, $branch, 1)[0]['hash'];
-          }
+          if(\core\isCommitHash($params[1])) $hash = $params[1];
+          else $hash = \core\getLatestHash($repo, $params[1]);
 
           $request_path = trim($params[2], "/");
           break;
-
-        case route("@/raw/{$alnum}(.*)$@"):
-          if(\core\isCommitHash($params[1])) {
-            $hash = $params[1];
-          } else {
-            $branch = $params[1];
-            $hash = \core\getLatestCommits($repo, $branch, 1)[0]['hash'];
-          }
-
-          $request_path = trim($params[2], "/");
-
-          $blob = \core\getBlob($repo, $request_path, $hash);
-          $mime = \core\detectMimeType($repo, $request_path, $hash);
-
-          header("Content-Type: {$mime}");
-          echo $blob;
-          exit;
       }
 
       if(isset($page)) break;
diff --git a/src/core.php b/src/core.php
index e82cf91..7cad4c4 100644
--- a/src/core.php
+++ b/src/core.php
@@ -177,6 +177,10 @@ function lookupRemoteDomain($remote) {
   };
 }
 
+function getLatestHash($repo, $branch) {
+  return getLatestCommits($repo, $branch, 1)[0]['hash'];
+}
+
 function getDefaultBranch($repo) {
   return str_replace("refs/heads/", "", $repo->execute('symbolic-ref', 'HEAD')[0]);
 }
@@ -198,7 +202,7 @@ function getType($repo, $path, $hash) {
   return false;
 }
 
-function getMimeType($repo, $path, $hash) {
+function detectMimeType($repo, $path, $hash) {
   $finfo = new \finfo(FILEINFO_MIME_TYPE);
 
   [$line] = $repo->execute('ls-tree', $hash, $path);
diff --git a/src/utils.php b/src/utils.php
index 403ce53..a47520a 100644
--- a/src/utils.php
+++ b/src/utils.php
@@ -78,4 +78,10 @@ function has_tld($str) {
   $TLDs = [".nl", ".com", ".org", ".eu"];
   $matches = array_filter($TLDs, fn ($tld) => str_ends_with($str, $tld));
   return !empty($matches);
+}
+
+function is_absolute($url) {
+  return str_starts_with($url, "http://") 
+    || str_starts_with($url, "https://")
+    || str_starts_with($url, "//");
 }
\ No newline at end of file