Monorepo for Tangled
1{{ define "title" }}{{ .Path }} at {{ .Ref }} · {{ .RepoInfo.FullName }}{{ end }}
2
3{{ define "extrameta" }}
4 {{ template "repo/fragments/meta" . }}
5
6 {{ $title := printf "%s at %s · %s" .Path .Ref .RepoInfo.FullName }}
7 {{ $url := printf "https://tangled.org/%s/blob/%s/%s" .RepoInfo.FullName .Ref .Path }}
8
9 {{ template "repo/fragments/og" (dict "RepoInfo" .RepoInfo "Title" $title "Url" $url) }}
10
11{{ end }}
12
13{{ define "repoContent" }}
14 {{ $linkstyle := "no-underline hover:underline" }}
15 <div class="peer pb-2 mb-3 text-base border-b border-gray-200 dark:border-gray-700">
16 <div class="flex flex-col md:flex-row md:justify-between gap-2">
17 <div id="breadcrumbs" class="overflow-x-auto whitespace-nowrap text-gray-400 dark:text-gray-500">
18 {{ range $idx, $value := .BreadCrumbs }}
19 {{ if ne $idx (sub (len $.BreadCrumbs) 1) }}
20 <a
21 href="{{ index . 1 }}"
22 class="text-bold text-gray-500 dark:text-gray-400 {{ $linkstyle }}"
23 >{{ pathUnescape (index . 0) }}</a
24 >
25 /
26 {{ else }}
27 <span class="text-bold text-black dark:text-white"
28 >{{ pathUnescape (index . 0) }}</span
29 >
30 {{ end }}
31 {{ end }}
32 </div>
33 <div id="file-info" class="text-gray-500 dark:text-gray-400 text-xs md:text-sm flex flex-wrap items-center gap-1 md:gap-0">
34 <span>at <a href="/{{ .RepoInfo.FullName }}/tree/{{ .Ref }}">{{ .Ref }}</a></span>
35
36 {{ if .BlobView.ShowingText }}
37 <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
38 <span>{{ .BlobView.Lines }} lines</span>
39 {{ end }}
40
41 {{ if .BlobView.SizeHint }}
42 <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
43 <span>{{ byteFmt .BlobView.SizeHint }}</span>
44 {{ end }}
45
46 {{ if .BlobView.HasRawView }}
47 <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
48 <a href="/{{ .RepoInfo.FullName }}/raw/{{ .Ref }}/{{ .Path }}">view raw</a>
49 {{ end }}
50
51 {{ if .BlobView.ShowToggle }}
52 <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
53 <a href="/{{ .RepoInfo.FullName }}/blob/{{ .Ref }}/{{ .Path }}?code={{ .BlobView.ShowingRendered }}" hx-boost="true">
54 view {{ if .BlobView.ShowingRendered }}code{{ else }}rendered{{ end }}
55 </a>
56 {{ end }}
57
58 {{ if .BlobView.ShowingText }}
59 <div id="toggle-wrap-content" class="flex items-center">
60 <span class="select-none px-1 md:px-2 [&:before]:content-['·']"></span>
61 <label class="flex lowercase font-normal px-1 py-0 gap-1 text-xs md:text-sm">
62 <input id="toggle-wrap-content-checkbox" type="checkbox" name="wrap"/>
63 wrap content
64 </label>
65 </div>
66 {{ end }}
67 </div>
68 </div>
69 </div>
70
71 {{ if .LastCommitInfo }}
72 {{ template "repo/fragments/lastCommitPanel" $ }}
73 {{ end }}
74
75 {{ $wrapContentClasses := "peer-has-[:checked]:*:whitespace-pre-wrap peer-has-[:checked]:*:[overflow-wrap:anywhere]" }}
76
77 {{ if .BlobView.IsUnsupported }}
78 <p class="text-center text-gray-400 dark:text-gray-500">
79 Previews are not supported for this file type.
80 </p>
81 {{ else if .BlobView.ContentType.IsSubmodule }}
82 <p class="text-center text-gray-400 dark:text-gray-500">
83 This directory is a git submodule of <a href="{{ .BlobView.ContentSrc }}">{{ .BlobView.ContentSrc }}</a>.
84 </p>
85 {{ else if .BlobView.ContentType.IsImage }}
86 <div class="text-center">
87 <img src="{{ .BlobView.ContentSrc }}"
88 alt="{{ .Path }}"
89 class="max-w-full h-auto mx-auto border border-gray-200 dark:border-gray-700 rounded" />
90 </div>
91 {{ else if .BlobView.ContentType.IsVideo }}
92 <div class="text-center">
93 <video controls class="max-w-full h-auto mx-auto border border-gray-200 dark:border-gray-700 rounded">
94 <source src="{{ .BlobView.ContentSrc }}">
95 Your browser does not support the video tag.
96 </video>
97 </div>
98 {{ else if .BlobView.ContentType.IsSvg }}
99 <div class="overflow-auto relative {{ $wrapContentClasses }}">
100 {{ if .BlobView.ShowingRendered }}
101 <div class="text-center">
102 <img src="{{ .BlobView.ContentSrc }}"
103 alt="{{ .Path }}"
104 class="max-w-full h-auto mx-auto border border-gray-200 dark:border-gray-700 rounded" />
105 </div>
106 {{ else }}
107 <div id="blob-contents" class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">{{ code .BlobView.Contents .Path | escapeHtml }}</div>
108 {{ end }}
109 </div>
110 {{ else if .BlobView.ContentType.IsMarkup }}
111 <div class="overflow-auto relative {{ $wrapContentClasses }}">
112 {{ if .BlobView.ShowingRendered }}
113 <div id="blob-contents" class="prose dark:prose-invert">{{ .BlobView.Contents | readme }}</div>
114 {{ else }}
115 <div id="blob-contents" class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">{{ code .BlobView.Contents .Path | escapeHtml }}</div>
116 {{ end }}
117 </div>
118 {{ else if .BlobView.ContentType.IsCode }}
119 <div class="overflow-auto relative {{ $wrapContentClasses }}">
120 <div id="blob-contents" class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">{{ code .BlobView.Contents .Path | escapeHtml }}</div>
121 </div>
122 {{ end }}
123 {{ template "fragments/multiline-select" }}
124 <script>
125 (() => {
126 const abortController = new AbortController();
127 const toggle = document.querySelector('#toggle-wrap-content');
128 const toggleCheckbox = document.querySelector('#toggle-wrap-content-checkbox');
129 const contents = document.querySelector('#blob-contents');
130
131 function showWrapContentToggleOnOverflow() {
132 if(!toggle || !toggleCheckbox || !contents) return;
133
134 const isScrollable = contents.scrollWidth > contents.clientWidth;
135 const showToggle = isScrollable || toggleCheckbox.checked;
136
137 if(showToggle) {
138 toggle.classList.remove('hidden');
139 } else {
140 toggle.classList.add('hidden');
141 }
142 }
143
144 window.addEventListener('resize', () => showWrapContentToggleOnOverflow(), {signal: abortController.signal});
145 document.body.addEventListener('htmx:afterSettle', () => showWrapContentToggleOnOverflow(), {signal: abortController.signal});
146 document.body.addEventListener('htmx:beforeCleanupElement', (e) => {
147 if(e.target === toggle) {
148 abortController.abort();
149 }
150 }, {signal: abortController.signal});
151
152 showWrapContentToggleOnOverflow();
153 })();
154 </script>
155{{ end }}