Skip to content

Instantly share code, notes, and snippets.

@feynon
Created August 29, 2023 12:35
Show Gist options
  • Save feynon/82e5845eee873590d92e7bb647a4d375 to your computer and use it in GitHub Desktop.
Save feynon/82e5845eee873590d92e7bb647a4d375 to your computer and use it in GitHub Desktop.
hnc
javascript:(function() { const createCommentElement = (comment, depth) => { const commentWrapper = document.createElement('div'); commentWrapper.style.paddingLeft = (depth * 20) + 'px'; commentWrapper.style.marginBottom = '10px'; commentWrapper.style.marginLeft = '10px'; commentWrapper.style.color = '#333'; commentWrapper.style.background = '#f6f6ef'; commentWrapper.style.fontFamily = 'Verdana, Geneva, sans-serif'; commentWrapper.style.fontSize = '14px'; const toggleButton = document.createElement('button'); toggleButton.textContent = '[-]'; toggleButton.style.marginRight = '10px'; toggleButton.style.background = 'none'; toggleButton.style.border = 'none'; toggleButton.style.color = '#888'; toggleButton.style.cursor = 'pointer'; commentWrapper.appendChild(toggleButton); const commentText = document.createElement('span'); const decoded = new DOMParser().parseFromString(comment.text, 'text/html').body.textContent || ''; const author = comment.author || 'Anonymous'; const formattedDate = new Date(comment.created_at).toLocaleString(); const authorElement = document.createElement('i'); authorElement.textContent = author; const dateElement = document.createElement('span'); dateElement.textContent = formattedDate; dateElement.style.color = '#888'; const contentElement = document.createElement('span'); insertTextWithLinks(decoded, contentElement); commentText.appendChild(authorElement); commentText.appendChild(document.createTextNode(' ')); commentText.appendChild(dateElement); commentText.appendChild(document.createElement('br')); commentText.appendChild(contentElement); commentWrapper.appendChild(commentText); const childrenWrapper = document.createElement('div'); childrenWrapper.style.marginLeft = '20px'; childrenWrapper.style.marginTop = '10px'; commentWrapper.appendChild(childrenWrapper); let isCollapsed = false; toggleButton.addEventListener('click', () => { if(isCollapsed) { commentText.style.display = ''; childrenWrapper.style.display = ''; toggleButton.textContent = '[-]'; isCollapsed = false; } else { commentText.style.display = 'none'; childrenWrapper.style.display = 'none'; toggleButton.textContent = '[+]'; isCollapsed = true; } }); return { commentWrapper, childrenWrapper }; }; const addCommentsToSidebar = (comments, depth, sidebarContent) => { for(let c of comments) { if(c.text){ const { commentWrapper, childrenWrapper } = createCommentElement(c, depth); sidebarContent.appendChild(commentWrapper); if (c.children) { addCommentsToSidebar(c.children, depth + 1, childrenWrapper); } } } }; const insertTextWithLinks = (text, contentElement) => { const urlRegex = /(https?:\/\/[^\s]+)/g; let lastIndex = 0; let match; while (match = urlRegex.exec(text)) { if (match.index > lastIndex) { contentElement.appendChild(document.createTextNode(text.slice(lastIndex, match.index))); } const anchor = document.createElement('a'); anchor.href = match[0]; anchor.target = "_blank"; anchor.rel = "noopener noreferrer"; anchor.style.color = "#333"; anchor.style.textDecoration = "underline"; anchor.textContent = match[0]; contentElement.appendChild(anchor); lastIndex = urlRegex.lastIndex; } if (lastIndex < text.length) { contentElement.appendChild(document.createTextNode(text.slice(lastIndex))); } }; const url = %60https://hn.algolia.com/api/v1/search?query=${encodeURIComponent(document.location.href)}&tags=story%60; fetch(url) .then((response) => response.json()) .then((data) => { if(data.hits.length === 0){ alert('This page has not been posted on Hacker News.'); return; } const highestScoringStory = data.hits.reduce((prev, cur) => (prev.points > cur.points) ? prev : cur); const storyId = highestScoringStory.objectID; const commentsUrl = %60https://hn.algolia.com/api/v1/items/${storyId}%60; fetch(commentsUrl) .then((response) => response.json()) .then((data) => { const sidebar = document.createElement('div'); sidebar.className = 'hn-comments-sidebar'; /* Add a unique class name for CSS scoping */ sidebar.innerHTML = %60 <style> .hn-comments-sidebar { position:fixed; right:0; top:0; width:600px; height:100%; background-color:#f6f6ef; overflow-y:auto; padding:1em; z-index:999999; font-family:Verdana, Geneva, sans-serif; font-size:14px; color:#333; } .hn-comments-sidebar a { color:#333; text-decoration:underline; } </style> %60; const sidebarContent = document.createElement('div'); sidebarContent.style.overflowY = 'scroll'; sidebarContent.style.height = '100%'; sidebar.appendChild(sidebarContent); addCommentsToSidebar(data.children, 0, sidebarContent); const dragHandle = document.createElement('div'); dragHandle.style.cssText = 'position:absolute;top:0;left:0;bottom:0;width:10px;background:rgba(0,0,0,0.1);cursor:ew-resize;'; sidebar.appendChild(dragHandle); let isDragging = false; let initialX = 0; let initialWidth = 0; dragHandle.addEventListener('mousedown', (e) => { isDragging = true; initialX = e.clientX; initialWidth = sidebar.offsetWidth; }); window.addEventListener('mousemove', (e) => { if(isDragging) { const offsetX = e.clientX - initialX; const newWidth = Math.max(400, initialWidth - offsetX); sidebar.style.width = newWidth + 'px'; } }); window.addEventListener('mouseup', () => { isDragging = false; }); sidebar.addEventListener('scroll', (e) => { dragHandle.style.top = sidebar.scrollTop + 'px'; }); document.body.appendChild(sidebar); }) .catch((error) => console.error('Error:', error)); }) .catch((error) => console.error('Error:', error));})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment