Skip to content

Commit cfe33b6

Browse files
committed
fix
1 parent 68972a9 commit cfe33b6

File tree

5 files changed

+67
-137
lines changed

5 files changed

+67
-137
lines changed

Diff for: web_src/css/base.css

+1
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,7 @@ input:-webkit-autofill:active,
693693

694694
.ui.dropdown .menu > .header {
695695
font-size: 0.8em;
696+
text-transform: none; /* reset fomantic's "uppercase" */
696697
}
697698

698699
.ui .text.left {

Diff for: web_src/js/features/repo-code.test.ts

-17
This file was deleted.

Diff for: web_src/js/features/repo-code.ts

+57-103
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
1-
import $ from 'jquery';
21
import {svg} from '../svg.ts';
3-
import {invertFileFolding} from './file-fold.ts';
42
import {createTippy} from '../modules/tippy.ts';
53
import {clippie} from 'clippie';
64
import {toAbsoluteUrl} from '../utils.ts';
7-
8-
export const singleAnchorRegex = /^#(L|n)([1-9][0-9]*)$/;
9-
export const rangeAnchorRegex = /^#(L[1-9][0-9]*)-(L[1-9][0-9]*)$/;
5+
import {addDelegatedEventListener} from '../utils/dom.ts';
106

117
function changeHash(hash: string) {
128
if (window.history.pushState) {
@@ -16,20 +12,10 @@ function changeHash(hash: string) {
1612
}
1713
}
1814

19-
function isBlame() {
20-
return Boolean(document.querySelector('div.blame'));
21-
}
15+
function selectRange(range: string): Element {
16+
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]`);
2218

23-
function getLineEls() {
24-
return document.querySelectorAll(`.code-view td.lines-code${isBlame() ? '.blame-code' : ''}`);
25-
}
26-
27-
function selectRange($linesEls, $selectionEndEl, $selectionStartEls?) {
28-
for (const el of $linesEls) {
29-
el.closest('tr').classList.remove('active');
30-
}
31-
32-
// add hashchange to permalink
3319
const refInNewIssue = document.querySelector('a.ref-in-new-issue');
3420
const copyPermalink = document.querySelector('a.copy-line-permalink');
3521
const viewGitBlame = document.querySelector('a.view_git_blame');
@@ -59,37 +45,29 @@ function selectRange($linesEls, $selectionEndEl, $selectionStartEls?) {
5945
copyPermalink.setAttribute('data-url', link);
6046
};
6147

62-
if ($selectionStartEls) {
63-
let a = parseInt($selectionEndEl[0].getAttribute('rel').slice(1));
64-
let b = parseInt($selectionStartEls[0].getAttribute('rel').slice(1));
65-
let c;
66-
if (a !== b) {
67-
if (a > b) {
68-
c = a;
69-
a = b;
70-
b = c;
71-
}
72-
const classes = [];
73-
for (let i = a; i <= b; i++) {
74-
classes.push(`[rel=L${i}]`);
75-
}
76-
$linesEls.filter(classes.join(',')).each(function () {
77-
this.closest('tr').classList.add('active');
78-
});
79-
changeHash(`#L${a}-L${b}`);
80-
81-
updateIssueHref(`L${a}-L${b}`);
82-
updateViewGitBlameFragment(`L${a}-L${b}`);
83-
updateCopyPermalinkUrl(`L${a}-L${b}`);
84-
return;
85-
}
48+
const rangeFields = range ? range.split('-') : [];
49+
const start = rangeFields[0] ?? '';
50+
if (!start) return null;
51+
const stop = rangeFields[1] || start;
52+
53+
let startLineNum = parseInt(start.substring(1));
54+
let stopLineNum = parseInt(stop.substring(1));
55+
if (startLineNum > stopLineNum) {
56+
const tmp = startLineNum;
57+
startLineNum = stopLineNum;
58+
stopLineNum = tmp;
59+
range = `${stop}-${start}`;
8660
}
87-
$selectionEndEl[0].closest('tr').classList.add('active');
88-
changeHash(`#${$selectionEndEl[0].getAttribute('rel')}`);
8961

90-
updateIssueHref($selectionEndEl[0].getAttribute('rel'));
91-
updateViewGitBlameFragment($selectionEndEl[0].getAttribute('rel'));
92-
updateCopyPermalinkUrl($selectionEndEl[0].getAttribute('rel'));
62+
const first = elLineNums[startLineNum - 1] ?? null;
63+
for (let i = startLineNum - 1; i <= stopLineNum - 1 && i < elLineNums.length; i++) {
64+
elLineNums[i].closest('tr').classList.add('active');
65+
}
66+
changeHash(`#${range}`);
67+
updateIssueHref(range);
68+
updateViewGitBlameFragment(range);
69+
updateCopyPermalinkUrl(range);
70+
return first;
9371
}
9472

9573
function showLineButton() {
@@ -103,6 +81,8 @@ function showLineButton() {
10381

10482
// find active row and add button
10583
const tr = document.querySelector('.code-view tr.active');
84+
if (!tr) return;
85+
10686
const td = tr.querySelector('td.lines-num');
10787
const btn = document.createElement('button');
10888
btn.classList.add('code-line-button', 'ui', 'basic', 'button');
@@ -128,62 +108,36 @@ function showLineButton() {
128108
}
129109

130110
export function initRepoCodeView() {
131-
if ($('.code-view .lines-num').length > 0) {
132-
$(document).on('click', '.lines-num span', function (e) {
133-
const linesEls = getLineEls();
134-
const selectedEls = Array.from(linesEls).filter((el) => {
135-
return el.matches(`[rel=${this.getAttribute('id')}]`);
136-
});
137-
138-
let from;
139-
if (e.shiftKey) {
140-
from = Array.from(linesEls).filter((el) => {
141-
return el.closest('tr').classList.contains('active');
142-
});
143-
}
144-
selectRange($(linesEls), $(selectedEls), from ? $(from) : null);
145-
window.getSelection().removeAllRanges();
146-
showLineButton();
147-
});
148-
149-
$(window).on('hashchange', () => {
150-
let m = rangeAnchorRegex.exec(window.location.hash);
151-
const $linesEls = $(getLineEls());
152-
let $first;
153-
if (m) {
154-
$first = $linesEls.filter(`[rel=${m[1]}]`);
155-
if ($first.length) {
156-
selectRange($linesEls, $first, $linesEls.filter(`[rel=${m[2]}]`));
157-
158-
// show code view menu marker (don't show in blame page)
159-
if (!isBlame()) {
160-
showLineButton();
161-
}
162-
163-
$('html, body').scrollTop($first.offset().top - 200);
164-
return;
165-
}
166-
}
167-
m = singleAnchorRegex.exec(window.location.hash);
168-
if (m) {
169-
$first = $linesEls.filter(`[rel=L${m[2]}]`);
170-
if ($first.length) {
171-
selectRange($linesEls, $first);
172-
173-
// show code view menu marker (don't show in blame page)
174-
if (!isBlame()) {
175-
showLineButton();
176-
}
177-
178-
$('html, body').scrollTop($first.offset().top - 200);
179-
}
180-
}
181-
}).trigger('hashchange');
182-
}
183-
$(document).on('click', '.fold-file', ({currentTarget}) => {
184-
invertFileFolding(currentTarget.closest('.file-content'), currentTarget);
111+
if (!document.querySelector('.code-view .lines-num')) return;
112+
113+
let selRangeStart: string;
114+
addDelegatedEventListener(document, 'click', '.lines-num span', (el: HTMLElement, e: KeyboardEvent) => {
115+
if (!selRangeStart || !e.shiftKey) {
116+
selRangeStart = el.getAttribute('id');
117+
selectRange(selRangeStart);
118+
} else {
119+
const selRangeStop = el.getAttribute('id');
120+
selectRange(`${selRangeStart}-${selRangeStop}`);
121+
}
122+
window.getSelection().removeAllRanges();
123+
showLineButton();
185124
});
186-
$(document).on('click', '.copy-line-permalink', async ({currentTarget}) => {
187-
await clippie(toAbsoluteUrl(currentTarget.getAttribute('data-url')));
125+
126+
const onHashChange = () => {
127+
if (!window.location.hash) return;
128+
const range = window.location.hash.substring(1);
129+
const first = selectRange(range);
130+
if (first) {
131+
// set scrollRestoration to 'manual' when there is a hash in url, so that the scroll position will not be remembered after refreshing
132+
if (window.history.scrollRestoration !== 'manual') window.history.scrollRestoration = 'manual';
133+
first.scrollIntoView({block: 'start'});
134+
showLineButton();
135+
}
136+
};
137+
onHashChange();
138+
window.addEventListener('hashchange', onHashChange);
139+
140+
addDelegatedEventListener(document, 'click', '.copy-line-permalink', (el) => {
141+
clippie(toAbsoluteUrl(el.getAttribute('data-url')));
188142
});
189143
}

Diff for: web_src/js/features/repo-diff.ts

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
import {POST, GET} from '../modules/fetch.ts';
2020
import {fomanticQuery} from '../modules/fomantic/base.ts';
2121
import {createTippy} from '../modules/tippy.ts';
22+
import {invertFileFolding} from './file-fold.ts';
2223

2324
const {pageData, i18n} = window.config;
2425

@@ -244,4 +245,8 @@ export function initRepoDiffView() {
244245
initRepoDiffFileViewToggle();
245246
initViewedCheckboxListenerFor();
246247
initExpandAndCollapseFilesButton();
248+
249+
addDelegatedEventListener(document, 'click', '.fold-file', (el) => {
250+
invertFileFolding(el.closest('.file-content'), el);
251+
});
247252
}

Diff for: web_src/js/features/repo-issue.ts

+4-17
Original file line numberDiff line numberDiff line change
@@ -373,38 +373,25 @@ export async function handleReply(el) {
373373

374374
export function initRepoPullRequestReview() {
375375
if (window.location.hash && window.location.hash.startsWith('#issuecomment-')) {
376-
// set scrollRestoration to 'manual' when there is a hash in url, so that the scroll position will not be remembered after refreshing
377-
if (window.history.scrollRestoration !== 'manual') {
378-
window.history.scrollRestoration = 'manual';
379-
}
380376
const commentDiv = document.querySelector(window.location.hash);
381377
if (commentDiv) {
382378
// get the name of the parent id
383379
const groupID = commentDiv.closest('div[id^="code-comments-"]')?.getAttribute('id');
384380
if (groupID && groupID.startsWith('code-comments-')) {
385381
const id = groupID.slice(14);
386382
const ancestorDiffBox = commentDiv.closest('.diff-file-box');
387-
// on pages like conversation, there is no diff header
388-
const diffHeader = ancestorDiffBox?.querySelector('.diff-file-header');
389-
390-
// offset is for scrolling
391-
let offset = 30;
392-
if (diffHeader) {
393-
offset += $('.diff-detail-box').outerHeight() + $(diffHeader).outerHeight();
394-
}
395383

396384
hideElem(`#show-outdated-${id}`);
397385
showElem(`#code-comments-${id}, #code-preview-${id}, #hide-outdated-${id}`);
398386
// if the comment box is folded, expand it
399387
if (ancestorDiffBox?.getAttribute('data-folded') === 'true') {
400388
setFileFolding(ancestorDiffBox, ancestorDiffBox.querySelector('.fold-file'), false);
401389
}
402-
403-
window.scrollTo({
404-
top: $(commentDiv).offset().top - offset,
405-
behavior: 'instant',
406-
});
407390
}
391+
// set scrollRestoration to 'manual' when there is a hash in url, so that the scroll position will not be remembered after refreshing
392+
if (window.history.scrollRestoration !== 'manual') window.history.scrollRestoration = 'manual';
393+
// wait for a while because some elements (eg: image, editor, etc.) may change the viewport's height.
394+
setTimeout(() => commentDiv.scrollIntoView({block: 'start'}), 100);
408395
}
409396
}
410397

0 commit comments

Comments
 (0)