mirror of
https://github.com/RuoJi6/ARTEX.git
synced 2026-10-27 17:03:49 +08:00
fix: preserve blank lines when copying HTTP packets
This commit is contained in:
1 parent
bd0ba56c82
commit
b9b137dc91
1 file changed
+40
@@ -111,6 +111,40 @@ function HighlightedBody({ body, format }: { body: string; format: BodyFormat })
|
||||
return body;
|
||||
}
|
||||
|
||||
// Empty grid rows have no text, so native selection copying drops their newlines.
|
||||
// Map the selected DOM boundaries back to the raw packet instead.
|
||||
function selectedPacketText(container: HTMLElement, value: string, lines: string[]): string | null {
|
||||
const selection = window.getSelection();
|
||||
if (!selection || selection.isCollapsed || selection.rangeCount !== 1) return null;
|
||||
const range = selection.getRangeAt(0);
|
||||
if (!container.contains(range.startContainer) || !container.contains(range.endContainer)) return null;
|
||||
|
||||
let start: number | null = null;
|
||||
let end: number | null = null;
|
||||
let offset = 0;
|
||||
container.querySelectorAll("[data-line] code").forEach((code, index) => {
|
||||
if (range.intersectsNode(code)) {
|
||||
const selected = document.createRange();
|
||||
selected.selectNodeContents(code);
|
||||
if (range.compareBoundaryPoints(Range.START_TO_START, selected) > 0) {
|
||||
selected.setStart(range.startContainer, range.startOffset);
|
||||
}
|
||||
if (range.compareBoundaryPoints(Range.END_TO_END, selected) < 0) {
|
||||
selected.setEnd(range.endContainer, range.endOffset);
|
||||
}
|
||||
const prefix = document.createRange();
|
||||
prefix.selectNodeContents(code);
|
||||
prefix.setEnd(selected.startContainer, selected.startOffset);
|
||||
start ??= offset + prefix.toString().length;
|
||||
prefix.setEnd(selected.endContainer, selected.endOffset);
|
||||
end = offset + prefix.toString().length;
|
||||
}
|
||||
const lineEnd = offset + lines[index].length;
|
||||
offset = lineEnd + (value[lineEnd] === "\r" ? 2 : 1);
|
||||
});
|
||||
return start !== null && end !== null ? value.slice(start, end) : null;
|
||||
}
|
||||
|
||||
export function HttpCodeBlock({ raw }: { raw: string }) {
|
||||
const [wrapLines, setWrapLines] = React.useState(true);
|
||||
const [copied, setCopied] = React.useState(false);
|
||||
@@ -183,6 +217,12 @@ export function HttpCodeBlock({ raw }: { raw: string }) {
|
||||
aria-readonly="true"
|
||||
tabIndex={0}
|
||||
className="max-h-[calc(100vh-15rem)] min-w-0 overflow-auto bg-background py-3 font-mono text-xs outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring"
|
||||
onCopy={(event) => {
|
||||
const text = selectedPacketText(event.currentTarget, value, lines);
|
||||
if (text === null) return;
|
||||
event.preventDefault();
|
||||
event.clipboardData.setData("text/plain", text);
|
||||
}}
|
||||
onKeyDown={(event) => {
|
||||
if (!(event.ctrlKey || event.metaKey) || event.key.toLowerCase() !== "a") return;
|
||||
event.preventDefault();
|
||||
|
||||
Reference in new issue
Block a user