Mecha CMS

Mecha CMS blog and documentation.

Detect External Links

External links checker for “HTML” page type.

This snippet will automatically add rel="nofollow" and target="_blank" attribute to the external links in the page description and content. You don’t need this snippet if you are using Markdown. Markdown plugin already has this feature included.

Hook::set([
    'page.description',
    'page.content'
], function($content) use($url) {
    // Page type is not set or has value other than “HTML”, skip!
    if ($this->type !== 'HTML') {
        return $content;
    }
    // No anchor(s) found, skip!
    if (strpos($content, '</a>') === false) {
        return $content;
    }
    // Get anchor element(s) from page content…
    return preg_replace_callback('#<a(?:\s[^>]*?)?>[\s\S]*?</a>#', function($m) use($url) {
        $a = new HTML($m[0]);
        // No `href` attribute, skip!
        if (!$href = $a['href'])) {
            return $m[0];
        }
        // Check for external link(s)…
        // Based on <https://github.com/tovic/parsedown-extra-plugin>
        $if = strpos($href, 'https://' . $url->host) === 0 ||
              strpos($href, 'http://' . $url->host) === 0 ||
              strpos($href, '/') === 0 ||
              strpos($href, '?') === 0 ||
              strpos($href, '#') === 0 ||
              strpos($href, 'data:') === 0 ||
              strpos($href, 'javascript:') === 0 ||
              strpos($href, '.') === 0 ||
              (
                  strpos($href, '://') === false &&
                  strpos($href, 'data:') === false
              );
        // Double check for relative protocol…
        if (strpos($href, '//') === 0 && strpos($href, '//' . $url->host) !== 0) {
            $if = false;
        }
        // If external link…
        if (!$if) {
            // Add `rel="nofollow"` attribute
            $a['rel'] = 'nofollow';
            // Add `target="_blank"` attribute
            $a['target'] = '_blank';
        }
        // Re-unite the anchor…
        return $a;
    }, $content);
    return $content;
}, 2.1);