this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Further polish hashtag stuffing logic

+43 -27
+4 -2
README.md
··· 78 78 79 79 ![Hashtag stuffing collapsing](readme-assets/hashtag-stuffing-collapsing.jpg) 80 80 81 - - Any paragraphs, except the first one, with more than 3 hashtags will be collapsed. 81 + - First paragraph of post content with more than 3 hashtags will be collapsed to max 3 lines. 82 + - Subsequent paragraphs after first paragraph with more than 3 hashtags will be collapsed to 1 line. 83 + - Adjacent paragraphs with more than 1 hashtag after collapsed paragraphs will be collapsed to 1 line. 82 84 - If there are text around or between the hashtags, they will not be collapsed. 83 - - Collapsed hashtags will be a single line with `...` at the end. 85 + - Collapsed hashtags will be appended with `...` at the end. 84 86 - They are also slightly faded out to reduce visual noise. 85 87 - Opening the post view will reveal the hashtags uncollapsed. 86 88
+39 -25
src/utils/enhance-content.js
··· 174 174 // ================ 175 175 // Get the <p> that contains a lot of hashtags, add a class to it 176 176 if (enhancedContent.indexOf('#') !== -1) { 177 - const hashtagStuffedParagraph = Array.from(dom.querySelectorAll('p')).find( 178 - (p) => { 179 - let hashtagCount = 0; 180 - for (let i = 0; i < p.childNodes.length; i++) { 181 - const node = p.childNodes[i]; 177 + let prevIndex = null; 178 + const hashtagStuffedParagraphs = Array.from( 179 + dom.querySelectorAll('p'), 180 + ).filter((p, index) => { 181 + let hashtagCount = 0; 182 + for (let i = 0; i < p.childNodes.length; i++) { 183 + const node = p.childNodes[i]; 182 184 183 - if (node.nodeType === Node.TEXT_NODE) { 184 - const text = node.textContent.trim(); 185 - if (text !== '') { 186 - return false; 187 - } 188 - } else if (node.tagName === 'A') { 189 - const linkText = node.textContent.trim(); 190 - if (!linkText || !linkText.startsWith('#')) { 191 - return false; 192 - } else { 193 - hashtagCount++; 194 - } 195 - } else { 185 + if (node.nodeType === Node.TEXT_NODE) { 186 + const text = node.textContent.trim(); 187 + if (text !== '') { 196 188 return false; 197 189 } 190 + } else if (node.tagName === 'BR') { 191 + // Ignore <br /> 192 + } else if (node.tagName === 'A') { 193 + const linkText = node.textContent.trim(); 194 + if (!linkText || !linkText.startsWith('#')) { 195 + return false; 196 + } else { 197 + hashtagCount++; 198 + } 199 + } else { 200 + return false; 198 201 } 199 - // Only consider "stuffing" if there are more than 3 hashtags 200 - return hashtagCount > 3; 201 - }, 202 - ); 203 - if (hashtagStuffedParagraph) { 204 - hashtagStuffedParagraph.classList.add('hashtag-stuffing'); 205 - hashtagStuffedParagraph.title = hashtagStuffedParagraph.innerText; 202 + } 203 + // Only consider "stuffing" if: 204 + // - there are more than 3 hashtags 205 + // - there are more than 1 hashtag in adjacent paragraphs 206 + if (hashtagCount > 3) { 207 + prevIndex = index; 208 + return true; 209 + } 210 + if (hashtagCount > 1 && prevIndex && index === prevIndex + 1) { 211 + prevIndex = index; 212 + return true; 213 + } 214 + }); 215 + if (hashtagStuffedParagraphs?.length) { 216 + hashtagStuffedParagraphs.forEach((p) => { 217 + p.classList.add('hashtag-stuffing'); 218 + p.title = p.innerText; 219 + }); 206 220 } 207 221 } 208 222