Further polish hashtag stuffing logic

This commit is contained in:
Lim Chee Aun 2023-08-20 10:17:56 +08:00
parent a325630c20
commit ccd79e5348
2 changed files with 43 additions and 27 deletions

View file

@ -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.

View file

@ -174,35 +174,49 @@ function enhanceContent(content, opts = {}) {
// ================
// Get the <p> 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 <br />
} 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;
});
}
}