Clean out spurious headers from an Element. Checks things like classnames and link density.

@param DOMDocument $article

@return void
543172
public function _cleanHeaders(DOMDocument $article)
    {
        for ($headerIndex = 1; $headerIndex < 3; $headerIndex++) {
            $headers = $article->getElementsByTagName('h' . $headerIndex);
            /** @var $header DOMElement */
            foreach ($headers as $header) {
                $weight = 0;
                if ($this->configuration->getWeightClasses()) {
                    $weight = $header->getClassWeight();
                }

                if ($weight < 0) {
                    $this->logger->debug(sprintf('[PrepArticle] Removing H node with 0 or less weight. Content was: \'%s\'', substr($header->nodeValue, 0, 128)));

                    NodeUtility::removeNode($header);
                }
            }
        }
    }
521049
public function published(Article $article)
    {
        $article->togglePublishedState();

        return $this->notifySuccess(trans(
                'cms::article.update.published', [
                'task' => $article->published ? 'published' : 'unpublished',
            ])
        );
    }
822412
function clean($tag) {
		if (isset($this->_tags[$tag])) {
			foreach ($this->_tags[$tag] as $k) { /** @var string $k */
				unset($this->_data[$k]);
			}
			unset($this->_tags[$tag]);
		}
	}
791913
public function remove()
    {
        foreach ($this as $node) {
            /**
             * @var \DOMNode $node
             */
            if ($node->parentNode instanceof \DOMElement) {
                $node->parentNode->removeChild($node);
            }
        }
        $this->clear();
    }
860000
protected function normalizeAttributes(PHPTAL_Dom_Element $element)
    {
        parent::normalizeAttributes($element);

        $attrs_by_qname = array();
        foreach ($element->getAttributeNodes() as $attrnode) {
            // safe, as there can't be two attrs with same qname
            $attrs_by_qname[$attrnode->getQualifiedName()] = $attrnode;
        }

	if (count($attrs_by_qname) > 1) {
		uksort($attrs_by_qname, array($this, 'compareQNames'));
		$element->setAttributeNodes(array_values($attrs_by_qname));
	}
    }
890765
private function removeHeaders($content)
        {
            $content = str_replace('<?xml encoding="UTF-8">', "", $content);
            $content = str_replace('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">', "", $content);
            $content = str_replace('<html><body>', "", $content);
            $content = str_replace('</body></html>', "", $content);

            return $content;
        }
640965
public function setArticle(Article $article = null)
    {
        $this->article = $article;
        $this->url = null;

        return $this;
    }
1286592
private function writeDocument(\DOMDocument $dom)
    {
        $dom->formatOutput = true;
        $this->write($dom->saveXML());
    }
694915
private function cleanupDOMDocument()
    {
        $expressions = array(
            '//comment()',
            '//processing-instruction()',
        );

        foreach ($expressions as $expression) {
            foreach ($this->xpath->query($expression) as $node) {
                $node->parentNode->removeChild($node);
            }
        }

        $this->dom->normalizeDocument();
    }
92877
protected function cleanAttributesOnWhitelist(\DOMElement $element)
    {
        for ($x = $element->attributes->length - 1; $x >= 0; $x--) {
            // get attribute name
            $attrName = $element->attributes->item($x)->name;

            // Remove attribute if not in whitelist
            if (!in_array(strtolower($attrName), $this->allowedAttrs) && !$this->isAriaAttribute(strtolower($attrName)) && !$this->isDataAttribute(strtolower($attrName))) {

                $element->removeAttribute($attrName);
                $this->xmlIssues[] = array(
                    'message' => 'Suspicious attribute \'' . $attrName . '\'',
                    'line' => $element->getLineNo(),
		);
            }

            // Do we want to strip remote references?
            if($this->removeRemoteReferences) {
                // Remove attribute if it has a remote reference
                if (isset($element->attributes->item($x)->value) && $this->hasRemoteReference($element->attributes->item($x)->value)) {
                    $element->removeAttribute($attrName);
                    $this->xmlIssues[] = array(
                        'message' => 'Suspicious attribute \'' . $attrName . '\'',
                        'line' => $element->getLineNo(),
		    );
                }
            }
        }
    }
257113
private static void cleanHeaders(Element e) {
        for (int headerIndex = 1; headerIndex < 7; headerIndex++) {
            Elements headers = getElementsByTag(e, "h" + headerIndex);
            for (Element header : headers) {
                if (getClassWeight(header) < 0
                        || getLinkDensity(header) > 0.33f) {
                    header.remove();
                }
            }
        }
    }
1037139
public void removeWikiLinkMarkup(StringBuilder article, String title) {
        int bracketStart = article.indexOf("[[");
        boolean includeLinkText = 
            options.contains(CleanerOption.INCLUDE_LINK_TEXT);
        while (bracketStart >= 0) {
            
            // grab the linked article name which is all text to the next ]], or
            // to
            int bracketEnd = article.indexOf("]]", bracketStart);
            // If there wasn't a matching closing bracket (i.e. malformatted
            // wiki), then abort the replacement
            if (bracketEnd < 0)
                break;
            
            // If the link text is supposed to be included in the document, then
            // strip out the pertinent text.  However, ensure that the link
            // points to an article, which filters out non-content links in the
            // article headers and footers
            if (includeLinkText && 
                isArticleLink(article.substring(bracketStart+2, 
                                                bracketEnd), title)) {

                // the link may also have a text description that replaces the
                // link text, e.g.  [[article title|link text]].
                int optionalLinkDescriptionStart = 
                    article.indexOf("|", bracketStart);
                // When selecting the optional text, ensure that the | delimeter
                // falls within the link structure itself
                int linkTextStart = 
                    (optionalLinkDescriptionStart >= 0 && 
                     optionalLinkDescriptionStart < bracketEnd)
                    ? optionalLinkDescriptionStart + 1
                    : bracketStart + 2;
                // Parse out the link text
                String linkText = article.substring(linkTextStart, bracketEnd);
                // Then replace the entire link with the desired text
                article.replace(bracketStart, bracketEnd+2, linkText);
            }
            // If the link text isn't to be used in the document, remove it
            // completely
            else {
                article.delete(bracketStart, bracketEnd + 2);
            }
            bracketStart = article.indexOf("[[", bracketStart);
        }   
    }
1133368
protected static function text(Element $element, string $phpExpression): void
    {
        $element->removeChildren();

        if ($phpExpression) {
            $element->appendChild(
                static::toPhp($phpExpression)
            );
        }
    }
1212020
public function edit(Article $article)
    {
        $tags         = Article::existingTags()->pluck('name');
        $selectedTags = implode(',', $article->tagNames());

        return view('administrator.articles.edit', compact('article', 'tags', 'selectedTags'));
    }
800151
protected function fixHeaders()
    {
        if (count($this->immediateChildren)) {
            $this->setHeaderParameter('Content-Type', 'boundary',
                $this->getBoundary()
                );
            $this->headers->remove('Content-Transfer-Encoding');
        } else {
            $this->setHeaderParameter('Content-Type', 'boundary', null);
            $this->setEncoding($this->encoder->getName());
        }
    }
1124782
private function prepDocument(DOMDocument $dom)
    {
        $this->logger->info('[PrepDocument] Preparing document for parsing...');

        foreach ($dom->shiftingAwareGetElementsByTagName('br') as $br) {
            $next = $br->nextSibling;

            /*
             * Whether 2 or more <br> elements have been found and replaced with a
             * <p> block.
             */
            $replaced = false;

            /*
             * If we find a <br> chain, remove the <br>s until we hit another element
             * or non-whitespace. This leaves behind the first <br> in the chain
             * (which will be replaced with a <p> later).
             */
            while (($next = NodeUtility::nextElement($next)) && ($next->nodeName === 'br')) {
                $this->logger->debug('[PrepDocument] Removing chain of BR nodes...');

                $replaced = true;
                $brSibling = $next->nextSibling;
                $next->parentNode->removeChild($next);
                $next = $brSibling;
            }

            /*
             * If we removed a <br> chain, replace the remaining <br> with a <p>. Add
             * all sibling nodes as children of the <p> until we hit another <br>
             * chain.
             */

            if ($replaced) {
                $p = $dom->createElement('p');
                $br->parentNode->replaceChild($p, $br);

                $next = $p->nextSibling;
                while ($next) {
                    // If we've hit another <br><br>, we're done adding children to this <p>.
                    if ($next->nodeName === 'br') {
                        $nextElem = NodeUtility::nextElement($next->nextSibling);
                        if ($nextElem && $nextElem->nodeName === 'br') {
                            break;
                        }
                    }

                    if (!$next->isPhrasingContent()) {
                        break;
                    }

                    $this->logger->debug('[PrepDocument] Replacing BR with a P node...');

                    // Otherwise, make this node a child of the new <p>.
                    $sibling = $next->nextSibling;
                    $p->appendChild($next);
                    $next = $sibling;
                }

                while ($p->lastChild && $p->lastChild->isWhitespace()) {
                    $p->removeChild($p->lastChild);
                }

                if ($p->parentNode->tagName === 'p') {
                    NodeUtility::setNodeTag($p->parentNode, 'div');
                }
            }
        }

        // Replace font tags with span
        $fonts = $dom->getElementsByTagName('font');
        $length = $fonts->length;
        for ($i = 0; $i < $length; $i++) {
            $this->logger->debug('[PrepDocument] Converting font tag into a span tag.');
            $font = $fonts->item($length - 1 - $i);
            NodeUtility::setNodeTag($font, 'span');
        }
    }
637503
private static void cleanStyles(Element e) {
        if (e == null) {
            return;
        }

        Element cur = e.children().first();

        // Remove any root styles, if we're able.
        if (!"readability-styled".equals(e.className())) {
            e.removeAttr("style");
        }

        // Go until there are no more child nodes
        while (cur != null) {
            // Remove style attributes
            if (!"readability-styled".equals(cur.className())) {
                cur.removeAttr("style");
            }
            cleanStyles(cur);
            cur = cur.nextElementSibling();
        }
    }