3v4l.org

run code in 300+ PHP versions simultaneously
<?php $html = <<<HTML <div> Some text <img src="https://example.com/foo?bar=food"> and a raw link http://example.com/number2 then <a href="https://example.com/the/third/url">original text</a> ... and <p>here's another HTTPS://www.example.net/booyah</p> and done </div> HTML; $dom = new DOMDocument(); $dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); $xpath = new DOMXPath($dom); $regex = '#\bhttps?://[-\w.]+(?::\d+)?(?:/(?:[\w/_.-]*(?:\?\S+)?)?)?#ui'; foreach ($xpath->query('//*[not(self::a)]/text()') as $textNode) { $text = $textNode->nodeValue; foreach (preg_match_all($regex, $text, $m) ? $m[0] : [] as $url) { $a = $dom->createElement('a', htmlspecialchars($url)); $a->setAttribute('href', $url); $mbPosOfUrlInText = mb_strpos($text, $url); // regurgitate any leading text as newpreceding node // then replace remainder of text with new hyperlink $textNode->parentNode->replaceChild( $a, $textNode->splitText($mbPosOfUrlInText) ); // add any text after url as new text node after new hyperlink $textNode->parentNode->insertBefore( $dom->createTextNode( mb_substr($text, $mbPosOfUrlInText + mb_strlen($url)) ), $a->nextSibling ); } } echo $dom->saveHTML();
Output for 8.1.0 - 8.1.34, 8.2.0 - 8.2.30, 8.3.0 - 8.3.30, 8.4.1 - 8.4.18, 8.5.0 - 8.5.3
<div> Some text <img src="https://example.com/foo?bar=food"> and a raw link <a href="http://example.com/number2">http://example.com/number2</a> then <a href="https://example.com/the/third/url">original text</a> ... and <p>here's another <a href="HTTPS://www.example.net/booyah">HTTPS://www.example.net/booyah</a></p> and done </div>

preferences:
56.19 ms | 1031 KiB | 4 Q