Warning: fopen(/www/sites/update.greasyfork.icu/index/store/forever/c7367fb39009740d5df0c9da06c3ee85.js): failed to open stream: No space left on device in /www/sites/update.greasyfork.icu/index/scriptControl.php on line 65
// ==UserScript== // @name Refined GitHub Comments // @license MIT // @homepageURL https://github.com/bluwy/refined-github-comments // @supportURL https://github.com/bluwy/refined-github-comments // @namespace https://greasyfork.org/en/scripts/465056-refined-github-comments // @version 0.1.2 // @description Remove clutter in the comments view // @author Bjorn Lu // @match https://github.com/** // @icon https://www.google.com/s2/favicons?sz=64&domain=github.com // @grant none // @downloadURL none // ==/UserScript== // common bots that i already know what they do const authorsToMinimize = [ 'changeset-bot', 'codeflowapp', ] // common comments that don't really add value const commentMatchToMinimize = [ /^![a-z]/, // commands that start with ! /^\/[a-z]/, // commands that start with / /^> root@0.0.0/, // astro preview release bot ] ;(function () { 'use strict' run() // listen to github page loaded event document.addEventListener('pjax:end', () => run()) document.addEventListener('turbo:render', () => run()) })() function run() { const allTimelineItem = document.querySelectorAll('.js-timeline-item') const seenComments = [] allTimelineItem.forEach((timelineItem) => { minimizeComment(timelineItem) minimizeBlockquote(timelineItem, seenComments) }) } // test urls: // https://github.com/withastro/astro/pull/6845 /** * @param {HTMLElement} timelineItem */ function minimizeComment(timelineItem) { // things can happen twice in github for some reason if (timelineItem.querySelector('.refined-github-comments-toggle')) return const header = timelineItem.querySelector('.timeline-comment-header') if (!header) return const headerName = header.querySelector('a.author') if (!headerName) return const commentBody = timelineItem.querySelector('.comment-body') if (!commentBody) return const commentBodyText = commentBody.innerText.trim() // minimize the comment if ( authorsToMinimize.includes(headerName.innerText) || commentMatchToMinimize.some((match) => match.test(commentBodyText)) ) { const commentContent = timelineItem.querySelector('.edit-comment-hide') if (!commentContent) return const commentActions = timelineItem.querySelector('.timeline-comment-actions') if (!commentActions) return const headerH3 = header.querySelector('h3') if (!headerH3) return const headerDiv = headerH3.querySelector('div') if (!headerDiv) return // hide comment header.style.borderBottom = 'none' commentContent.style.display = 'none' // add comment excerpt const excerpt = document.createElement('span') excerpt.setAttribute('class', 'text-fg-muted text-normal text-italic css-truncate css-truncate-overflow mr-2') excerpt.innerHTML = commentBodyText.slice(0, 100) excerpt.style.opacity = '0.5' headerH3.classList.add('css-truncate') headerH3.classList.add('css-truncate-overflow') headerDiv.appendChild(excerpt) // add toggle button const toggleBtn = toggleComment((isShow) => { if (isShow) { header.style.borderBottom = '' commentContent.style.display = '' excerpt.style.display = 'none' } else { header.style.borderBottom = 'none' commentContent.style.display = 'none' excerpt.style.display = '' } }) commentActions.prepend(toggleBtn) } } // test urls: // https://github.com/bluwy/refined-github-comments/issues/1 // https://github.com/sveltejs/svelte/issues/2323 // https://github.com/pnpm/pnpm/issues/6463 /** * @param {HTMLElement} timelineItem * @param {{ text: string, id: string, author: string }[]} seenComments */ function minimizeBlockquote(timelineItem, seenComments) { const commentBody = timelineItem.querySelector('.comment-body') if (!commentBody) return const commentId = timelineItem.querySelector('.timeline-comment-group')?.id if (!commentId) return const commentAuthor = timelineItem.querySelector('.timeline-comment-header a.author')?.innerText if (!commentAuthor) return const commentText = commentBody.innerText.trim().replace(/\s+/g, ' ') // bail early in first comment and if comment is already checked before if (seenComments.length === 0 || commentBody.querySelector('.refined-github-comments-reply-text')) { seenComments.push({ text: commentText, id: commentId, author: commentAuthor }) return } const blockquotes = commentBody.querySelectorAll(':scope > blockquote') for (const blockquote of blockquotes) { const blockquoteText = blockquote.innerText.trim().replace(/\s+/g, ' ') const dupIndex = seenComments.findIndex((comment) => comment.text === blockquoteText) if (dupIndex >= 0) { const dup = seenComments[dupIndex] // if replying to the one above, always minimize it if (dupIndex === seenComments.length - 1) { // use span.js-clear so github would remove this summary when re-quoting this reply, // add nbsp so that the summary tag has some content, that the details would also // get copied when re-quoting too. const summary = `\ Replying to @${dup.author} above entirely  ` blockquote.innerHTML = `
${summary}${blockquote.innerHTML}
` } // if replying to a long comment, or a comment with code, always minimize it else if (blockquoteText.length > 200 || blockquote.querySelector('pre')) { // use span.js-clear so github would remove this summary when re-quoting this reply, // add nbsp so that the summary tag has some content, that the details would also // get copied when re-quoting too. const summary = `\ Replying to @${dup.author}'s comment entirely  ` blockquote.innerHTML = `
${summary}${blockquote.innerHTML}
` } // otherwise, just add a hint so we don't have to navigate away a short sentence else { // use span.js-clear so github would remove this hint when re-quoting this reply const hint = `\ Replying to @${dup.author}'s comment entirely ` blockquote.innerHTML = `${hint}${blockquote.innerHTML}` } continue } const partialDupIndex = seenComments.findIndex((comment) => comment.text.includes(blockquoteText)) if (partialDupIndex >= 0) { const dup = seenComments[partialDupIndex] // get first four words and last four words, craft a text fragment to highlight const splitted = blockquoteText.split(' ') const textFragment = splitted.length < 9 ? `#:~:text=${encodeURIComponent(blockquoteText)}` : `#:~:text=${encodeURIComponent(splitted.slice(0, 4).join(' '))},${encodeURIComponent(splitted.slice(-4).join(' '))}` // if replying to the one above, prepend hint if (partialDupIndex === seenComments.length - 1) { // use span.js-clear so github would remove this hint when re-quoting this reply const hint = `\ Replying to @${dup.author} above partially (view original quote) ` blockquote.innerHTML = `${hint}${blockquote.innerHTML}` } // prepend generic hint else { // use span.js-clear so github would remove this hint when re-quoting this reply const hint = `\ Replying to @${dup.author}'s comment partially (view original quote) ` blockquote.innerHTML = `${hint}${blockquote.innerHTML}` } } } seenComments.push({ text: commentText, id: commentId, author: commentAuthor }) } // create the toggle comment like github does when you hide a comment function toggleComment(onClick) { const btn = document.createElement('button') // copied from github hidden comment style btn.innerHTML = `
Show comment
` const showNode = btn.querySelector('div:nth-child(1)') const hideNode = btn.querySelector('div:nth-child(2)') let isShow = false btn.setAttribute('type', 'button') btn.setAttribute('class', 'refined-github-comments-toggle timeline-comment-action btn-link') btn.style.marginTop = '2px' btn.style.marginRight = '4px' btn.addEventListener('click', () => { isShow = !isShow if (isShow) { showNode.style.display = 'none' hideNode.style.display = '' } else { showNode.style.display = '' hideNode.style.display = 'none' } onClick(isShow) }) return btn }