Search code examples
phphtmlreplaceattributesdomdocument

How to replace img src and link href in a document with a mustache expression?


I trying to replace the src,href value but with a small modified using regex

Simple example

//Find:
<img src="icons/google-icon.svg" > 
//Replace to: 
<img src="{{asset('icons/google-icon.svg')}}" >

//Find:
<link href="css/style.css"> 
//Replace to: 
<link href="{{asset('css/style.css')}}">
/** etc... */

Now this is my regex:

//Find:
src\s*=\s*"(.+?)" 
//Replace to:
src="{{ asset('$1') }}"

And its work very great actually but its only for src not [href,src], also I want to exclude any value that contains {{asset

Any idea? Thanks in advance


Solution

  • You can use an alternation to match src or href, and then a negative lookahead to assert that the src/href doesn't start with {{asset:

    ((?:src|href)\s*=\s*")((?!{{\s*asset)[^"]+)
    

    Demo on regex101

    This will also change href attributes inside <a> tags or elsewhere. If that is an issue, use a DOMDocument solution instead. Note that if your HTML is not just a snippet then you don't need to add the div tag around it in the call to loadHTML and the last line should be changed to echo substr($doc->saveXML(), 38);.

    $html = <<<EOT
    //Find:
    <img src="icons/google-icon.svg" > 
    //Replace to: 
    <img src="{{asset('icons/google-icon.svg')}}" >
    
    //Find:
    <link href="css/style.css"> 
    //Replace to: 
    <link href="{{asset('css/style.css')}}">
    /** etc... */
    <a href="http://www.example.com">
    EOT;
    
    $doc = new DOMDocument();
    $doc->loadHTML("<div>$html</div>", LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
    
    $xpath = new DOMXPath($doc);
    foreach ($xpath->query('//img') as $img) {
        $src = $img->getAttribute('src');
        if (preg_match('/^(?!{{\s*asset).*$/', $src, $m)) {
            $img->setAttribute('src', "{{asset('" . $m[0] . ")'}}");
        }
    }
    
    foreach ($xpath->query('//link') as $link) {
        $href = $link->getAttribute('href');
        if (preg_match('/^(?!{{\s*asset).*$/', $href, $m)) {
            $link->setAttribute('href', "{{asset('" . $m[0] . ")'}}");
        }
    }
    
    // strip XML header and added <div> tag
    echo substr($doc->saveXML(), 44, -6);
    

    Output:

    //Find:
    <img src="{{asset('icons/google-icon.svg)'}}"/> 
    //Replace to: 
    <img src="{{asset('icons/google-icon.svg')}}"/>
    
    //Find:
    <link href="{{asset('css/style.css)'}}"/> 
    //Replace to: 
    <link href="{{asset('css/style.css')}}"/>
    /** etc... */
    <a href="http://www.example.com"/>
    

    Demo on 3v4l.org