diff --git a/README.md b/README.md index 66f2a1ad..d2dcf919 100644 --- a/README.md +++ b/README.md @@ -78,9 +78,11 @@ Everything is designed and engineered following my taste and vision. This is a p ![Hashtag stuffing collapsing](readme-assets/hashtag-stuffing-collapsing.jpg) -- Any paragraphs, except the first one, with more than 3 hashtags will be collapsed. +- First paragraph of post content with more than 3 hashtags will be collapsed to max 3 lines. +- Subsequent paragraphs after first paragraph with more than 3 hashtags will be collapsed to 1 line. +- Adjacent paragraphs with more than 1 hashtag after collapsed paragraphs will be collapsed to 1 line. - If there are text around or between the hashtags, they will not be collapsed. -- Collapsed hashtags will be a single line with `...` at the end. +- Collapsed hashtags will be appended with `...` at the end. - They are also slightly faded out to reduce visual noise. - Opening the post view will reveal the hashtags uncollapsed. diff --git a/src/utils/enhance-content.js b/src/utils/enhance-content.js index 2d2586d6..1a6d70ce 100644 --- a/src/utils/enhance-content.js +++ b/src/utils/enhance-content.js @@ -174,35 +174,49 @@ function enhanceContent(content, opts = {}) { // ================ // Get the

that contains a lot of hashtags, add a class to it if (enhancedContent.indexOf('#') !== -1) { - const hashtagStuffedParagraph = Array.from(dom.querySelectorAll('p')).find( - (p) => { - let hashtagCount = 0; - for (let i = 0; i < p.childNodes.length; i++) { - const node = p.childNodes[i]; + let prevIndex = null; + const hashtagStuffedParagraphs = Array.from( + dom.querySelectorAll('p'), + ).filter((p, index) => { + let hashtagCount = 0; + for (let i = 0; i < p.childNodes.length; i++) { + const node = p.childNodes[i]; - if (node.nodeType === Node.TEXT_NODE) { - const text = node.textContent.trim(); - if (text !== '') { - return false; - } - } else if (node.tagName === 'A') { - const linkText = node.textContent.trim(); - if (!linkText || !linkText.startsWith('#')) { - return false; - } else { - hashtagCount++; - } - } else { + if (node.nodeType === Node.TEXT_NODE) { + const text = node.textContent.trim(); + if (text !== '') { return false; } + } else if (node.tagName === 'BR') { + // Ignore
+ } else if (node.tagName === 'A') { + const linkText = node.textContent.trim(); + if (!linkText || !linkText.startsWith('#')) { + return false; + } else { + hashtagCount++; + } + } else { + return false; } - // Only consider "stuffing" if there are more than 3 hashtags - return hashtagCount > 3; - }, - ); - if (hashtagStuffedParagraph) { - hashtagStuffedParagraph.classList.add('hashtag-stuffing'); - hashtagStuffedParagraph.title = hashtagStuffedParagraph.innerText; + } + // Only consider "stuffing" if: + // - there are more than 3 hashtags + // - there are more than 1 hashtag in adjacent paragraphs + if (hashtagCount > 3) { + prevIndex = index; + return true; + } + if (hashtagCount > 1 && prevIndex && index === prevIndex + 1) { + prevIndex = index; + return true; + } + }); + if (hashtagStuffedParagraphs?.length) { + hashtagStuffedParagraphs.forEach((p) => { + p.classList.add('hashtag-stuffing'); + p.title = p.innerText; + }); } }