FossilRepo

fossilrepo / templates / fossil / code_file.html
1
{% extends "base.html" %}
2
{% block title %}{{ filepath }} — {{ project.name }} — Fossilrepo{% endblock %}
3
4
{% block extra_head %}
5
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css">
6
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
7
<style>
8
.code-table { border-collapse: collapse; width: 100%; }
9
.code-table td.line-num {
10
width: 1%; white-space: nowrap; padding: 0 16px !important;
11
text-align: right; user-select: none; cursor: pointer;
12
color: #4b5563; font-size: 0.75rem; line-height: 1.5rem;
13
border-right: 1px solid #374151; vertical-align: top;
14
}
15
.code-table td.line-num:hover { color: #DC394C; }
16
.code-table td.line-num a { color: inherit; text-decoration: none; display: block; }
17
.code-table td.line-code {
18
white-space: pre; padding: 0 16px !important;
19
font-size: 0.8125rem; line-height: 1.5rem; vertical-align: top;
20
}
21
.line-row:hover { background: rgba(220, 57, 76, 0.05); }
22
.line-row:target { background: rgba(220, 57, 76, 0.12); }
23
.line-row:target .line-num { color: #DC394C; font-weight: 600; }
24
.line-row { scroll-margin-top: 40vh; }
25
.line-popover {
26
position: absolute; left: 100%; top: 50%; transform: translateY(-50%);
27
margin-left: 4px; z-index: 20; white-space: nowrap;
28
background: #1f2937; border: 1px solid #374151; border-radius: 6px;
29
box-shadow: 0 4px 12px rgba(0,0,0,0.4); padding: 2px;
30
display: flex; gap: 2px;
31
}
32
.line-popover button {
33
display: flex; align-items: center; gap: 4px; padding: 4px 8px;
34
font-size: 0.7rem; color: #d1d5db; background: transparent;
35
border: none; border-radius: 4px; cursor: pointer;
36
}
37
.line-popover button:hover { background: #374151; color: #fff; }
38
.line-popover button.copied { color: #22c55e; }
39
</style>
40
{% endblock %}
41
42
{% block content %}
43
<h1 class="text-2xl font-bold text-gray-100 mb-2">{{ project.name }}</h1>
44
{% include "fossil/_project_nav.html" %}
45
46
<div class="overflow-hidden rounded-lg bg-gray-800 shadow-sm border border-gray-700">
47
<!-- File path breadcrumb + stats -->
48
<div class="px-4 py-3 border-b border-gray-700 flex flex-wrap items-center justify-between gap-x-2 gap-y-2">
49
<div class="flex flex-wrap items-center gap-1 text-sm font-mono min-w-0">
50
<a href="{% url 'fossil:code' slug=project.slug %}" class="text-brand-light hover:text-brand">{{ project.slug }}</a>
51
{% for crumb in file_breadcrumbs %}
52
<span class="text-gray-600">/</span>
53
{% if forloop.last %}
54
<span class="text-gray-200">{{ crumb.name }}</span>
55
{% else %}
56
<a href="{% url 'fossil:code_dir' slug=project.slug dirpath=crumb.path %}" class="text-brand-light hover:text-brand">{{ crumb.name }}</a>
57
{% endif %}
58
{% endfor %}
59
</div>
60
<div class="flex flex-wrap items-center gap-2">
61
{% if can_render %}
62
<div class="flex items-center gap-1 text-xs">
63
<a href="?mode=source" class="px-2 py-1 rounded {% if view_mode == 'source' %}bg-brand text-white{% else %}text-gray-500 hover:text-white{% endif %}">Source</a>
64
<a href="?mode=rendered" class="px-2 py-1 rounded {% if view_mode == 'rendered' %}bg-brand text-white{% else %}text-gray-500 hover:text-white{% endif %}">Rendered</a>
65
</div>
66
{% endif %}
67
<a href="{% url 'fossil:code_blame' slug=project.slug filepath=filepath %}" class="px-2 py-1 text-xs text-gray-500 hover:text-brand-light rounded hover:bg-gray-700">Blame</a>
68
<a href="{% url 'fossil:file_history' slug=project.slug filepath=filepath %}" class="px-2 py-1 text-xs text-gray-500 hover:text-brand-light rounded hover:bg-gray-700">History</a>
69
<a href="{% url 'fossil:code_raw' slug=project.slug filepath=filepath %}" class="px-2 py-1 text-xs text-gray-500 hover:text-brand-light rounded hover:bg-gray-700">Raw</a>
70
{% if not is_binary %}
71
<span class="text-xs text-gray-500">{{ line_count }} line{{ line_count|pluralize }}</span>
72
{% endif %}
73
</div>
74
</div>
75
<div class="overflow-x-auto">
76
{% if is_binary %}
77
<p class="p-4 text-sm text-gray-500">{{ content }}</p>
78
{% elif view_mode == "rendered" and rendered_html %}
79
<div class="px-6 py-6">
80
<div class="prose prose-invert prose-gray max-w-none">
81
{{ rendered_html }}
82
</div>
83
</div>
84
{% else %}
85
<table class="code-table">
86
<tbody>
87
{% for line in lines %}
88
<tr class="line-row" id="L{{ line.num }}">
89
<td class="line-num" style="position:relative"
90
x-data="{ pop: false, copied: false }"
91
@click.stop="pop = !pop; window.location.hash = 'L{{ line.num }}'"
92
@click.outside="pop = false">
93
{{ line.num }}
94
<div class="line-popover" x-show="pop" x-transition @click.stop>
95
<button @click="navigator.clipboard.writeText(window.location.origin + window.location.pathname + '#L{{ line.num }}'); copied = true; setTimeout(() => { copied = false; pop = false }, 1000)" :class="copied && 'copied'">
96
<span x-show="!copied">Copy link</span><span x-show="copied">Copied!</span>
97
</button>
98
</div>
99
</td>
100
<td class="line-code"><code class="language-{{ language }}">{{ line.text }}</code></td>
101
</tr>
102
{% endfor %}
103
</tbody>
104
</table>
105
{% endif %}
106
</div>
107
</div>
108
109
{% if not is_binary %}
110
<script>
111
document.querySelectorAll('.line-code code').forEach(el => hljs.highlightElement(el));
112
</script>
113
{% endif %}
114
{% endblock %}
115

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button