forked from tangled.org/core
this repo has no description

appview: support selecting multiple lines in blob

Signed-off-by: Naomi Roberts <mia@naomieow.xyz>

Changed files
+96 -7
appview
pages
templates
+90
appview/pages/templates/fragments/multiline-select.html
···
+
{{ define "fragments/multiline-select" }}
+
<script>
+
function highlight(scroll = false) {
+
document.querySelectorAll(".hl").forEach(el => {
+
el.classList.remove("hl");
+
});
+
+
const hash = window.location.hash;
+
if (!hash || !hash.startsWith("#L")) {
+
return;
+
}
+
+
const rangeStr = hash.substring(2);
+
const parts = rangeStr.split("-");
+
let startLine, endLine;
+
+
if (parts.length === 2) {
+
startLine = parseInt(parts[0], 10);
+
endLine = parseInt(parts[1], 10);
+
} else {
+
startLine = parseInt(parts[0], 10);
+
endLine = startLine;
+
}
+
+
if (isNaN(startLine) || isNaN(endLine)) {
+
console.log("nan");
+
console.log(startLine);
+
console.log(endLine);
+
return;
+
}
+
+
let target = null;
+
+
for (let i = startLine; i<= endLine; i++) {
+
const idEl = document.getElementById(`L${i}`);
+
if (idEl) {
+
const el = idEl.closest(".line");
+
if (el) {
+
el.classList.add("hl");
+
target = el;
+
}
+
}
+
}
+
+
if (scroll && target) {
+
target.scrollIntoView({
+
behavior: "smooth",
+
block: "center",
+
});
+
}
+
}
+
+
document.addEventListener("DOMContentLoaded", () => {
+
console.log("DOMContentLoaded");
+
highlight(true);
+
});
+
window.addEventListener("hashchange", () => {
+
console.log("hashchange");
+
highlight();
+
});
+
window.addEventListener("popstate", () => {
+
console.log("popstate");
+
highlight();
+
});
+
+
const lineNumbers = document.querySelectorAll('a[href^="#L"');
+
let startLine = null;
+
+
lineNumbers.forEach(el => {
+
el.addEventListener("click", (event) => {
+
event.preventDefault();
+
const currentLine = parseInt(el.href.split("#L")[1]);
+
+
if (event.shiftKey && startLine !== null) {
+
const endLine = currentLine;
+
const min = Math.min(startLine, endLine);
+
const max = Math.max(startLine, endLine);
+
const newHash = `#L${min}-${max}`;
+
history.pushState(null, '', newHash);
+
} else {
+
const newHash = `#L${currentLine}`;
+
history.pushState(null, '', newHash);
+
startLine = currentLine;
+
}
+
+
highlight();
+
});
+
});
+
</script>
+
{{ end }}
+1
appview/pages/templates/repo/blob.html
···
{{ end }}
</div>
{{ end }}
+
{{ template "fragments/multiline-select" }}
{{ end }}
+3 -2
appview/pages/templates/strings/string.html
···
hx-boost="true"
href="/strings/{{ .String.Did }}/{{ .String.Rkey }}/edit">
{{ i "pencil" "size-4" }}
-
<span class="hidden md:inline">edit</span>
+
<span class="hidden md:inline">edit</span>
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</a>
<button
···
hx-confirm="Are you sure you want to delete the string `{{ .String.Filename }}`?"
>
{{ i "trash-2" "size-4" }}
-
<span class="hidden md:inline">delete</span>
+
<span class="hidden md:inline">delete</span>
{{ i "loader-circle" "w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
</button>
</div>
···
<div id="blob-contents" class="whitespace-pre peer-target:bg-yellow-200 dark:peer-target:bg-yellow-900">{{ .String.Contents | escapeHtml }}</div>
{{ end }}
</div>
+
{{ template "fragments/multiline-select" }}
</section>
{{ end }}
+2 -5
input.css
···
}
/* LineHighlight */
.chroma .hl {
-
background-color: #bcc0cc;
+
@apply bg-amber-400/30 dark:bg-amber-500/20;
}
+
/* LineNumbersTable */
.chroma .lnt {
white-space: pre;
···
text-decoration: underline;
}
}
-
-
.chroma .line:has(.ln:target) {
-
@apply bg-amber-400/30 dark:bg-amber-500/20;
-
}