| 
									
										
										
										
											2022-01-28 13:00:11 -08:00
										 |  |  | import $ from 'jquery'; | 
					
						
							| 
									
										
										
										
											2021-10-17 01:28:04 +08:00
										 |  |  | import {svg} from '../svg.js'; | 
					
						
							| 
									
										
										
										
											2022-05-07 20:28:10 +02:00
										 |  |  | import {invertFileFolding} from './file-fold.js'; | 
					
						
							| 
									
										
										
										
											2022-11-04 21:33:50 +02:00
										 |  |  | import {createTippy, showTemporaryTooltip} from '../modules/tippy.js'; | 
					
						
							| 
									
										
										
										
											2022-08-09 14:37:34 +02:00
										 |  |  | import {copyToClipboard} from './clipboard.js'; | 
					
						
							| 
									
										
										
										
											2021-10-17 01:28:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-04 21:33:50 +02:00
										 |  |  | const {i18n} = window.config; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-17 01:28:04 +08:00
										 |  |  | function changeHash(hash) { | 
					
						
							|  |  |  |   if (window.history.pushState) { | 
					
						
							|  |  |  |     window.history.pushState(null, null, hash); | 
					
						
							|  |  |  |   } else { | 
					
						
							|  |  |  |     window.location.hash = hash; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function selectRange($list, $select, $from) { | 
					
						
							|  |  |  |   $list.removeClass('active'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // add hashchange to permalink
 | 
					
						
							|  |  |  |   const $issue = $('a.ref-in-new-issue'); | 
					
						
							|  |  |  |   const $copyPermalink = $('a.copy-line-permalink'); | 
					
						
							| 
									
										
										
										
											2022-04-26 18:54:40 +08:00
										 |  |  |   const $viewGitBlame = $('a.view_git_blame'); | 
					
						
							| 
									
										
										
										
											2021-10-17 01:28:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-12 06:00:24 +01:00
										 |  |  |   const updateIssueHref = function (anchor) { | 
					
						
							|  |  |  |     if ($issue.length === 0) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-10-17 01:28:04 +08:00
										 |  |  |     let href = $issue.attr('href'); | 
					
						
							|  |  |  |     href = `${href.replace(/%23L\d+$|%23L\d+-L\d+$/, '')}%23${anchor}`; | 
					
						
							|  |  |  |     $issue.attr('href', href); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-26 18:54:40 +08:00
										 |  |  |   const updateViewGitBlameFragment = function (anchor) { | 
					
						
							|  |  |  |     if ($viewGitBlame.length === 0) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     let href = $viewGitBlame.attr('href'); | 
					
						
							|  |  |  |     href = `${href.replace(/#L\d+$|#L\d+-L\d+$/, '')}`; | 
					
						
							|  |  |  |     if (anchor.length !== 0) { | 
					
						
							|  |  |  |       href = `${href}#${anchor}`; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     $viewGitBlame.attr('href', href); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-09 14:37:34 +02:00
										 |  |  |   const updateCopyPermalinkUrl = function(anchor) { | 
					
						
							| 
									
										
										
										
											2022-04-26 18:54:40 +08:00
										 |  |  |     if ($copyPermalink.length === 0) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-08-09 14:37:34 +02:00
										 |  |  |     let link = $copyPermalink.attr('data-url'); | 
					
						
							| 
									
										
										
										
											2021-10-17 01:28:04 +08:00
										 |  |  |     link = `${link.replace(/#L\d+$|#L\d+-L\d+$/, '')}#${anchor}`; | 
					
						
							| 
									
										
										
										
											2022-08-09 14:37:34 +02:00
										 |  |  |     $copyPermalink.attr('data-url', link); | 
					
						
							| 
									
										
										
										
											2021-10-17 01:28:04 +08:00
										 |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if ($from) { | 
					
						
							| 
									
										
										
										
											2022-02-18 07:50:36 +01:00
										 |  |  |     let a = parseInt($select.attr('rel').slice(1)); | 
					
						
							|  |  |  |     let b = parseInt($from.attr('rel').slice(1)); | 
					
						
							| 
									
										
										
										
											2021-10-17 01:28:04 +08:00
										 |  |  |     let c; | 
					
						
							|  |  |  |     if (a !== b) { | 
					
						
							|  |  |  |       if (a > b) { | 
					
						
							|  |  |  |         c = a; | 
					
						
							|  |  |  |         a = b; | 
					
						
							|  |  |  |         b = c; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       const classes = []; | 
					
						
							|  |  |  |       for (let i = a; i <= b; i++) { | 
					
						
							|  |  |  |         classes.push(`[rel=L${i}]`); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       $list.filter(classes.join(',')).addClass('active'); | 
					
						
							|  |  |  |       changeHash(`#L${a}-L${b}`); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       updateIssueHref(`L${a}-L${b}`); | 
					
						
							| 
									
										
										
										
											2022-04-26 18:54:40 +08:00
										 |  |  |       updateViewGitBlameFragment(`L${a}-L${b}`); | 
					
						
							| 
									
										
										
										
											2022-08-09 14:37:34 +02:00
										 |  |  |       updateCopyPermalinkUrl(`L${a}-L${b}`); | 
					
						
							| 
									
										
										
										
											2021-10-17 01:28:04 +08:00
										 |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   $select.addClass('active'); | 
					
						
							|  |  |  |   changeHash(`#${$select.attr('rel')}`); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   updateIssueHref($select.attr('rel')); | 
					
						
							| 
									
										
										
										
											2022-04-26 18:54:40 +08:00
										 |  |  |   updateViewGitBlameFragment($select.attr('rel')); | 
					
						
							| 
									
										
										
										
											2022-08-09 14:37:34 +02:00
										 |  |  |   updateCopyPermalinkUrl($select.attr('rel')); | 
					
						
							| 
									
										
										
										
											2021-10-17 01:28:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function showLineButton() { | 
					
						
							| 
									
										
										
										
											2022-08-09 14:37:34 +02:00
										 |  |  |   const menu = document.querySelector('.code-line-menu'); | 
					
						
							|  |  |  |   if (!menu) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // remove all other line buttons
 | 
					
						
							|  |  |  |   for (const el of document.querySelectorAll('.code-line-button')) { | 
					
						
							|  |  |  |     el.remove(); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // find active row and add button
 | 
					
						
							|  |  |  |   const tr = document.querySelector('.code-view td.lines-code.active').closest('tr'); | 
					
						
							|  |  |  |   const td = tr.querySelector('td'); | 
					
						
							|  |  |  |   const btn = document.createElement('button'); | 
					
						
							|  |  |  |   btn.classList.add('code-line-button'); | 
					
						
							|  |  |  |   btn.innerHTML = svg('octicon-kebab-horizontal'); | 
					
						
							|  |  |  |   td.prepend(btn); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // put a copy of the menu back into DOM for the next click
 | 
					
						
							|  |  |  |   btn.closest('.code-view').appendChild(menu.cloneNode(true)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   createTippy(btn, { | 
					
						
							|  |  |  |     trigger: 'click', | 
					
						
							|  |  |  |     content: menu, | 
					
						
							|  |  |  |     placement: 'right-start', | 
					
						
							|  |  |  |     role: 'menu', | 
					
						
							|  |  |  |     interactive: 'true', | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2021-10-17 01:28:04 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-04 21:33:50 +02:00
										 |  |  | function initCopyFileContent() { | 
					
						
							|  |  |  |   // get raw text for copy content button, at the moment, only one button (and one related file content) is supported.
 | 
					
						
							|  |  |  |   const copyFileContent = document.querySelector('#copy-file-content'); | 
					
						
							|  |  |  |   if (!copyFileContent) return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   copyFileContent.addEventListener('click', async () => { | 
					
						
							|  |  |  |     const text = Array.from(document.querySelectorAll('.file-view .lines-code')).map((el) => el.textContent).join(''); | 
					
						
							|  |  |  |     const success = await copyToClipboard(text); | 
					
						
							|  |  |  |     showTemporaryTooltip(copyFileContent, success ? i18n.copy_success : i18n.copy_error); | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-17 01:28:04 +08:00
										 |  |  | export function initRepoCodeView() { | 
					
						
							|  |  |  |   if ($('.code-view .lines-num').length > 0) { | 
					
						
							|  |  |  |     $(document).on('click', '.lines-num span', function (e) { | 
					
						
							|  |  |  |       const $select = $(this); | 
					
						
							|  |  |  |       let $list; | 
					
						
							|  |  |  |       if ($('div.blame').length) { | 
					
						
							|  |  |  |         $list = $('.code-view td.lines-code.blame-code'); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         $list = $('.code-view td.lines-code'); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       selectRange($list, $list.filter(`[rel=${$select.attr('id')}]`), (e.shiftKey ? $list.filter('.active').eq(0) : null)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (window.getSelection) { | 
					
						
							|  |  |  |         window.getSelection().removeAllRanges(); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         document.selection.empty(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // show code view menu marker (don't show in blame page)
 | 
					
						
							|  |  |  |       if ($('div.blame').length === 0) { | 
					
						
							|  |  |  |         showLineButton(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     $(window).on('hashchange', () => { | 
					
						
							|  |  |  |       let m = window.location.hash.match(/^#(L\d+)-(L\d+)$/); | 
					
						
							|  |  |  |       let $list; | 
					
						
							|  |  |  |       if ($('div.blame').length) { | 
					
						
							|  |  |  |         $list = $('.code-view td.lines-code.blame-code'); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         $list = $('.code-view td.lines-code'); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       let $first; | 
					
						
							|  |  |  |       if (m) { | 
					
						
							|  |  |  |         $first = $list.filter(`[rel=${m[1]}]`); | 
					
						
							|  |  |  |         selectRange($list, $first, $list.filter(`[rel=${m[2]}]`)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // show code view menu marker (don't show in blame page)
 | 
					
						
							|  |  |  |         if ($('div.blame').length === 0) { | 
					
						
							|  |  |  |           showLineButton(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $('html, body').scrollTop($first.offset().top - 200); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       m = window.location.hash.match(/^#(L|n)(\d+)$/); | 
					
						
							|  |  |  |       if (m) { | 
					
						
							|  |  |  |         $first = $list.filter(`[rel=L${m[2]}]`); | 
					
						
							|  |  |  |         selectRange($list, $first); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // show code view menu marker (don't show in blame page)
 | 
					
						
							|  |  |  |         if ($('div.blame').length === 0) { | 
					
						
							|  |  |  |           showLineButton(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $('html, body').scrollTop($first.offset().top - 200); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }).trigger('hashchange'); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   $(document).on('click', '.fold-file', ({currentTarget}) => { | 
					
						
							| 
									
										
										
										
											2022-05-07 20:28:10 +02:00
										 |  |  |     invertFileFolding(currentTarget.closest('.file-content'), currentTarget); | 
					
						
							| 
									
										
										
										
											2021-10-17 01:28:04 +08:00
										 |  |  |   }); | 
					
						
							|  |  |  |   $(document).on('click', '.blob-excerpt', async ({currentTarget}) => { | 
					
						
							| 
									
										
										
										
											2021-11-22 09:19:01 +01:00
										 |  |  |     const url = currentTarget.getAttribute('data-url'); | 
					
						
							|  |  |  |     const query = currentTarget.getAttribute('data-query'); | 
					
						
							|  |  |  |     const anchor = currentTarget.getAttribute('data-anchor'); | 
					
						
							| 
									
										
										
										
											2021-10-17 01:28:04 +08:00
										 |  |  |     if (!url) return; | 
					
						
							|  |  |  |     const blob = await $.get(`${url}?${query}&anchor=${anchor}`); | 
					
						
							|  |  |  |     currentTarget.closest('tr').outerHTML = blob; | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2022-08-09 14:37:34 +02:00
										 |  |  |   $(document).on('click', '.copy-line-permalink', async (e) => { | 
					
						
							|  |  |  |     const success = await copyToClipboard(e.currentTarget.getAttribute('data-url')); | 
					
						
							|  |  |  |     if (!success) return; | 
					
						
							|  |  |  |     document.querySelector('.code-line-button')?._tippy?.hide(); | 
					
						
							|  |  |  |   }); | 
					
						
							| 
									
										
										
										
											2022-11-04 21:33:50 +02:00
										 |  |  |   initCopyFileContent(); | 
					
						
							| 
									
										
										
										
											2021-10-17 01:28:04 +08:00
										 |  |  | } |