Commit 2dc512c

mo khan <mo@mokhan.ca>
2026-01-31 06:06:35
refactor: format html templates
1 parent b446157
internal/templates/blob.gohtml
@@ -1,5 +1,5 @@
 {{- /*gotype: mokhan.ca/antonmedv/gitmal/pkg/templates.BlobParams */ -}}
-{{ define "head" }}
+{{- define "head" -}}
 <style>
   [id] {
     scroll-margin-top: var(--header-height);
@@ -48,16 +48,15 @@
     height: auto;
   }
 </style>
-{{ end }}
-
-{{ define "body" }}
-  {{ template "header" . }}
-  {{ if .IsImage }}
-    <div class="image border">{{.Content}}</div>
-  {{ else if .IsBinary}}
-    <div class="binary-file border">Binary file</div>
-  {{ else }}
-    {{ .Content }}
-  {{ end }}
-{{ end }}
+{{- end}}
 
+{{- define "body" -}}
+{{- template "header" .}}
+{{- if .IsImage}}
+<div class="image border">{{.Content}}</div>
+{{- else if .IsBinary}}
+<div class="binary-file border">Binary file</div>
+{{- else}}
+{{.Content}}
+{{- end}}
+{{- end}}
internal/templates/branches.gohtml
@@ -1,5 +1,5 @@
 {{- /*gotype: mokhan.ca/antonmedv/gitmal/pkg/templates.BranchesParams*/ -}}
-{{ define "head" }}
+{{- define "head" -}}
 <style>
   .branches {
     border: 1px solid var(--c-border);
@@ -33,21 +33,23 @@
     border-radius: 999px;
   }
 </style>
-{{ end }}
+{{- end}}
 
-{{ define "body" }}
-  <h1>Branches</h1>
-  <div class="branches">
-    {{ if .Branches }}
-      {{ range .Branches }}
-        <div class="branch-row">
-          <a href="{{ .Href }}">{{ .Name }}</a>
-          {{ if .IsDefault }}<span class="badge">default</span>{{ end }}
-          <a href="{{ .CommitsHref }}" style="margin-left:auto; font-size:13px; color: var(--c-text-2)">commits →</a>
-        </div>
-      {{ end }}
-    {{ else }}
-      <div class="branch-row">(no branches)</div>
-    {{ end }}
+{{- define "body" -}}
+<h1>Branches</h1>
+<div class="branches">
+{{- if .Branches}}
+{{- range .Branches}}
+  <div class="branch-row">
+    <a href="{{.Href}}">{{.Name}}</a>
+{{- if .IsDefault}}
+    <span class="badge">default</span>
+{{- end}}
+    <a href="{{.CommitsHref}}" style="margin-left:auto; font-size:13px; color: var(--c-text-2)">commits →</a>
   </div>
-{{ end }}
+{{- end}}
+{{- else}}
+  <div class="branch-row">(no branches)</div>
+{{- end}}
+</div>
+{{- end}}
internal/templates/commit.gohtml
@@ -1,5 +1,5 @@
 {{- /*gotype: mokhan.ca/antonmedv/gitmal/pkg/templates.CommitParams*/ -}}
-{{ define "head" }}
+{{- define "head" -}}
 <style>
   h1 code {
     border-radius: var(--border-radius);
@@ -8,46 +8,39 @@
     font-family: var(--font-family-mono), monospace;
     font-weight: 500;
   }
-
   .commit {
     display: flex;
     flex-direction: column;
     gap: 16px;
     margin-bottom: 16px;
   }
-
   .commit-info {
     display: flex;
     flex-direction: row;
     gap: 8px;
     align-items: flex-end;
   }
-
   .commit-author {
     color: var(--c-text-1);
     font-weight: 600;
     min-width: 0;
     overflow-wrap: break-word;
   }
-
   .commit-date {
     color: var(--c-text-2);
     font-size: 12px;
     font-family: var(--font-family-mono), monospace;
   }
-
   .commit-message {
     border: 1px solid var(--c-border);
     border-radius: var(--border-radius);
     padding: 16px;
   }
-
   .ref-badges {
     display: inline-flex;
     gap: 6px;
     margin-left: 8px;
   }
-
   .badge {
     font-size: 12px;
     color: var(--c-text-2);
@@ -56,56 +49,47 @@
     border-radius: 999px;
     white-space: nowrap;
   }
-
   .commit-subject {
     font-size: 16px;
     font-weight: 600;
     line-height: 1.3;
     hyphens: auto;
   }
-
   .commit-body {
     margin-top: 16px;
     white-space: pre-wrap;
     line-height: 1.5;
     hyphens: auto;
   }
-
   .commit-subinfo {
     display: flex;
     flex-direction: row;
     gap: 16px;
     justify-content: space-between;
   }
-
   .commit-layout {
     display: grid;
     grid-template-columns: 1fr;
     gap: 16px;
   }
-
   @media (min-width: 960px) {
     .commit-layout {
       grid-template-columns: 300px 1fr;
       align-items: start;
     }
-
     .files-tree {
       position: sticky;
       top: 16px;
     }
-
     .files-tree-content {
       max-height: calc(100vh - var(--header-height) - 40px);
       overflow: auto;
     }
   }
-
   .files-tree {
     border: 1px solid var(--c-border);
     border-radius: var(--border-radius);
   }
-
   .files-tree-header {
     display: flex;
     flex-direction: row;
@@ -119,69 +103,54 @@
     font-size: 14px;
     font-weight: 600;
   }
-
   .files-tree-content {
     display: block;
     padding-block: 6px;
   }
-
   .tree .children {
     margin-left: 16px;
     border-left: 1px dashed var(--c-border);
   }
-
   .tree .node {
     display: flex;
     align-items: center;
     gap: 8px;
     padding: 10px 16px;
   }
-
   .tree .file-name {
     flex: 1;
     font-weight: 500;
     color: var(--c-text-1);
     cursor: pointer;
   }
-
   .tree .file-name:hover {
     color: var(--c-brand-2);
     text-decoration: underline;
   }
-
   .tree .dir {
     color: var(--c-dir);
   }
-
   .tree .file-added {
     color: var(--c-green);
   }
-
   .tree .file-deleted {
     color: var(--c-red);
   }
-
   .tree .file-renamed {
     color: var(--c-yellow);
   }
-
-  /* Per-file sections */
-
   .files {
     min-width: 0;
   }
-
   .file-section + .file-section {
     margin-top: 16px;
   }
-
   pre {
     border: 1px solid var(--c-border);
     border-top: none;
     border-bottom-left-radius: var(--border-radius);
     border-bottom-right-radius: var(--border-radius);
   }
-
   pre {
     margin: 0;
     padding: 8px 16px;
@@ -193,7 +162,6 @@
     tab-size: 4;
     font-family: var(--font-family-mono), monospace;
   }
-
   pre > code {
     display: block;
     padding: 0 16px;
@@ -202,12 +170,10 @@
     line-height: var(--code-line-height);
     font-size: var(--code-font-size);
   }
-
   .binary-file {
     padding: 8px 16px;
     font-style: italic;
   }
-
   .border {
     border: 1px solid var(--c-border);
     border-top: none;
@@ -215,90 +181,87 @@
     border-bottom-right-radius: 6px;
   }
 </style>
-{{ end }}
-
-{{ define "body" }}
-    <h1>Commit <code>{{ .Commit.ShortHash }}</code></h1>
-
-    <div class="commit">
-        <div class="commit-info">
-            <div class="commit-author">{{ .Commit.Author }} &lt;{{ .Commit.Email }}&gt;</div>
-            <div class="commit-date">{{ .Commit.Date | FormatDate }}</div>
-        </div>
-        <div class="commit-message">
-            <div class="commit-subject">
-                {{ .Commit.Subject }}
-                {{ if .Commit.RefNames }}
-                    <span class="ref-badges">
-                        {{ range .Commit.RefNames }}
-                            {{ if or (eq .Kind "Branch") (eq .Kind "Tag") }}
-                                <span class="badge">{{ if eq .Kind "Tag" }}tag: {{ end }}{{ .Name }}</span>
-                            {{ end }}
-                        {{ end }}
-                    </span>
-                {{ end }}
-            </div>
-            {{ if .Commit.Body }}
-                <div class="commit-body">{{ .Commit.Body }}</div>
-            {{ end }}
-        </div>
-        <div class="commit-subinfo">
-            <div class="commit-branch">
-                {{ if .Commit.Branch }}
-                    <a href="../commits/{{ .Commit.Branch.DirName }}/index.html" class="badge">{{ .Commit.Branch }}</a>
-                {{ end }}
-            </div>
-            {{ if .Commit.Parents }}
-                <div class="commit-parents">
-                    {{ if eq (len .Commit.Parents)  1 }}
-                        1 parent
-                    {{ else }}
-                        {{ .Commit.Parents | len }} parents
-                    {{ end }}
-                    {{ range $i, $p := .Commit.Parents }}
-                        {{ if gt $i 0 }}, {{ end }}
-                        <a href="{{ $p }}.html"><code>{{ $p | ShortHash }}</code></a>
-                    {{ end }}
-                </div>
-            {{ end }}
-        </div>
+{{- end}}
+
+{{- define "body" -}}
+<h1>Commit <code>{{.Commit.ShortHash}}</code></h1>
+<div class="commit">
+  <div class="commit-info">
+    <div class="commit-author">{{.Commit.Author}} &lt;{{.Commit.Email}}&gt;</div>
+    <div class="commit-date">{{.Commit.Date | FormatDate}}</div>
+  </div>
+  <div class="commit-message">
+    <div class="commit-subject">
+      {{.Commit.Subject}}
+{{- if .Commit.RefNames}}
+      <span class="ref-badges">
+{{- range .Commit.RefNames}}
+{{- if or (eq .Kind "Branch") (eq .Kind "Tag")}}
+        <span class="badge">{{if eq .Kind "Tag"}}tag: {{end}}{{.Name}}</span>
+{{- end}}
+{{- end}}
+      </span>
+{{- end}}
     </div>
-
-    <div class="commit-layout">
-        <div class="files-tree">
-            <div class="files-tree-header">Changed files ({{ len .FileViews }})</div>
-            <div class="files-tree-content">
-                {{ if .FileTree }}
-                    <div class="tree">
-                        {{ template "file_tree" (FileTreeParams .FileTree) }}
-                    </div>
-                {{ else }}
-                    <div style="color: var(--c-text-3)">(no files)</div>
-                {{ end }}
-            </div>
-        </div>
-
-        <div class="files">
-            {{ range .FileViews }}
-                <section id="{{ .Path }}" class="file-section">
-                    <header class="file-header">
-                        {{ if .IsRename }}
-                            <div class="path">{{ .OldName }} → {{ .NewName }}</div>
-                        {{ else }}
-                            <div class="path">{{ .Path }}</div>
-                        {{ end }}
-                    </header>
-                    {{ if .IsBinary }}
-                        <div class="binary-file border">Binary file</div>
-                    {{ else if (and .IsRename (not .HasChanges)) }}
-                        <div class="binary-file border">File renamed without changes</div>
-                    {{ else }}
-                        <div class="file-diff">
-                            {{ .HTML }}
-                        </div>
-                    {{ end }}
-                </section>
-            {{ end }}
-        </div>
+{{- if .Commit.Body}}
+    <div class="commit-body">{{.Commit.Body}}</div>
+{{- end}}
+  </div>
+  <div class="commit-subinfo">
+    <div class="commit-branch">
+{{- if .Commit.Branch}}
+      <a href="../commits/{{.Commit.Branch.DirName}}/index.html" class="badge">{{.Commit.Branch}}</a>
+{{- end}}
+    </div>
+{{- if .Commit.Parents}}
+    <div class="commit-parents">
+{{- if eq (len .Commit.Parents) 1}}
+      1 parent
+{{- else}}
+      {{.Commit.Parents | len}} parents
+{{- end}}
+{{- range $i, $p := .Commit.Parents}}
+{{- if gt $i 0}}, {{end}}
+      <a href="{{$p}}.html"><code>{{$p | ShortHash}}</code></a>
+{{- end}}
+    </div>
+{{- end}}
+  </div>
+</div>
+<div class="commit-layout">
+  <div class="files-tree">
+    <div class="files-tree-header">Changed files ({{len .FileViews}})</div>
+    <div class="files-tree-content">
+{{- if .FileTree}}
+      <div class="tree">
+{{- template "file_tree" (FileTreeParams .FileTree)}}
+      </div>
+{{- else}}
+      <div style="color: var(--c-text-3)">(no files)</div>
+{{- end}}
     </div>
-{{ end }}
+  </div>
+  <div class="files">
+{{- range .FileViews}}
+    <section id="{{.Path}}" class="file-section">
+      <header class="file-header">
+{{- if .IsRename}}
+        <div class="path">{{.OldName}} → {{.NewName}}</div>
+{{- else}}
+        <div class="path">{{.Path}}</div>
+{{- end}}
+      </header>
+{{- if .IsBinary}}
+      <div class="binary-file border">Binary file</div>
+{{- else if (and .IsRename (not .HasChanges))}}
+      <div class="binary-file border">File renamed without changes</div>
+{{- else}}
+      <div class="file-diff">
+{{.HTML}}
+      </div>
+{{- end}}
+    </section>
+{{- end}}
+  </div>
+</div>
+{{- end}}
internal/templates/commits_list.gohtml
@@ -1,203 +1,176 @@
 {{- /*gotype: mokhan.ca/antonmedv/gitmal/pkg/templates.CommitsListParams*/ -}}
-{{ define "head" }}
-    <style>
-      .commits {
-        border: 1px solid var(--c-border);
-        border-top: none;
-        border-bottom-left-radius: var(--border-radius);
-        border-bottom-right-radius: var(--border-radius);
-        overflow-x: auto;
-      }
-
-      .row {
-        display: flex;
-        height: 40px;
-        border-bottom: 1px solid var(--c-border);
-        padding-inline: 16px;
-        gap: 16px;
-      }
-
-      .row:last-child {
-        border-bottom: none;
-      }
-
-      .row:hover {
-        background-color: var(--c-bg-alt);
-      }
-
-      .cell {
-        display: flex;
-        gap: 8px;
-        align-items: center;
-      }
-
-      .hash a {
-        font-family: var(--font-family-mono), monospace;
-        color: var(--c-text-2);
-      }
-
-      .commit-title {
-        flex: 1;
-      }
-
-      .commit-title a {
-        color: var(--c-text-1);
-        line-height: 1.5;
-      }
-
-      .commit-title a:hover {
-        color: var(--c-brand-2);
-      }
-
-      .ref-badges {
-        display: inline-flex;
-        gap: 6px;
-        margin-left: 8px;
-      }
-
-      .badge {
-        font-size: 12px;
-        color: var(--c-text-2);
-        border: 1px solid var(--c-border);
-        padding: 2px 6px;
-        border-radius: 999px;
-        white-space: nowrap;
-      }
-
-      .date {
-        font-family: var(--font-family-mono), monospace;
-        font-size: 12px;
-        color: var(--c-text-2);
-      }
-
-      .pagination {
-        display: flex;
-        gap: 8px;
-        align-items: center;
-        justify-content: center;
-        margin-top: 12px;
-        padding: 8px 0;
-        color: var(--c-text-2);
-      }
-
-      .pagination a,
-      .pagination span.btn {
-        display: inline-flex;
-        align-items: center;
-        gap: 6px;
-        padding: 6px 10px;
-        border: 1px solid var(--c-border);
-        border-radius: 6px;
-        background: var(--c-bg-elv);
-        color: var(--c-text-1);
-        text-decoration: none;
-        font-size: 13px;
-      }
-
-      .pagination a:hover {
-        color: var(--c-brand-2);
-        border-color: var(--c-brand-2);
-      }
-
-      .pagination .disabled {
-        opacity: 0.5;
-        pointer-events: none;
-      }
-
-      .pagination .page-indicator {
-        margin: 0 4px;
-        font-size: 13px;
-        color: var(--c-text-2);
-      }
-
-      /* Mobile optimizations */
-      @media (max-width: 767px) {
-        .row {
-          height: auto;
-          padding: 10px 12px;
-          gap: 12px;
-          flex-wrap: wrap;
-          align-items: flex-start;
-        }
-
-        .commit-title {
-          flex-basis: 100%;
-          order: 1;
-        }
-
-        .author, .date, .hash {
-          font-size: 12px;
-        }
-
-        .author {
-          color: var(--c-text-2);
-          order: 2;
-        }
-
-        .date {
-          order: 2;
-        }
-
-        .hash {
-          margin-left: auto;
-          order: 3;
-        }
-      }
-    </style>
-{{ end }}
-
-{{ define "body" }}
-    {{ template "header" . }}
-    <div class="commits">
-        {{ range .Commits }}
-            <div class="row">
-                <div class="cell hash">
-                    <a href="{{ .Href }}">{{ .ShortHash }}</a>
-                </div>
-                <div class="cell commit-title">
-                  <a href="{{ .Href }}">{{ .Subject }}</a>
-                  {{ if .RefNames }}
-                  <div class="ref-badges">
-                    {{ range .RefNames }}
-                      {{ if or (eq .Kind "Branch") (eq .Kind "Tag") }}
-                        <span class="badge">{{ if eq .Kind "Tag" }}tag: {{ end }}{{ .Name }}</span>
-                      {{ end }}
-                    {{ end }}
-                  </div>
-                  {{ end }}
-                </div>
-                <div class="cell author">{{ .Author }}</div>
-                <div class="cell date">{{ .Date | FormatDate }}</div>
-            </div>
-        {{ else}}
-            <div class="row">(no commits)</div>
-        {{ end }}
+{{- define "head" -}}
+<style>
+  .commits {
+    border: 1px solid var(--c-border);
+    border-top: none;
+    border-bottom-left-radius: var(--border-radius);
+    border-bottom-right-radius: var(--border-radius);
+    overflow-x: auto;
+  }
+  .row {
+    display: flex;
+    height: 40px;
+    border-bottom: 1px solid var(--c-border);
+    padding-inline: 16px;
+    gap: 16px;
+  }
+  .row:last-child {
+    border-bottom: none;
+  }
+  .row:hover {
+    background-color: var(--c-bg-alt);
+  }
+  .cell {
+    display: flex;
+    gap: 8px;
+    align-items: center;
+  }
+  .hash a {
+    font-family: var(--font-family-mono), monospace;
+    color: var(--c-text-2);
+  }
+  .commit-title {
+    flex: 1;
+  }
+  .commit-title a {
+    color: var(--c-text-1);
+    line-height: 1.5;
+  }
+  .commit-title a:hover {
+    color: var(--c-brand-2);
+  }
+  .ref-badges {
+    display: inline-flex;
+    gap: 6px;
+    margin-left: 8px;
+  }
+  .badge {
+    font-size: 12px;
+    color: var(--c-text-2);
+    border: 1px solid var(--c-border);
+    padding: 2px 6px;
+    border-radius: 999px;
+    white-space: nowrap;
+  }
+  .date {
+    font-family: var(--font-family-mono), monospace;
+    font-size: 12px;
+    color: var(--c-text-2);
+  }
+  .pagination {
+    display: flex;
+    gap: 8px;
+    align-items: center;
+    justify-content: center;
+    margin-top: 12px;
+    padding: 8px 0;
+    color: var(--c-text-2);
+  }
+  .pagination a,
+  .pagination span.btn {
+    display: inline-flex;
+    align-items: center;
+    gap: 6px;
+    padding: 6px 10px;
+    border: 1px solid var(--c-border);
+    border-radius: 6px;
+    background: var(--c-bg-elv);
+    color: var(--c-text-1);
+    text-decoration: none;
+    font-size: 13px;
+  }
+  .pagination a:hover {
+    color: var(--c-brand-2);
+    border-color: var(--c-brand-2);
+  }
+  .pagination .disabled {
+    opacity: 0.5;
+    pointer-events: none;
+  }
+  .pagination .page-indicator {
+    margin: 0 4px;
+    font-size: 13px;
+    color: var(--c-text-2);
+  }
+  @media (max-width: 767px) {
+    .row {
+      height: auto;
+      padding: 10px 12px;
+      gap: 12px;
+      flex-wrap: wrap;
+      align-items: flex-start;
+    }
+    .commit-title {
+      flex-basis: 100%;
+      order: 1;
+    }
+    .author, .date, .hash {
+      font-size: 12px;
+    }
+    .author {
+      color: var(--c-text-2);
+      order: 2;
+    }
+    .date {
+      order: 2;
+    }
+    .hash {
+      margin-left: auto;
+      order: 3;
+    }
+  }
+</style>
+{{- end}}
+
+{{- define "body" -}}
+{{- template "header" .}}
+<div class="commits">
+{{- range .Commits}}
+  <div class="row">
+    <div class="cell hash">
+      <a href="{{.Href}}">{{.ShortHash}}</a>
     </div>
-    <div class="pagination">
-        {{ if .Page.FirstHref }}
-            <a class="btn" href="{{ .Page.FirstHref }}">« First</a>
-        {{ else }}
-            <span class="btn disabled">« First</span>
-        {{ end }}
-
-        {{ if .Page.PrevHref }}
-            <a class="btn" href="{{ .Page.PrevHref }}">← Newer</a>
-        {{ else }}
-            <span class="btn disabled">← Newer</span>
-        {{ end }}
-
-        <span class="page-indicator">Page {{ .Page.Page }} of {{ .Page.TotalPages }}</span>
-
-        {{ if .Page.NextHref }}
-            <a class="btn" href="{{ .Page.NextHref }}">Older →</a>
-        {{ else }}
-            <span class="btn disabled">Older →</span>
-        {{ end }}
-
-        {{ if .Page.LastHref }}
-            <a class="btn" href="{{ .Page.LastHref }}">Last »</a>
-        {{ else }}
-            <span class="btn disabled">Last »</span>
-        {{ end }}
+    <div class="cell commit-title">
+      <a href="{{.Href}}">{{.Subject}}</a>
+{{- if .RefNames}}
+      <div class="ref-badges">
+{{- range .RefNames}}
+{{- if or (eq .Kind "Branch") (eq .Kind "Tag")}}
+        <span class="badge">{{if eq .Kind "Tag"}}tag: {{end}}{{.Name}}</span>
+{{- end}}
+{{- end}}
+      </div>
+{{- end}}
     </div>
-{{ end }}
+    <div class="cell author">{{.Author}}</div>
+    <div class="cell date">{{.Date | FormatDate}}</div>
+  </div>
+{{- else}}
+  <div class="row">(no commits)</div>
+{{- end}}
+</div>
+<div class="pagination">
+{{- if .Page.FirstHref}}
+  <a class="btn" href="{{.Page.FirstHref}}">« First</a>
+{{- else}}
+  <span class="btn disabled">« First</span>
+{{- end}}
+{{- if .Page.PrevHref}}
+  <a class="btn" href="{{.Page.PrevHref}}">← Newer</a>
+{{- else}}
+  <span class="btn disabled">← Newer</span>
+{{- end}}
+  <span class="page-indicator">Page {{.Page.Page}} of {{.Page.TotalPages}}</span>
+{{- if .Page.NextHref}}
+  <a class="btn" href="{{.Page.NextHref}}">Older →</a>
+{{- else}}
+  <span class="btn disabled">Older →</span>
+{{- end}}
+{{- if .Page.LastHref}}
+  <a class="btn" href="{{.Page.LastHref}}">Last »</a>
+{{- else}}
+  <span class="btn disabled">Last »</span>
+{{- end}}
+</div>
+{{- end}}
internal/templates/file_tree.gohtml
@@ -1,43 +1,43 @@
 {{- /*gotype:mokhan.ca/antonmedv/gitmal/pkg/templates.FileTreeParams*/ -}}
-{{ define "file_tree" }}
-    {{ range .Nodes }}
-        {{ if .IsDir }}
-            <details open>
-                <summary class="node">
-                    <svg aria-hidden="true" focusable="false" width="16" height="16" class="dir">
-                        <use xlink:href="#dir"></use>
-                    </svg>
-                    <span class="file-name">{{ .Name }}</span>
-                </summary>
-                <div class="children">
-                    {{ template "file_tree" (FileTreeParams .Children) }}
-                </div>
-            </details>
-        {{ else }}
-            <div class="node">
-                <div class="icon" aria-hidden="true">
-                    {{ if .IsNew }}
-                        <svg aria-hidden="true" focusable="false" width="16" height="16" class="file-added">
-                            <use xlink:href="#file-added"></use>
-                        </svg>
-                    {{ else if .IsDelete }}
-                        <svg aria-hidden="true" focusable="false" width="16" height="16" class="file-deleted">
-                            <use xlink:href="#file-deleted"></use>
-                        </svg>
-                    {{ else if .IsRename }}
-                        <svg aria-hidden="true" focusable="false" width="16" height="16" class="file-renamed">
-                            <use xlink:href="#file-renamed"></use>
-                        </svg>
-                    {{ else }}
-                        <svg aria-hidden="true" focusable="false" width="16" height="16">
-                            <use xlink:href="#file-modified"></use>
-                        </svg>
-                    {{ end }}
-                </div>
-                <a href="#{{.Path}}" class="file-name">
-                    {{ .Path | BaseName }}
-                </a>
-            </div>
-        {{ end }}
-    {{ end }}
-{{ end }}
+{{- define "file_tree" -}}
+{{- range .Nodes}}
+{{- if .IsDir}}
+<details open>
+  <summary class="node">
+    <svg aria-hidden="true" focusable="false" width="16" height="16" class="dir">
+      <use xlink:href="#dir"></use>
+    </svg>
+    <span class="file-name">{{.Name}}</span>
+  </summary>
+  <div class="children">
+{{- template "file_tree" (FileTreeParams .Children)}}
+  </div>
+</details>
+{{- else}}
+<div class="node">
+  <div class="icon" aria-hidden="true">
+{{- if .IsNew}}
+    <svg aria-hidden="true" focusable="false" width="16" height="16" class="file-added">
+      <use xlink:href="#file-added"></use>
+    </svg>
+{{- else if .IsDelete}}
+    <svg aria-hidden="true" focusable="false" width="16" height="16" class="file-deleted">
+      <use xlink:href="#file-deleted"></use>
+    </svg>
+{{- else if .IsRename}}
+    <svg aria-hidden="true" focusable="false" width="16" height="16" class="file-renamed">
+      <use xlink:href="#file-renamed"></use>
+    </svg>
+{{- else}}
+    <svg aria-hidden="true" focusable="false" width="16" height="16">
+      <use xlink:href="#file-modified"></use>
+    </svg>
+{{- end}}
+  </div>
+  <a href="#{{.Path}}" class="file-name">
+    {{.Path | BaseName}}
+  </a>
+</div>
+{{- end}}
+{{- end}}
+{{- end}}
internal/templates/header.gohtml
@@ -1,27 +1,27 @@
 {{- /*gotype: mokhan.ca/antonmedv/gitmal/pkg/templates.HeaderParams*/ -}}
-{{ define "header" }}
-    <header>
-        {{ if .Ref }}
-            <div class="header-ref" aria-label="Ref">{{ .Ref }}</div>
-        {{ end }}
-        {{ if .Header }}
-            <h1 class="title">{{ .Header }}</h1>
-        {{ else if .Breadcrumbs }}
-            <nav class="breadcrumbs" aria-label="Breadcrumbs">
-                {{ range $i, $b := .Breadcrumbs }}
-                    {{ if gt $i 0 }}
-                        <div>/</div>
-                    {{ end }}
-                    {{ if $b.Href }}
-                        <a href="{{$b.Href}}">{{$b.Name}}</a>
-                    {{ else }}
-                        <h1>{{$b.Name}}</h1>
-                        {{ if $b.IsDir}}
-                            <div>/</div>
-                        {{ end}}
-                    {{ end }}
-                {{ end }}
-            </nav>
-        {{ end }}
-    </header>
-{{ end }}
+{{- define "header" -}}
+<header>
+{{- if .Ref}}
+  <div class="header-ref" aria-label="Ref">{{.Ref}}</div>
+{{- end}}
+{{- if .Header}}
+  <h1 class="title">{{.Header}}</h1>
+{{- else if .Breadcrumbs}}
+  <nav class="breadcrumbs" aria-label="Breadcrumbs">
+{{- range $i, $b := .Breadcrumbs}}
+{{- if gt $i 0}}
+    <div>/</div>
+{{- end}}
+{{- if $b.Href}}
+    <a href="{{$b.Href}}">{{$b.Name}}</a>
+{{- else}}
+    <h1>{{$b.Name}}</h1>
+{{- if $b.IsDir}}
+    <div>/</div>
+{{- end}}
+{{- end}}
+{{- end}}
+  </nav>
+{{- end}}
+</header>
+{{- end}}
internal/templates/layout.gohtml
@@ -4,46 +4,50 @@
 <head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1">
-  <title>{{ .Title }}</title>
-  <link rel="stylesheet" href="{{ .RootHref }}css/layout.css">
-{{- if .NeedsMarkdownCSS }}<link rel="stylesheet" href="{{ .RootHref }}css/markdown.css">{{ end }}
-{{- if .NeedsSyntaxCSS }}<link rel="stylesheet" href="{{ .RootHref }}css/syntax.css">{{ end }}
-{{ template "head" . }}
+  <title>{{.Title}}</title>
+  <link rel="stylesheet" href="{{.RootHref}}css/layout.css">
+{{- if .NeedsMarkdownCSS}}
+  <link rel="stylesheet" href="{{.RootHref}}css/markdown.css">
+{{- end}}
+{{- if .NeedsSyntaxCSS}}
+  <link rel="stylesheet" href="{{.RootHref}}css/syntax.css">
+{{- end}}
+{{- template "head" .}}
 </head>
 <body>
-{{ template "svg" . }}
+{{- template "svg" .}}
 <div class="menu">
   <div class="menu-content">
-    <a href="{{ .RootHref }}index.html" class="project-name">{{ .Name }}</a>
-    <div class="menu-item {{ if eq .Selected "code" }}selected{{ end }}">
-      <a href="{{ .RootHref }}blob/{{ .CurrentRefDir }}/index.html">
+    <a href="{{.RootHref}}index.html" class="project-name">{{.Name}}</a>
+    <div class="menu-item{{if eq .Selected "code"}} selected{{end}}">
+      <a href="{{.RootHref}}blob/{{.CurrentRefDir}}/index.html">
         <svg aria-hidden="true" width="16" height="16"><use xlink:href="#code"></use></svg>
         Code
       </a>
     </div>
-    <div class="menu-item {{ if eq .Selected "branches" }}selected{{ end }}">
-        <a href="{{ .RootHref }}branches.html">
-          <svg aria-hidden="true" focusable="false" width="16" height="16"><use xlink:href="#branch"></use></svg>
-          Branches
-        </a>
+    <div class="menu-item{{if eq .Selected "branches"}} selected{{end}}">
+      <a href="{{.RootHref}}branches.html">
+        <svg aria-hidden="true" focusable="false" width="16" height="16"><use xlink:href="#branch"></use></svg>
+        Branches
+      </a>
     </div>
-    <div class="menu-item {{ if eq .Selected "tags" }}selected{{ end }}">
-        <a href="{{ .RootHref }}tags.html">
-          <svg aria-hidden="true" focusable="false" width="16" height="16"><use xlink:href="#tag"></use></svg>
-          Tags
-        </a>
+    <div class="menu-item{{if eq .Selected "tags"}} selected{{end}}">
+      <a href="{{.RootHref}}tags.html">
+        <svg aria-hidden="true" focusable="false" width="16" height="16"><use xlink:href="#tag"></use></svg>
+        Tags
+      </a>
     </div>
-    <div class="menu-item {{ if eq .Selected "commits" }}selected{{ end }}">
-        <a href="{{ .RootHref }}commits/{{ .CurrentRefDir }}/index.html">
-          <svg aria-hidden="true" focusable="false" width="16" height="16"><use xlink:href="#commit"></use></svg>
-          Commits
-        </a>
+    <div class="menu-item{{if eq .Selected "commits"}} selected{{end}}">
+      <a href="{{.RootHref}}commits/{{.CurrentRefDir}}/index.html">
+        <svg aria-hidden="true" focusable="false" width="16" height="16"><use xlink:href="#commit"></use></svg>
+        Commits
+      </a>
     </div>
   </div>
 </div>
 <main>
   <div class="main-content">
-    {{ template "body" . }}
+{{- template "body" .}}
   </div>
 </main>
 <footer></footer>
internal/templates/list.gohtml
@@ -1,143 +1,126 @@
 {{- /*gotype: mokhan.ca/antonmedv/gitmal/pkg/templates.ListParams*/ -}}
-{{ define "head" }}
-    <style>
-      .files {
-        border: 1px solid var(--c-border);
-        border-top: none;
-        width: 100%;
-        border-bottom-left-radius: var(--border-radius);
-        border-bottom-right-radius: var(--border-radius);
-        overflow-x: auto;
-      }
-
-      .files .dir {
-        color: var(--c-dir);
-      }
-
-      .files a {
-        color: var(--c-text-1);
-      }
-
-      .files a:hover {
-        color: var(--c-brand-2);
-      }
-
-      .row {
-        display: flex;
-        height: 40px;
-        border-bottom: 1px solid var(--c-border);
-        padding-inline: 16px;
-        gap: 16px;
-      }
-
-      .row:last-child {
-        border-bottom: none;
-      }
-
-      .row:hover {
-        background-color: var(--c-bg-alt);
-      }
-
-      .cell {
-        flex: 1;
-        display: flex;
-        gap: 8px;
-        align-items: center;
-        white-space: nowrap;
-      }
-
-      .cell:not(:first-child) {
-        justify-content: flex-end;
-        max-width: 100px;
-      }
-
-      @media (max-width: 767px) {
-        .file-mode {
-          display: none;
-        }
-      }
-
-      {{ if .Readme }}
-      .markdown-container {
-        padding-inline: 16px;
-        border: 1px solid var(--c-divider);
-        border-radius: 8px;
-        overflow-x: auto;
-        margin-top: 16px;
-      }
-
-      .markdown-body {
-        width: 100%;
-        min-width: 200px;
-        max-width: 980px;
-        margin: 0 auto;
-        padding: 32px;
-        word-wrap: break-word;
-        font-size: 16px;
-        line-height: 1.5;
-      }
-
-      @media (max-width: 767px) {
-        .markdown-body {
-          padding: 16px;
-        }
-      }
-      {{ end }}
-    </style>
-{{ end }}
-
-{{ define "body" }}
-    {{ template "header" . }}
-
-    <div class="files">
-        {{ if .ParentHref }}
-            <div class="row">
-                <div class="cell">
-                    <svg aria-hidden="true" focusable="false" width="16" height="16" class="dir">
-                        <use xlink:href="#dir"></use>
-                    </svg>
-                    <a href="{{ .ParentHref }}">..</a>
-                </div>
-            </div>
-        {{ end }}
-
-        {{ if or .Dirs .Files }}
-            {{ range .Dirs }}
-                <div class="row">
-                    <div class="cell">
-                        <svg aria-hidden="true" focusable="false" width="16" height="16" class="dir">
-                            <use xlink:href="#dir"></use>
-                        </svg>
-                        <a href="{{ .Href }}">{{ .Name }}</a>
-                    </div>
-                </div>
-            {{ end }}
-
-            {{ range .Files }}
-                <div class="row">
-                    <div class="cell">
-                        <svg aria-hidden="true" focusable="false" width="16" height="16">
-                            <use xlink:href="#file"></use>
-                        </svg>
-                        <a href="{{ .Href }}">{{ .Name }}</a>
-                    </div>
-                    <div class="cell file-mode">{{ .Mode }}</div>
-                    <div class="cell file-size">{{ .Size }}</div>
-                </div>
-            {{ end }}
-        {{ else }}
-            <div class="row">
-                <div class="cell">(empty)</div>
-            </div>
-        {{ end }}
+{{- define "head" -}}
+<style>
+  .files {
+    border: 1px solid var(--c-border);
+    border-top: none;
+    width: 100%;
+    border-bottom-left-radius: var(--border-radius);
+    border-bottom-right-radius: var(--border-radius);
+    overflow-x: auto;
+  }
+  .files .dir {
+    color: var(--c-dir);
+  }
+  .files a {
+    color: var(--c-text-1);
+  }
+  .files a:hover {
+    color: var(--c-brand-2);
+  }
+  .row {
+    display: flex;
+    height: 40px;
+    border-bottom: 1px solid var(--c-border);
+    padding-inline: 16px;
+    gap: 16px;
+  }
+  .row:last-child {
+    border-bottom: none;
+  }
+  .row:hover {
+    background-color: var(--c-bg-alt);
+  }
+  .cell {
+    flex: 1;
+    display: flex;
+    gap: 8px;
+    align-items: center;
+    white-space: nowrap;
+  }
+  .cell:not(:first-child) {
+    justify-content: flex-end;
+    max-width: 100px;
+  }
+  @media (max-width: 767px) {
+    .file-mode {
+      display: none;
+    }
+  }
+{{- if .Readme}}
+  .markdown-container {
+    padding-inline: 16px;
+    border: 1px solid var(--c-divider);
+    border-radius: 8px;
+    overflow-x: auto;
+    margin-top: 16px;
+  }
+  .markdown-body {
+    width: 100%;
+    min-width: 200px;
+    max-width: 980px;
+    margin: 0 auto;
+    padding: 32px;
+    word-wrap: break-word;
+    font-size: 16px;
+    line-height: 1.5;
+  }
+  @media (max-width: 767px) {
+    .markdown-body {
+      padding: 16px;
+    }
+  }
+{{- end}}
+</style>
+{{- end}}
+
+{{- define "body" -}}
+{{- template "header" .}}
+<div class="files">
+{{- if .ParentHref}}
+  <div class="row">
+    <div class="cell">
+      <svg aria-hidden="true" focusable="false" width="16" height="16" class="dir">
+        <use xlink:href="#dir"></use>
+      </svg>
+      <a href="{{.ParentHref}}">..</a>
     </div>
-
-    {{ if .Readme }}
-        <div class="markdown-container">
-            <div class="markdown-body">
-                {{ .Readme }}
-            </div>
-        </div>
-    {{ end }}
-{{ end }}
-
+  </div>
+{{- end}}
+{{- if or .Dirs .Files}}
+{{- range .Dirs}}
+  <div class="row">
+    <div class="cell">
+      <svg aria-hidden="true" focusable="false" width="16" height="16" class="dir">
+        <use xlink:href="#dir"></use>
+      </svg>
+      <a href="{{.Href}}">{{.Name}}</a>
+    </div>
+  </div>
+{{- end}}
+{{- range .Files}}
+  <div class="row">
+    <div class="cell">
+      <svg aria-hidden="true" focusable="false" width="16" height="16">
+        <use xlink:href="#file"></use>
+      </svg>
+      <a href="{{.Href}}">{{.Name}}</a>
+    </div>
+    <div class="cell file-mode">{{.Mode}}</div>
+    <div class="cell file-size">{{.Size}}</div>
+  </div>
+{{- end}}
+{{- else}}
+  <div class="row">
+    <div class="cell">(empty)</div>
+  </div>
+{{- end}}
+</div>
+{{- if .Readme}}
+<div class="markdown-container">
+  <div class="markdown-body">
+{{.Readme}}
+  </div>
+</div>
+{{- end}}
+{{- end}}
internal/templates/markdown.gohtml
@@ -1,43 +1,39 @@
 {{- /*gotype: mokhan.ca/antonmedv/gitmal/pkg/templates.MarkdownParams*/ -}}
-{{ define "head" }}
-    <style>
-      [id] {
-        scroll-margin-top: var(--header-height);
-      }
-
-      .markdown-container {
-        border: 1px solid var(--c-divider);
-        border-top: none;
-        border-bottom-left-radius: 8px;
-        border-bottom-right-radius: 8px;
-        overflow-x: auto;
-      }
-
-      .markdown-body {
-        width: 100%;
-        min-width: 200px;
-        max-width: 980px;
-        margin: 0 auto;
-        padding: 32px;
-        word-wrap: break-word;
-        font-size: 16px;
-        line-height: 1.5;
-      }
-
-      @media (max-width: 767px) {
-        .markdown-body {
-          padding: 16px;
-        }
-      }
-    </style>
-{{ end }}
-
-{{ define "body" }}
-    {{ template "header" . }}
-    <article class="markdown-container">
-        <div class="markdown-body">
-            {{ .Content }}
-        </div>
-    </article>
-{{ end }}
+{{- define "head" -}}
+<style>
+  [id] {
+    scroll-margin-top: var(--header-height);
+  }
+  .markdown-container {
+    border: 1px solid var(--c-divider);
+    border-top: none;
+    border-bottom-left-radius: 8px;
+    border-bottom-right-radius: 8px;
+    overflow-x: auto;
+  }
+  .markdown-body {
+    width: 100%;
+    min-width: 200px;
+    max-width: 980px;
+    margin: 0 auto;
+    padding: 32px;
+    word-wrap: break-word;
+    font-size: 16px;
+    line-height: 1.5;
+  }
+  @media (max-width: 767px) {
+    .markdown-body {
+      padding: 16px;
+    }
+  }
+</style>
+{{- end}}
 
+{{- define "body" -}}
+{{- template "header" .}}
+<article class="markdown-container">
+  <div class="markdown-body">
+{{.Content}}
+  </div>
+</article>
+{{- end}}
internal/templates/svg.gohtml
@@ -1,19 +1,19 @@
-{{ define "svg" }}
+{{- define "svg" -}}
 <svg style="display: none" aria-hidden="true" focusable="false">
   <symbol id="dir" viewBox="0 0 16 16">
     <path fill="currentColor" d="M1.75 1A1.75 1.75 0 0 0 0 2.75v10.5C0 14.216.784 15 1.75 15h12.5A1.75 1.75 0 0 0 16 13.25v-8.5A1.75 1.75 0 0 0 14.25 3H7.5a.25.25 0 0 1-.2-.1l-.9-1.2C6.07 1.26 5.55 1 5 1H1.75Z"/>
   </symbol>
   <symbol id="file" viewBox="0 0 16 16">
-      <path fill="currentColor" d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"/>
+    <path fill="currentColor" d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V6h-2.75A1.75 1.75 0 0 1 9 4.25V1.5Zm6.75.062V4.25c0 .138.112.25.25.25h2.688l-.011-.013-2.914-2.914-.013-.011Z"/>
   </symbol>
   <symbol id="file-added" viewBox="0 0 16 16">
-      <path fill="currentColor" d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V4.664a.25.25 0 0 0-.073-.177l-2.914-2.914a.25.25 0 0 0-.177-.073Zm4.48 3.758a.75.75 0 0 1 .755.745l.01 1.497h1.497a.75.75 0 0 1 0 1.5H9v1.507a.75.75 0 0 1-1.5 0V9.005l-1.502.01a.75.75 0 0 1-.01-1.5l1.507-.01-.01-1.492a.75.75 0 0 1 .745-.755Z"/>
+    <path fill="currentColor" d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V4.664a.25.25 0 0 0-.073-.177l-2.914-2.914a.25.25 0 0 0-.177-.073Zm4.48 3.758a.75.75 0 0 1 .755.745l.01 1.497h1.497a.75.75 0 0 1 0 1.5H9v1.507a.75.75 0 0 1-1.5 0V9.005l-1.502.01a.75.75 0 0 1-.01-1.5l1.507-.01-.01-1.492a.75.75 0 0 1 .745-.755Z"/>
   </symbol>
   <symbol id="file-modified" viewBox="0 0 16 16">
-      <path fill="currentColor" d="M1 1.75C1 .784 1.784 0 2.75 0h7.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V4.664a.25.25 0 0 0-.073-.177l-2.914-2.914a.25.25 0 0 0-.177-.073ZM8 3.25a.75.75 0 0 1 .75.75v1.5h1.5a.75.75 0 0 1 0 1.5h-1.5v1.5a.75.75 0 0 1-1.5 0V7h-1.5a.75.75 0 0 1 0-1.5h1.5V4A.75.75 0 0 1 8 3.25Zm-3 8a.75.75 0 0 1 .75-.75h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1-.75-.75Z"/>
+    <path fill="currentColor" d="M1 1.75C1 .784 1.784 0 2.75 0h7.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16H2.75A1.75 1.75 0 0 1 1 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25V4.664a.25.25 0 0 0-.073-.177l-2.914-2.914a.25.25 0 0 0-.177-.073ZM8 3.25a.75.75 0 0 1 .75.75v1.5h1.5a.75.75 0 0 1 0 1.5h-1.5v1.5a.75.75 0 0 1-1.5 0V7h-1.5a.75.75 0 0 1 0-1.5h1.5V4A.75.75 0 0 1 8 3.25Zm-3 8a.75.75 0 0 1 .75-.75h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1-.75-.75Z"/>
   </symbol>
   <symbol id="file-deleted" viewBox="0 0 16 16">
-      <path fill="currentColor" d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V4.664a.25.25 0 0 0-.073-.177l-2.914-2.914a.25.25 0 0 0-.177-.073Zm4.5 6h2.242a.75.75 0 0 1 0 1.5h-2.24l-2.254.015a.75.75 0 0 1-.01-1.5Z"/>
+    <path fill="currentColor" d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-9.5A1.75 1.75 0 0 1 2 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h9.5a.25.25 0 0 0 .25-.25V4.664a.25.25 0 0 0-.073-.177l-2.914-2.914a.25.25 0 0 0-.177-.073Zm4.5 6h2.242a.75.75 0 0 1 0 1.5h-2.24l-2.254.015a.75.75 0 0 1-.01-1.5Z"/>
   </symbol>
   <symbol id="file-renamed" viewBox="0 0 16 16">
     <path fill="currentColor" d="M2 1.75C2 .784 2.784 0 3.75 0h6.586c.464 0 .909.184 1.237.513l2.914 2.914c.329.328.513.773.513 1.237v9.586A1.75 1.75 0 0 1 13.25 16h-3.5a.75.75 0 0 1 0-1.5h3.5a.25.25 0 0 0 .25-.25V4.664a.25.25 0 0 0-.073-.177l-2.914-2.914a.25.25 0 0 0-.177-.073H3.75a.25.25 0 0 0-.25.25v6.5a.75.75 0 0 1-1.5 0v-6.5Z"/>
@@ -35,4 +35,4 @@
     <path fill="currentColor" d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path>
   </symbol>
 </svg>
-{{ end }}
+{{- end}}
internal/templates/tags.gohtml
@@ -1,71 +1,63 @@
 {{- /*gotype: mokhan.ca/antonmedv/gitmal/pkg/templates.TagsParams*/ -}}
-{{ define "head" }}
-    <style>
-      .tags {
-        border: 1px solid var(--c-border);
-        border-radius: var(--border-radius);
-        overflow: hidden;
-      }
-
-      .tag-row {
-        display: flex;
-        align-items: center;
-        gap: 12px;
-        height: 44px;
-        padding-inline: 16px;
-        border-bottom: 1px solid var(--c-border);
-        background-color: var(--c-bg-elv);
-      }
-
-      .tag-row:last-child {
-        border-bottom: none;
-      }
-
-      .cell {
-        display: flex;
-        gap: 8px;
-        align-items: center;
-      }
-
-      .tag-title {
-        flex: 1;
-      }
-
-      .tag-row a {
-        color: var(--c-text-1);
-      }
-
-      .tag-row a:hover {
-        color: var(--c-brand-2);
-        text-decoration: none;
-      }
-
-      .date {
-        font-family: var(--font-family-mono), monospace;
-        font-size: 12px;
-        color: var(--c-text-2);
-      }
-
-      .hash a {
-        font-family: var(--font-family-mono), monospace;
-        color: var(--c-text-2);
-      }
-    </style>
-{{ end }}
-
-{{ define "body" }}
-    <h1>Tags</h1>
-    <div class="tags">
-        {{ if .Tags }}
-            {{ range .Tags }}
-                <div class="tag-row">
-                    <div class="cell tag-title"><a href="commit/{{ .CommitHash }}.html">{{ .Name }}</a></div>
-                    <div class="cell date">{{ .Date | FormatDate }}</div>
-                    <div class="cell hash"><a href="commit/{{ .CommitHash }}.html">{{ ShortHash .CommitHash }}</a></div>
-                </div>
-            {{ end }}
-        {{ else }}
-            <div class="tag-row">(no tags)</div>
-        {{ end }}
-    </div>
-{{ end }}
+{{- define "head" -}}
+<style>
+  .tags {
+    border: 1px solid var(--c-border);
+    border-radius: var(--border-radius);
+    overflow: hidden;
+  }
+  .tag-row {
+    display: flex;
+    align-items: center;
+    gap: 12px;
+    height: 44px;
+    padding-inline: 16px;
+    border-bottom: 1px solid var(--c-border);
+    background-color: var(--c-bg-elv);
+  }
+  .tag-row:last-child {
+    border-bottom: none;
+  }
+  .cell {
+    display: flex;
+    gap: 8px;
+    align-items: center;
+  }
+  .tag-title {
+    flex: 1;
+  }
+  .tag-row a {
+    color: var(--c-text-1);
+  }
+  .tag-row a:hover {
+    color: var(--c-brand-2);
+    text-decoration: none;
+  }
+  .date {
+    font-family: var(--font-family-mono), monospace;
+    font-size: 12px;
+    color: var(--c-text-2);
+  }
+  .hash a {
+    font-family: var(--font-family-mono), monospace;
+    color: var(--c-text-2);
+  }
+</style>
+{{- end}}
+
+{{- define "body" -}}
+<h1>Tags</h1>
+<div class="tags">
+{{- if .Tags}}
+{{- range .Tags}}
+  <div class="tag-row">
+    <div class="cell tag-title"><a href="commit/{{.CommitHash}}.html">{{.Name}}</a></div>
+    <div class="cell date">{{.Date | FormatDate}}</div>
+    <div class="cell hash"><a href="commit/{{.CommitHash}}.html">{{ShortHash .CommitHash}}</a></div>
+  </div>
+{{- end}}
+{{- else}}
+  <div class="tag-row">(no tags)</div>
+{{- end}}
+</div>
+{{- end}}