FossilRepo
Add clickable permalink anchors to diff line numbers - Each diff line gets an anchor ID: #diff-1-R42 (new) or #diff-1-L42 (old) - Line numbers are clickable links that update the URL hash - Target line highlighted with brand color background - Scroll-to-line on page load when hash is present - Hover state on gutter numbers
Commit
dc6f6e1bab6ebcdad14940e1bea80e5ec042e825deeab2bc7f778674fba90d13
Parent
5a04a5733693ed2…
1 file changed
+27
-3
+27
-3
| --- templates/fossil/checkin_detail.html | ||
| +++ templates/fossil/checkin_detail.html | ||
| @@ -10,11 +10,15 @@ | ||
| 10 | 10 | .diff-line-del { background: rgba(239, 68, 68, 0.1); } |
| 11 | 11 | .diff-line-del td:last-child { color: #fca5a5; } |
| 12 | 12 | .diff-line-hunk { background: rgba(96, 165, 250, 0.08); } |
| 13 | 13 | .diff-line-hunk td { color: #93c5fd; font-weight: 500; } |
| 14 | 14 | .diff-line-header td { color: #6b7280; font-weight: 600; } |
| 15 | - .diff-gutter { width: 1%; user-select: none; color: #4b5563; text-align: right; padding: 0 6px; border-right: 1px solid #374151; } | |
| 15 | + .diff-gutter { width: 1%; user-select: none; color: #4b5563; text-align: right; padding: 0 6px; border-right: 1px solid #374151; cursor: pointer; } | |
| 16 | + .diff-gutter:hover { color: #DC394C; } | |
| 17 | + .diff-gutter a { color: inherit; text-decoration: none; display: block; } | |
| 18 | + .line-row:target { background: rgba(220, 57, 76, 0.15) !important; } | |
| 19 | + .line-row:target .diff-gutter { color: #DC394C; font-weight: 600; } | |
| 16 | 20 | </style> |
| 17 | 21 | {% endblock %} |
| 18 | 22 | |
| 19 | 23 | {% block content %} |
| 20 | 24 | <h1 class="text-2xl font-bold text-gray-100 mb-2">{{ project.name }}</h1> |
| @@ -114,15 +118,29 @@ | ||
| 114 | 118 | <p class="p-4 text-sm text-gray-500">Binary file</p> |
| 115 | 119 | {% elif fd.diff_lines %} |
| 116 | 120 | <table class="diff-table"> |
| 117 | 121 | <tbody> |
| 118 | 122 | {% for dl in fd.diff_lines %} |
| 119 | - <tr class="diff-line-{{ dl.type }}"> | |
| 123 | + {% if dl.new_num %} | |
| 124 | + <tr class="diff-line-{{ dl.type }} line-row" id="diff-{{ forloop.parentloop.counter }}-R{{ dl.new_num }}"> | |
| 120 | 125 | <td class="diff-gutter">{{ dl.old_num }}</td> |
| 121 | - <td class="diff-gutter">{{ dl.new_num }}</td> | |
| 126 | + <td class="diff-gutter"><a href="#diff-{{ forloop.parentloop.counter }}-R{{ dl.new_num }}">{{ dl.new_num }}</a></td> | |
| 127 | + <td>{{ dl.text }}</td> | |
| 128 | + </tr> | |
| 129 | + {% elif dl.old_num %} | |
| 130 | + <tr class="diff-line-{{ dl.type }} line-row" id="diff-{{ forloop.parentloop.counter }}-L{{ dl.old_num }}"> | |
| 131 | + <td class="diff-gutter"><a href="#diff-{{ forloop.parentloop.counter }}-L{{ dl.old_num }}">{{ dl.old_num }}</a></td> | |
| 132 | + <td class="diff-gutter"></td> | |
| 133 | + <td>{{ dl.text }}</td> | |
| 134 | + </tr> | |
| 135 | + {% else %} | |
| 136 | + <tr class="diff-line-{{ dl.type }}"> | |
| 137 | + <td class="diff-gutter"></td> | |
| 138 | + <td class="diff-gutter"></td> | |
| 122 | 139 | <td>{{ dl.text }}</td> |
| 123 | 140 | </tr> |
| 141 | + {% endif %} | |
| 124 | 142 | {% endfor %} |
| 125 | 143 | </tbody> |
| 126 | 144 | </table> |
| 127 | 145 | {% else %} |
| 128 | 146 | <p class="p-4 text-sm text-gray-500">No diff available</p> |
| @@ -130,6 +148,12 @@ | ||
| 130 | 148 | </div> |
| 131 | 149 | </div> |
| 132 | 150 | {% endfor %} |
| 133 | 151 | {% endif %} |
| 134 | 152 | </div> |
| 153 | +<script> | |
| 154 | + if (window.location.hash) { | |
| 155 | + const el = document.querySelector(window.location.hash); | |
| 156 | + if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' }); | |
| 157 | + } | |
| 158 | +</script> | |
| 135 | 159 | {% endblock %} |
| 136 | 160 |
| --- templates/fossil/checkin_detail.html | |
| +++ templates/fossil/checkin_detail.html | |
| @@ -10,11 +10,15 @@ | |
| 10 | .diff-line-del { background: rgba(239, 68, 68, 0.1); } |
| 11 | .diff-line-del td:last-child { color: #fca5a5; } |
| 12 | .diff-line-hunk { background: rgba(96, 165, 250, 0.08); } |
| 13 | .diff-line-hunk td { color: #93c5fd; font-weight: 500; } |
| 14 | .diff-line-header td { color: #6b7280; font-weight: 600; } |
| 15 | .diff-gutter { width: 1%; user-select: none; color: #4b5563; text-align: right; padding: 0 6px; border-right: 1px solid #374151; } |
| 16 | </style> |
| 17 | {% endblock %} |
| 18 | |
| 19 | {% block content %} |
| 20 | <h1 class="text-2xl font-bold text-gray-100 mb-2">{{ project.name }}</h1> |
| @@ -114,15 +118,29 @@ | |
| 114 | <p class="p-4 text-sm text-gray-500">Binary file</p> |
| 115 | {% elif fd.diff_lines %} |
| 116 | <table class="diff-table"> |
| 117 | <tbody> |
| 118 | {% for dl in fd.diff_lines %} |
| 119 | <tr class="diff-line-{{ dl.type }}"> |
| 120 | <td class="diff-gutter">{{ dl.old_num }}</td> |
| 121 | <td class="diff-gutter">{{ dl.new_num }}</td> |
| 122 | <td>{{ dl.text }}</td> |
| 123 | </tr> |
| 124 | {% endfor %} |
| 125 | </tbody> |
| 126 | </table> |
| 127 | {% else %} |
| 128 | <p class="p-4 text-sm text-gray-500">No diff available</p> |
| @@ -130,6 +148,12 @@ | |
| 130 | </div> |
| 131 | </div> |
| 132 | {% endfor %} |
| 133 | {% endif %} |
| 134 | </div> |
| 135 | {% endblock %} |
| 136 |
| --- templates/fossil/checkin_detail.html | |
| +++ templates/fossil/checkin_detail.html | |
| @@ -10,11 +10,15 @@ | |
| 10 | .diff-line-del { background: rgba(239, 68, 68, 0.1); } |
| 11 | .diff-line-del td:last-child { color: #fca5a5; } |
| 12 | .diff-line-hunk { background: rgba(96, 165, 250, 0.08); } |
| 13 | .diff-line-hunk td { color: #93c5fd; font-weight: 500; } |
| 14 | .diff-line-header td { color: #6b7280; font-weight: 600; } |
| 15 | .diff-gutter { width: 1%; user-select: none; color: #4b5563; text-align: right; padding: 0 6px; border-right: 1px solid #374151; cursor: pointer; } |
| 16 | .diff-gutter:hover { color: #DC394C; } |
| 17 | .diff-gutter a { color: inherit; text-decoration: none; display: block; } |
| 18 | .line-row:target { background: rgba(220, 57, 76, 0.15) !important; } |
| 19 | .line-row:target .diff-gutter { color: #DC394C; font-weight: 600; } |
| 20 | </style> |
| 21 | {% endblock %} |
| 22 | |
| 23 | {% block content %} |
| 24 | <h1 class="text-2xl font-bold text-gray-100 mb-2">{{ project.name }}</h1> |
| @@ -114,15 +118,29 @@ | |
| 118 | <p class="p-4 text-sm text-gray-500">Binary file</p> |
| 119 | {% elif fd.diff_lines %} |
| 120 | <table class="diff-table"> |
| 121 | <tbody> |
| 122 | {% for dl in fd.diff_lines %} |
| 123 | {% if dl.new_num %} |
| 124 | <tr class="diff-line-{{ dl.type }} line-row" id="diff-{{ forloop.parentloop.counter }}-R{{ dl.new_num }}"> |
| 125 | <td class="diff-gutter">{{ dl.old_num }}</td> |
| 126 | <td class="diff-gutter"><a href="#diff-{{ forloop.parentloop.counter }}-R{{ dl.new_num }}">{{ dl.new_num }}</a></td> |
| 127 | <td>{{ dl.text }}</td> |
| 128 | </tr> |
| 129 | {% elif dl.old_num %} |
| 130 | <tr class="diff-line-{{ dl.type }} line-row" id="diff-{{ forloop.parentloop.counter }}-L{{ dl.old_num }}"> |
| 131 | <td class="diff-gutter"><a href="#diff-{{ forloop.parentloop.counter }}-L{{ dl.old_num }}">{{ dl.old_num }}</a></td> |
| 132 | <td class="diff-gutter"></td> |
| 133 | <td>{{ dl.text }}</td> |
| 134 | </tr> |
| 135 | {% else %} |
| 136 | <tr class="diff-line-{{ dl.type }}"> |
| 137 | <td class="diff-gutter"></td> |
| 138 | <td class="diff-gutter"></td> |
| 139 | <td>{{ dl.text }}</td> |
| 140 | </tr> |
| 141 | {% endif %} |
| 142 | {% endfor %} |
| 143 | </tbody> |
| 144 | </table> |
| 145 | {% else %} |
| 146 | <p class="p-4 text-sm text-gray-500">No diff available</p> |
| @@ -130,6 +148,12 @@ | |
| 148 | </div> |
| 149 | </div> |
| 150 | {% endfor %} |
| 151 | {% endif %} |
| 152 | </div> |
| 153 | <script> |
| 154 | if (window.location.hash) { |
| 155 | const el = document.querySelector(window.location.hash); |
| 156 | if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' }); |
| 157 | } |
| 158 | </script> |
| 159 | {% endblock %} |
| 160 |