Parse HTML and replace inky components

@param string $html
@return string
778967
public function parse($html)
    {
        $errorHandling = libxml_use_internal_errors(true);

        $dom = new \DOMDocument();
        $dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

        $xpath = new \DOMXpath($dom);

        foreach ($this->componentFactories as $tag => $factory) {
            $tags = $xpath->query('//' . $tag);

            if ($tags) {
                foreach ($tags as $node) {
                    $factory->parse($node);
                }
            }
        }

        libxml_clear_errors();
        libxml_use_internal_errors($errorHandling);

        return $dom->saveHTML();
    }
521830
protected static function parseReleases($html)
    {
        $releases         = array();
        $xmlErrorHandling = libxml_use_internal_errors(true);

        $dom = new DOMDocument();
        $dom->loadHTML($html);
        $xpath = new DOMXPath($dom);

        $nodes = self::getByClass('version', $xpath);
        foreach ($nodes as $node) {
            $version = $node->getAttribute('id');
            if (1 !== preg_match(self::SKIP_PATTERN, $version)) {
                $date      = '';
                $dateNodes = self::getByClass('releasedate', $xpath, $node);
                foreach ($dateNodes as $dateNode) {
                    $date = $dateNode->getAttribute('datetime');
                }
                $releases[$version] = empty($date) ? '' : $date;
            }
        }

        libxml_clear_errors();
        libxml_use_internal_errors($xmlErrorHandling);

        return (array)$releases;
    }
621980
public function parse(string $html) : TokenCollection
    {
        self::$allHtml = $html;
        $tokens = new TokenCollection();
        $remainingHtml = trim($html);
        while (mb_strlen($remainingHtml) > 0) {
            $token = TokenFactory::buildFromHtml(
                $remainingHtml,
                null,
                $this->throwOnError
            );
            if (!$token instanceof Token) {
                // Error has occurred, so we stop.
                break;
            }

            $remainingHtml = $token->parse($remainingHtml);
            $tokens[] = $token;
        }

        return $tokens;
    }
1133613
public function addAttributesToHtml($html)
    {
        $html = trim((string) $html);

        $attributes = array_merge($this->getRequiredAttributes(), $this->attributes());
        $attributesString = Html::attributes($attributes);

        return preg_replace('|<(.*?)>|', "<$1$attributesString>", $html, 1);
    }
866838
public function convert($html)
    {
        preg_match_all('|<img ([^>]+)>|', $html, $matches);

        foreach($matches[0] as $img)
        {
            $crawler = new Crawler();
            $crawler->addContent($img);
            $imgTag = $crawler->filter("img");

            $src = $imgTag->attr('src');
            $width = $imgTag->attr('width');
            $height = $imgTag->attr('height');

            if (!empty($width) || !empty($height)) {
                $format = $width . "x" . $height;
                $updatedTagString = preg_replace("| src=[\"']" . $src . "[\"']|", " src=\"" . $this->imResize($src, $format) . "\"", $img);
                $html = str_replace($img, $updatedTagString, $html);
            }
        }

        return $html;
    }
319269
public function fixNonvoidTags($html) {
        return preg_replace_callback('~(<([\w]+)[^>]*?)(\s*/>)~u', function ($matches) {
            // something went wrong
            if(empty($matches[2])) {
                // do nothing
                return $matches[0];
            }
            // regular void elements
            if(in_array($matches[2], array('area','base','br','col','embed','hr','img','input','keygen','link','meta','param','source','track','wbr'))) {
                // do nothing
                return $matches[0];
            }
            // correctly closed element
            return trim(mb_substr($matches[0], 0, -2), 'UTF-8') . '></' . $matches[2] . '>';
        }, $html);
    }
592561
private function parseNoContents(string $tag, string $html): string
    {
        $remainingHtml = \ltrim($html);
        $matchingResult = \preg_match(
            "/(<\/\s*" . $tag . "\s*>)/i",
            $html,
            $endOfScriptMatches
        );
        if ($matchingResult === 0) {
            return '';
        }

        $closingTag = $endOfScriptMatches[1];
        $this->value = \mb_substr($remainingHtml, 0, \mb_strpos($html, $closingTag));

        return \mb_substr(
            \mb_strstr($remainingHtml, $closingTag),
            \mb_strlen($closingTag)
        );
    }
700342
private function cleanupXss($html)
    {
        if (false === $this->config['xss_filter']) {
            return $html;
        }

        $this->logger->info('Filtering HTML to remove XSS');

        return htmLawed(
            $html,
            [
                'safe' => 1,
                // *+iframe: do not remove iframe elements
                'elements' => '*+iframe-meta',
                'deny_attribute' => 'style',
                'comment' => 1,
                'cdata' => 1,
            ]
        );
    }
1001315
public static function Html($Mixed) {
      if (!is_string($Mixed)) {
         return self::To($Mixed, 'Html');
      } else {
         $IsHtml = strpos($Mixed, '<') !== FALSE
            || (bool)preg_match('/&#?[a-z0-9]{1,10};/i', $Mixed);

         if ($IsHtml) {
            // The text contains html and must be purified.

            $Formatter = Gdn::Factory('HtmlFormatter');
            if(is_null($Formatter)) {
               // If there is no HtmlFormatter then make sure that script injections won't work.
               return self::Display($Mixed);
            }

            // Allow the code tag to keep all enclosed html encoded.
            $Mixed = preg_replace(
               array('/<code([^>]*)>(.+?)<\/code>/sei'),
               array('\'<code\'.RemoveQuoteSlashes(\'\1\').\'>\'.htmlspecialchars(RemoveQuoteSlashes(\'\2\')).\'</code>\''),
               $Mixed
            );
            
            // Do HTML filtering before our special changes
            $Mixed = $Formatter->Format($Mixed);

            // Links
            $Mixed = Gdn_Format::Links($Mixed);
            // Mentions & Hashes
            $Mixed = Gdn_Format::Mentions($Mixed);

            // nl2br
            if(C('Garden.Format.ReplaceNewlines', TRUE)) {
               $Mixed = preg_replace("/(\015\012)|(\015)|(\012)/", "<br />", $Mixed);
               $Mixed = FixNl2Br($Mixed);
            }
            
            $Result = $Mixed;            

//            $Result = $Result.
//               "<h3>Html</h3><pre>".nl2br(htmlspecialchars(str_replace("<br />", "\n", $Mixed)))."</pre>".
//               "<h3>Formatted</h3><pre>".nl2br(htmlspecialchars(str_replace("<br />", "\n", $Result)))."</pre>";
         } else {
            // The text does not contain html and does not have to be purified.
            // This is an optimization because purifying is very slow and memory intense.
            $Result = htmlspecialchars($Mixed, ENT_NOQUOTES, 'UTF-8');
            $Result = Gdn_Format::Mentions($Result);
            $Result = Gdn_Format::Links($Result);
            if(C('Garden.Format.ReplaceNewlines', TRUE)) {
               $Result = preg_replace("/(\015\012)|(\015)|(\012)/", "<br />", $Result);
               $Result = FixNl2Br($Result);
            }
         }
         
         return $Result;
      }
   }
1353265
public function get($html = null)
    {
        if (null === $html) {
            if (file_exists($this->_path)) {
                $html = file_get_contents($this->_path);
            }
        }

        $this->_path = null;

        return $this->parse($html);
    }
1013534
protected function regexSearchReplace( $html ) {

		/* cherry pick likely content areas */
		// HTML5, ungreedy
		preg_match( '/(?:<main[^>]*>)(.*)<\/main>/isU', $html, $matches );
		$html = ( ! empty( $matches[1] ) ) ? $matches[1] : $html;

		// WP content area, greedy
		preg_match( '/(?:<div id="main"[^>]*>)(.*)<\/div>/is', $html, $matches );
		$html = ( ! empty( $matches[1] ) ) ? $matches[1] : $html;

		// general content area, greedy
		preg_match( '/(?:<div id="content"[^>]*>)(.*)<\/div>/is', $html, $matches );
		$html = ( ! empty( $matches[1] ) ) ? $matches[1] : $html;

		// specific PB content area, greedy
		preg_match( '/(?:<div class="entry-content"[^>]*>)(.*)<\/div>/is', $html, $matches );
		$html = ( ! empty( $matches[1] ) ) ? $matches[1] : $html;

		/* cull */
		// get rid of script tags, ungreedy
		$result = preg_replace( '/(?:<script[^>]*>)(.*)<\/script>/isU', '', $html );
		// get rid of forms, ungreedy
		$result = preg_replace( '/(?:<form[^>]*>)(.*)<\/form>/isU', '', $result );
		// get rid of html5 nav content, ungreedy
		$result = preg_replace( '/(?:<nav[^>]*>)(.*)<\/nav>/isU', '', $result );
		// get rid of PB nav, next/previous
		$result = preg_replace( '/(?:<div class="nav"[^>]*>)(.*)<\/div>/isU', '', $result );
		// get rid of PB share buttons
		$result = preg_replace( '/(?:<div class="share-wrap-single"[^>]*>)(.*)<\/div>/isU', '', $result );
		// get rid of html5 footer content, ungreedy
		$result = preg_replace( '/(?:<footer[^>]*>)(.*)<\/footer>/isU', '', $result );
		// get rid of sidebar content, greedy
		$result = preg_replace( '/(?:<div id="sidebar\d{0,}"[^>]*>)(.*)<\/div>/is', '', $result );
		// get rid of comments, greedy
		$result = preg_replace( '/(?:<div id="comments"[^>]*>)(.*)<\/div>/is', '', $result );

		return $result;
	}
1083850
protected function cleaningHtml($html)
    {
        $xml = false;
        $childrens = null;

        try {
            $xml = @simplexml_load_string($html);
        } catch (\Exception $e) {
            // ignore
        }

        if ($xml !== false) {
            if (!$this->hasHead && $xml->getName() === 'head') {
                $childrens = $xml->xpath('//head/child::*');
            }
            if (!$this->hasBody && $xml->getName() === 'body') {
                $childrens = $xml->xpath('//body/child::*');
            }

            if ($childrens !== null) {
                $temp = '';
                foreach ($childrens as $children) {
                    $temp .= $children->saveXML();
                }
                $html = html_entity_decode($temp);
            }
        }

        if ($this->hasHtml) {
            $html = $this->htmlMatches['before'].$html.$this->htmlMatches['after'];
        }
        if ($this->hasDoctype) {
            $html = $this->doctypeMatches['content'].$html;
        }

        return $html;
    }
8896
protected function stripHtml($html)
    {
        $str = html_entity_decode($html);

        // Strip HTML (Replace br with newline, remove "invisible" tags and strip other tags)
        $str = preg_replace('#<br[^>]*?>#siu', "\n", $str);
        $str = preg_replace(
            [
                '#<applet[^>]*?.*?</applet>#siu',
                '#<embed[^>]*?.*?</embed>#siu',
                '#<head[^>]*?>.*?</head>#siu',
                '#<noframes[^>]*?.*?</noframes>#siu',
                '#<noscript[^>]*?.*?</noscript>#siu',
                '#<noembed[^>]*?.*?</noembed>#siu',
                '#<object[^>]*?.*?</object>#siu',
                '#<script[^>]*?.*?</script>#siu',
                '#<style[^>]*?>.*?</style>#siu'
            ],
            '',
            $str
        );
        $str = strip_tags($str);

        // Trim whitespace
        $str = str_replace("\t", '', $str);
        $str = preg_replace('#\n\r|\r\n#', "\n", $str);
        $str = preg_replace('#\n{3,}#', "\n\n", $str);
        $str = preg_replace('/ {2,}/', ' ', $str);
        $str = implode("\n", array_map('trim', explode("\n", $str)));
        $str = trim($str)."\n";
        return $str;
    }
1076786
public function plain($html)
    {
        $plain = preg_replace('#<br\s*/?>#iu', "\n", $html);
        $plain = strip_tags($plain);
        $plain = html_entity_decode($plain, ENT_QUOTES | ENT_HTML5);

        return $plain;
    }
1238789
protected function decodeHtml($html): string
    {
        $text = html_entity_decode($html);
        $text = preg_replace('#<br\s*/?>#', LF, $text);

        return $text;
    }
206414
public static function removeEmptyLines($html) {
    // merge multiple linebreaks to one
    $html = preg_replace("/(<br>\s*)+/", "<br>", $html);
    // remove linebreaks at the beginning of a paragraph
    $html = preg_replace("/<p>(\s|<br>)*/", "<p>", $html);
    // remove linebreaks at the end of a paragraph
    $html = preg_replace("/(\s|<br>)*<\/p>/", "</p>", $html);
    // remove empty paragraphs
    $html = preg_replace("/<p><\/p>/", "", $html);
    return $html;
  }
1188414
public function convertToString($html)
    {
        $externalJavaScript = $this->extractExternalJavaScript($html);

        return $this->replaceJavaScriptTags($html, $externalJavaScript);
    }