Fix auto-link nested <a> tag protection and add feature flag check

This commit is contained in:
2026-07-21 13:46:54 +02:00
parent e80967f0fe
commit 2fdf90519a
+14 -15
View File
@@ -598,7 +598,9 @@ class CodePressCMS {
// Auto-link page titles to existing content pages (but not in H1 tags) // Auto-link page titles to existing content pages (but not in H1 tags)
if ($this->config['features']['auto_link_pages'] ?? true) {
$body = $this->autoLinkPageTitles($body, $cleanName); $body = $this->autoLinkPageTitles($body, $cleanName);
}
// Convert relative internal links to clean URLs (skip already-prefixed URLs) // Convert relative internal links to clean URLs (skip already-prefixed URLs)
$body = preg_replace('/href="\/blog\/([^"]+)"/', 'href="/' . $this->currentLanguage . '/blog/$1"', $body); $body = preg_replace('/href="\/blog\/([^"]+)"/', 'href="/' . $this->currentLanguage . '/blog/$1"', $body);
@@ -620,15 +622,6 @@ class CodePressCMS {
* @return string Content with auto-linked page titles * @return string Content with auto-linked page titles
*/ */
private function autoLinkPageTitles($content, $excludeTitle = '') { private function autoLinkPageTitles($content, $excludeTitle = '') {
// Protect existing <a> tags and <h1> content with placeholders
$placeholders = [];
$content = preg_replace_callback('/<a\b[^>]*>.*?<\/a>|<h1\b[^>]*>.*?<\/h1>|\[([^\]]*)\]\(([^)]*)\)|^#{1,6}\s.*$/m', function($m) use (&$placeholders) {
$key = '@@LINK_' . count($placeholders) . '@@';
$placeholders[$key] = $m[0];
return $key;
}, $content);
// Get all available pages with their titles
$pages = $this->getAllPageTitles(); $pages = $this->getAllPageTitles();
foreach ($pages as $pagePath => $pageTitle) { foreach ($pages as $pagePath => $pageTitle) {
@@ -636,16 +629,22 @@ class CodePressCMS {
continue; continue;
} }
// Protect existing <a> tags, <h1> content, and markdown links before each replacement
$placeholders = [];
$protected = preg_replace_callback('/<a\b[^>]*>.*?<\/a>|<h1\b[^>]*>.*?<\/h1>|\[([^\]]*)\]\(([^)]*)\)|^#{1,6}\s.*$/m', function($m) use (&$placeholders) {
$key = '@@ALINK_' . count($placeholders) . '@@';
$placeholders[$key] = $m[0];
return $key;
}, $content);
$pattern = '/\b' . preg_quote($pageTitle, '/') . '\b/i'; $pattern = '/\b' . preg_quote($pageTitle, '/') . '\b/i';
$content = preg_replace_callback($pattern, function($matches) use ($pageTitle, $pagePath) { $protected = preg_replace_callback($pattern, function($matches) use ($pageTitle, $pagePath) {
return '<a href="' . $this->buildUrl($pagePath) . '" class="auto-link" title="' . $this->t('go_to') . ' ' . htmlspecialchars($pageTitle) . '">' . $matches[0] . '</a>'; return '<a href="' . $this->buildUrl($pagePath) . '" class="auto-link" title="' . $this->t('go_to') . ' ' . htmlspecialchars($pageTitle) . '">' . $matches[0] . '</a>';
}, $content); }, $protected);
}
// Restore protected placeholders // Restore placeholders
foreach ($placeholders as $key => $value) { $content = str_replace(array_keys($placeholders), array_values($placeholders), $protected);
$content = str_replace($key, $value, $content);
} }
return $content; return $content;