Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
60.00% covered (warning)
60.00%
3 / 5
CRAP
97.26% covered (success)
97.26%
71 / 73
InForeignContent
0.00% covered (danger)
0.00%
0 / 1
60.00% covered (warning)
60.00%
3 / 5
26
97.26% covered (success)
97.26%
71 / 73
 characters
100.00% covered (success)
100.00%
1 / 1
5
100.00% covered (success)
100.00%
28 / 28
 isIntegrationPoint
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
3 / 3
 startTag
0.00% covered (danger)
0.00%
0 / 1
12
96.15% covered (success)
96.15%
25 / 26
 endTag
100.00% covered (success)
100.00%
1 / 1
5
100.00% covered (success)
100.00%
15 / 15
 endDocument
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 1
<?php
namespace RemexHtml\TreeBuilder;
use RemexHtml\HTMLData;
use RemexHtml\Tokenizer\Attributes;
/**
 * The rules for parsing tokens in foreign content.
 *
 * This is not referred to as an insertion mode in the spec, but is
 * sufficiently similar to one that we can inherit from InsertionMode here.
 */
class InForeignContent extends InsertionMode {
    /**
     * The list of tag names which unconditionally generate a parse error when
     * seen in foreign content.
     * @var array<string,bool>
     */
    private static $notAllowed = [
        'b' => true,
        'big' => true,
        'blockquote' => true,
        'body' => true,
        'br' => true,
        'center' => true,
        'code' => true,
        'dd' => true,
        'div' => true,
        'dl' => true,
        'dt' => true,
        'em' => true,
        'embed' => true,
        'h1' => true,
        'h2' => true,
        'h3' => true,
        'h4' => true,
        'h5' => true,
        'h6' => true,
        'head' => true,
        'hr' => true,
        'i' => true,
        'img' => true,
        'li' => true,
        'listing' => true,
        'menu' => true,
        'meta' => true,
        'nobr' => true,
        'ol' => true,
        'p' => true,
        'pre' => true,
        'ruby' => true,
        's' => true,
        'small' => true,
        'span' => true,
        'strong' => true,
        'strike' => true,
        'sub' => true,
        'sup' => true,
        'table' => true,
        'tt' => true,
        'u' => true,
        'ul' => true,
        'var' => true,
    ];
    /**
     * The table for correcting the tag names of SVG elements, given in the
     * "Any other start tag" section of the spec.
     */
    private static $svgElementCase = [
        'altglyph' => 'altGlyph',
        'altglyphdef' => 'altGlyphDef',
        'altglyphitem' => 'altGlyphItem',
        'animatecolor' => 'animateColor',
        'animatemotion' => 'animateMotion',
        'animatetransform' => 'animateTransform',
        'clippath' => 'clipPath',
        'feblend' => 'feBlend',
        'fecolormatrix' => 'feColorMatrix',
        'fecomponenttransfer' => 'feComponentTransfer',
        'fecomposite' => 'feComposite',
        'feconvolvematrix' => 'feConvolveMatrix',
        'fediffuselighting' => 'feDiffuseLighting',
        'fedisplacementmap' => 'feDisplacementMap',
        'fedistantlight' => 'feDistantLight',
        'fedropshadow' => 'feDropShadow',
        'feflood' => 'feFlood',
        'fefunca' => 'feFuncA',
        'fefuncb' => 'feFuncB',
        'fefuncg' => 'feFuncG',
        'fefuncr' => 'feFuncR',
        'fegaussianblur' => 'feGaussianBlur',
        'feimage' => 'feImage',
        'femerge' => 'feMerge',
        'femergenode' => 'feMergeNode',
        'femorphology' => 'feMorphology',
        'feoffset' => 'feOffset',
        'fepointlight' => 'fePointLight',
        'fespecularlighting' => 'feSpecularLighting',
        'fespotlight' => 'feSpotLight',
        'fetile' => 'feTile',
        'feturbulence' => 'feTurbulence',
        'foreignobject' => 'foreignObject',
        'glyphref' => 'glyphRef',
        'lineargradient' => 'linearGradient',
        'radialgradient' => 'radialGradient',
        'textpath' => 'textPath',
    ];
    public function characters( $text, $start, $length, $sourceStart, $sourceLength ) {
        $builder = $this->builder;
        while ( $length ) {
            $normalLength = strcspn( $text, "\0\t\n\f\r ", $start, $length );
            if ( $normalLength ) {
                $builder->framesetOK = false;
                $builder->insertCharacters( $text, $start, $normalLength,
                    $sourceStart, $sourceLength );
            }
            $start += $normalLength;
            $length -= $normalLength;
            $sourceStart += $normalLength;
            $sourceLength -= $normalLength;
            if ( !$length ) {
                break;
            }
            $char = $text[$start];
            if ( $char === "\0" ) {
                $builder->error( "replaced null character", $sourceStart );
                $builder->insertCharacters( "\xef\xbf\xbd", 0, 3, $sourceStart, $sourceLength );
                $start++;
                $length--;
                $sourceStart++;
                $sourceLength--;
            } else {
                // Whitespace
                $wsLength = strspn( $text, "\t\n\f\r ", $start, $length );
                $builder->insertCharacters( $text, $start, $wsLength, $sourceStart, $wsLength );
                $start += $wsLength;
                $length -= $wsLength;
                $sourceStart += $wsLength;
                $sourceLength -= $wsLength;
            }
        }
    }
    private function isIntegrationPoint( Element $element ) {
        return $element->namespace === HTMLData::NS_HTML
            || $element->isMathmlTextIntegration()
            || $element->isHtmlIntegration();
    }
    public function startTag( $name, Attributes $attrs, $selfClose, $sourceStart, $sourceLength ) {
        $builder = $this->builder;
        $stack = $builder->stack;
        $dispatcher = $this->dispatcher;
        if ( isset( self::$notAllowed[$name] ) ) {
            $allowed = false;