Hi team,
I found a bug in the Articles addon (components/com_sppagebuilder/addons/articles/site.php) where void elements like <br /> inside an article's introtext end up duplicated in the rendered HTML output.
Issue Description
When an article contains a single line break in the intro text (e.g., <p><strong>Title</strong><br />Venue: Details...</p>), the Articles addon displays it with an extra empty line break:
HTML <div class="sppb-article-introtext"><strong>Title</strong><br><br>Venue: Details...</div>
Cause
In site.php, the DOM traversal function traverseNodes() treats all XML_ELEMENT_NODE elements equally without checking if an element is a self-closing/void tag.
For <br>, it runs:
PHP $content .= '<' . $child->nodeName . '>'; $this->traverseNodes($child, $content, $charCount, $limit); $content .= '</' . $child->nodeName . '>';
This generates <br></br>. Because </br> is invalid HTML syntax, modern web browsers automatically parse the closing </br> as a second <br> tag, causing unwanted double spacing.
Proposed Solution
Maintain a list of standard HTML void elements (<br>, <img>, <hr>, etc.) so they do not receive closing tags or recursive child processing.
Update traverseNodes() in site.php to:
`
PHP
function traverseNodes($node, &$content, &$charCount, $limit) {
$voidTags = ['br', 'hr', 'img', 'input', 'link', 'meta', 'area', 'base', 'col', 'embed', 'param', 'source', 'track', 'wbr'];
foreach ($node->childNodes as $child) {
if ($child->nodeType == XML_TEXT_NODE) {
$text = $child->textContent;
$remainingChars = $limit - $charCount;
if (mb_strlen($text) <= $remainingChars) {
$content .= htmlspecialchars($text);
$charCount += mb_strlen($text);
} else {
$content .= htmlspecialchars(mb_substr($text, 0, $remainingChars)) . '...';
$charCount = $limit;
return;
}
} elseif ($child->nodeType == XML_ELEMENT_NODE) {
$tag = strtolower($child->nodeName);
$content .= '<' . $child->nodeName;
if ($child->hasAttributes()) {
foreach ($child->attributes as $attr) {
$content .= ' ' . $attr->nodeName . '="' . htmlspecialchars($attr->nodeValue) . '"';
}
}
if (in_array($tag, $voidTags)) {
$content .= '>';
continue;
}
$content .= '>';
$this->traverseNodes($child, $content, $charCount, $limit);
$content .= '</' . $child->nodeName . '>';
if ($charCount >= $limit) return;
}
}
}
`
Could you please review and consider including this fix in the next SP Page Builder update?
Thank you!