You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

repo-code.js 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. import {svg} from '../svg.js';
  2. function changeHash(hash) {
  3. if (window.history.pushState) {
  4. window.history.pushState(null, null, hash);
  5. } else {
  6. window.location.hash = hash;
  7. }
  8. }
  9. function selectRange($list, $select, $from) {
  10. $list.removeClass('active');
  11. // add hashchange to permalink
  12. const $issue = $('a.ref-in-new-issue');
  13. const $copyPermalink = $('a.copy-line-permalink');
  14. if ($issue.length === 0 || $copyPermalink.length === 0) {
  15. return;
  16. }
  17. const updateIssueHref = function(anchor) {
  18. let href = $issue.attr('href');
  19. href = `${href.replace(/%23L\d+$|%23L\d+-L\d+$/, '')}%23${anchor}`;
  20. $issue.attr('href', href);
  21. };
  22. const updateCopyPermalinkHref = function(anchor) {
  23. let link = $copyPermalink.attr('data-clipboard-text');
  24. link = `${link.replace(/#L\d+$|#L\d+-L\d+$/, '')}#${anchor}`;
  25. $copyPermalink.attr('data-clipboard-text', link);
  26. };
  27. if ($from) {
  28. let a = parseInt($select.attr('rel').substr(1));
  29. let b = parseInt($from.attr('rel').substr(1));
  30. let c;
  31. if (a !== b) {
  32. if (a > b) {
  33. c = a;
  34. a = b;
  35. b = c;
  36. }
  37. const classes = [];
  38. for (let i = a; i <= b; i++) {
  39. classes.push(`[rel=L${i}]`);
  40. }
  41. $list.filter(classes.join(',')).addClass('active');
  42. changeHash(`#L${a}-L${b}`);
  43. updateIssueHref(`L${a}-L${b}`);
  44. updateCopyPermalinkHref(`L${a}-L${b}`);
  45. return;
  46. }
  47. }
  48. $select.addClass('active');
  49. changeHash(`#${$select.attr('rel')}`);
  50. updateIssueHref($select.attr('rel'));
  51. updateCopyPermalinkHref($select.attr('rel'));
  52. }
  53. function showLineButton() {
  54. if ($('.code-line-menu').length === 0) return;
  55. $('.code-line-button').remove();
  56. $('.code-view td.lines-code.active').closest('tr').find('td:eq(0)').first().prepend(
  57. $(`<button class="code-line-button">${svg('octicon-kebab-horizontal')}</button>`)
  58. );
  59. $('.code-line-menu').appendTo($('.code-view'));
  60. $('.code-line-button').popup({popup: $('.code-line-menu'), on: 'click'});
  61. }
  62. export function initRepoCodeView() {
  63. if ($('.code-view .lines-num').length > 0) {
  64. $(document).on('click', '.lines-num span', function (e) {
  65. const $select = $(this);
  66. let $list;
  67. if ($('div.blame').length) {
  68. $list = $('.code-view td.lines-code.blame-code');
  69. } else {
  70. $list = $('.code-view td.lines-code');
  71. }
  72. selectRange($list, $list.filter(`[rel=${$select.attr('id')}]`), (e.shiftKey ? $list.filter('.active').eq(0) : null));
  73. if (window.getSelection) {
  74. window.getSelection().removeAllRanges();
  75. } else {
  76. document.selection.empty();
  77. }
  78. // show code view menu marker (don't show in blame page)
  79. if ($('div.blame').length === 0) {
  80. showLineButton();
  81. }
  82. });
  83. $(window).on('hashchange', () => {
  84. let m = window.location.hash.match(/^#(L\d+)-(L\d+)$/);
  85. let $list;
  86. if ($('div.blame').length) {
  87. $list = $('.code-view td.lines-code.blame-code');
  88. } else {
  89. $list = $('.code-view td.lines-code');
  90. }
  91. let $first;
  92. if (m) {
  93. $first = $list.filter(`[rel=${m[1]}]`);
  94. selectRange($list, $first, $list.filter(`[rel=${m[2]}]`));
  95. // show code view menu marker (don't show in blame page)
  96. if ($('div.blame').length === 0) {
  97. showLineButton();
  98. }
  99. $('html, body').scrollTop($first.offset().top - 200);
  100. return;
  101. }
  102. m = window.location.hash.match(/^#(L|n)(\d+)$/);
  103. if (m) {
  104. $first = $list.filter(`[rel=L${m[2]}]`);
  105. selectRange($list, $first);
  106. // show code view menu marker (don't show in blame page)
  107. if ($('div.blame').length === 0) {
  108. showLineButton();
  109. }
  110. $('html, body').scrollTop($first.offset().top - 200);
  111. }
  112. }).trigger('hashchange');
  113. }
  114. $(document).on('click', '.fold-file', ({currentTarget}) => {
  115. const box = currentTarget.closest('.file-content');
  116. const folded = box.getAttribute('data-folded') !== 'true';
  117. currentTarget.innerHTML = svg(`octicon-chevron-${folded ? 'right' : 'down'}`, 18);
  118. box.setAttribute('data-folded', String(folded));
  119. });
  120. $(document).on('click', '.blob-excerpt', async ({currentTarget}) => {
  121. const url = currentTarget.getAttribute('data-url');
  122. const query = currentTarget.getAttribute('data-query');
  123. const anchor = currentTarget.getAttribute('data-anchor');
  124. if (!url) return;
  125. const blob = await $.get(`${url}?${query}&anchor=${anchor}`);
  126. currentTarget.closest('tr').outerHTML = blob;
  127. });
  128. }