1

I've created a plugin that turn all links into protocol-relative URLs (removing http: and https:) based off the tags and attributes that I list in the $tag and $attribute variables. This is part of the function. To save space, the rest of the code can be found here.

$tag = 'a|base|div|form|iframe|img|link|meta|script|svg';
$attribute = 'action|content|data-project-file|href|src|srcset|style';
# If 'Protocol Relative URL' option is checked, only apply change to internal links
if ( $this->option == 1 ) {
    # Remove protocol from home URL
    $website = preg_replace( '/https?:\/\//', '', home_url() );
    # Remove protocol from internal links
    $links = preg_replace( '/(<(' . $tag . ')([^>]*)(' . $attribute . ')=["\'])https?:\/\/' . $website . '/i', '$1//' . $website, $links );
}
# Else, remove protocols from all links
else {
    $links = preg_replace( '/(<(' . $tag . ')([^>]*)(' . $attribute . ')=["\'])https?:\/\//i', '$1//', $links );
}

This works as intended, but it doesn't work on these examples:

<!-- Within the 'style' attribute -->
<div class="some-class" style='background-color:rgba(255,255,255,0);background-image:url("http://placehold.it/300x200");background-position:center center;background-repeat:no-repeat'>
<!-- Within the 'srcset' attribute -->
<img src="http://placehold.it/600x300" srcset="http://placehold.it/500 500x, http://placehold.it/100 100w">

However, the code partially works for these examples.

<div class="some-class" style='background-color:rgba(255,255,255,0);background-image:url("http://placehold.it/300x200");background-position:center center;background-repeat:no-repeat'>
<img src="http://placehold.it/600x300" srcset="//placehold.it/500 500x, http://placehold.it/100 100w">

I've played around with adding additional values to the $tag and $attribute variables, but that didn't help. I'd assume I need to update the rest of my regex to cover these two additional tags? Or is there is a different way to approach it, such as DOMDocument?

1
  • 2
    This question isn't really relevant to WordPress, you'd probably do better asking it on a PHP or RegEx exchange.
    – totels
    Commented Feb 28, 2017 at 23:22

1 Answer 1

0

I was able to use the following regex to cover all tags & attributes with protocols:

/<(?:input\b[^<]*\bvalue=[\"\']https?:\/\/|link\b[^<]*?\brel=[\'\"]canonical[\'\"][^<]*?>)(*SKIP)(*F)|https?:\/\//

This is the updated section:

# If 'Relative' option is selected, remove domain from all internal links
$exceptions = '<(?:input\b[^<]*\bvalue=[\"\']https?:\/\/|link\b[^<]*?\brel=[\'\"]canonical[\'\"][^<]*?>)(*SKIP)(*F)';
if ( $this->option == 2 ) {
    $website = preg_replace( '/https?:\/\//', '', home_url() );
    $links = preg_replace( '/' . $exceptions . '|https?:\/\/' . $website . '/', '', $links );
}
# For all external links, remove protocols
$links = preg_replace( '/<(?:input\b[^<]*\bvalue=[\"\']https?:\/\/|link\b[^<]*?\brel=[\'\"]canonical[\'\"][^<]*?>)(*SKIP)(*F)|https?:\/\//', '//', $links );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.