Skip to content

Commit 32b4725

Browse files
committed
feat: support multi-line selection with URL parameters
1 parent 8125633 commit 32b4725

File tree

2 files changed

+29
-14
lines changed

2 files changed

+29
-14
lines changed

templates/repo/view_file.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@
108108
{{range $idx, $code := .FileContent}}
109109
{{$line := Eval $idx "+" 1}}
110110
<tr>
111-
<td id="L{{$line}}" class="lines-num"><span id="L{{$line}}" data-line-number="{{$line}}"></span></td>
111+
<td id="L{{$line}}" class="lines-num"><span data-line-number="{{$line}}"></span></td>
112112
{{if $.EscapeStatus.Escaped}}
113113
<td class="lines-escape">{{if (index $.LineEscapeStatus $idx).Escaped}}<button class="toggle-escape-button btn interact-bg" title="{{if (index $.LineEscapeStatus $idx).HasInvisible}}{{ctx.Locale.Tr "repo.invisible_runes_line"}} {{end}}{{if (index $.LineEscapeStatus $idx).HasAmbiguous}}{{ctx.Locale.Tr "repo.ambiguous_runes_line"}}{{end}}"></button>{{end}}</td>
114114
{{end}}

web_src/js/features/repo-code.ts

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ function changeHash(hash: string) {
1414
// it selects the code lines defined by range: `L1-L3` (3 lines) or `L2` (singe line)
1515
function selectRange(range: string): Element {
1616
for (const el of document.querySelectorAll('.code-view tr.active')) el.classList.remove('active');
17-
const elLineNums = document.querySelectorAll(`.code-view td.lines-num span[data-line-number]`);
17+
const elLineNums = document.querySelectorAll(`.code-view td.lines-num[id^="L"]`);
1818

1919
const refInNewIssue = document.querySelector('a.ref-in-new-issue');
2020
const copyPermalink = document.querySelector('a.copy-line-permalink');
@@ -81,11 +81,12 @@ function showLineButton() {
8181
el.remove();
8282
}
8383

84-
// find active row and add button
85-
const tr = document.querySelector('.code-view tr.active');
86-
if (!tr) return;
84+
// Find first active row and add button
85+
const activeRows = document.querySelectorAll('.code-view tr.active');
86+
if (activeRows.length === 0) return;
8787

88-
const td = tr.querySelector('td.lines-num');
88+
const firstActiveRow = activeRows[0];
89+
const td = firstActiveRow.querySelector('td.lines-num');
8990
const btn = document.createElement('button');
9091
btn.classList.add('code-line-button', 'ui', 'basic', 'button');
9192
btn.innerHTML = svg('octicon-kebab-horizontal');
@@ -96,16 +97,30 @@ function showLineButton() {
9697

9798
createTippy(btn, {
9899
theme: 'menu',
99-
trigger: 'click',
100-
hideOnClick: true,
100+
trigger: 'manual', // Use manual trigger
101101
content: menu,
102102
placement: 'right-start',
103103
interactive: true,
104-
onShow: (tippy) => {
105-
tippy.popper.addEventListener('click', () => {
106-
tippy.hide();
107-
}, {once: true});
108-
},
104+
appendTo: () => document.body,
105+
});
106+
107+
// Handle menu button click manually
108+
btn.addEventListener('click', (e) => {
109+
e.stopPropagation();
110+
const tippyInstance = btn._tippy;
111+
if (tippyInstance && tippyInstance.state.isVisible) {
112+
tippyInstance.hide();
113+
} else if (tippyInstance) {
114+
tippyInstance.show();
115+
}
116+
});
117+
118+
// Hide menu when clicking menu items
119+
menu.addEventListener('click', () => {
120+
const tippyInstance = btn._tippy;
121+
if (tippyInstance) {
122+
tippyInstance.hide();
123+
}
109124
});
110125
}
111126

@@ -118,7 +133,7 @@ export function initRepoCodeView() {
118133

119134
// "file code view" and "blame" pages need this "line number button" feature
120135
let selRangeStart: string;
121-
addDelegatedEventListener(document, 'click', '.code-view .lines-num span', (el: HTMLElement, e: KeyboardEvent) => {
136+
addDelegatedEventListener(document, 'click', '.code-view .lines-num', (el: HTMLElement, e: KeyboardEvent) => {
122137
if (!selRangeStart || !e.shiftKey) {
123138
selRangeStart = el.getAttribute('id');
124139
selectRange(selRangeStart);

0 commit comments

Comments
 (0)