Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
BeforeHtml
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
4 / 4
7
100.00% covered (success)
100.00%
1 / 1
 characters
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
2
 startTag
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
2
 endTag
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 endDocument
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace Wikimedia\RemexHtml\TreeBuilder;
4
5use Wikimedia\RemexHtml\Tokenizer\Attributes;
6use Wikimedia\RemexHtml\Tokenizer\PlainAttributes;
7
8/**
9 * The "before html" insertion mode
10 */
11class BeforeHtml extends InsertionMode {
12    public function characters( $text, $start, $length, $sourceStart, $sourceLength ) {
13        // Ignore whitespace
14        [ $part1, $part2 ] = $this->splitInitialMatch(
15            true, "\t\n\f\r ", $text, $start, $length, $sourceStart, $sourceLength );
16        [ $start, $length, $sourceStart, $sourceLength ] = $part2;
17        if ( !$length ) {
18            return;
19        }
20        // Generate missing <html> tag
21        $this->builder->insertElement( 'html', new PlainAttributes, false, $sourceStart, 0 );
22        $this->dispatcher->switchMode( Dispatcher::BEFORE_HEAD )
23            ->characters( $text, $start, $length, $sourceStart, $sourceLength );
24    }
25
26    public function startTag( $name, Attributes $attrs, $selfClose, $sourceStart, $sourceLength ) {
27        if ( $name === 'html' ) {
28            $this->builder->insertElement( $name, $attrs, false,
29                $sourceStart, $sourceLength );
30            $this->dispatcher->switchMode( Dispatcher::BEFORE_HEAD );
31        } else {
32            $this->builder->insertElement( 'html', new PlainAttributes,    false,
33                $sourceStart, 0 );
34            $this->dispatcher->switchMode( Dispatcher::BEFORE_HEAD )
35                ->startTag( $name, $attrs, $selfClose, $sourceStart, $sourceLength );
36        }
37    }
38
39    public function endTag( $name, $sourceStart, $sourceLength ) {
40        $allowed = [ "head" => true, "body" => true, "html" => true, "br" => true ];
41        if ( !isset( $allowed[$name] ) ) {
42            $this->builder->error( 'end tag not allowed before html', $sourceStart );
43            return;
44        }
45        $this->builder->insertElement( 'html', new PlainAttributes, false, $sourceStart, 0 );
46        $this->dispatcher->switchMode( Dispatcher::BEFORE_HEAD )
47            ->endTag( $name, $sourceStart, $sourceLength );
48    }
49
50    public function endDocument( $pos ) {
51        $this->builder->insertElement( 'html', new PlainAttributes, false, $pos, 0 );
52        $this->dispatcher->switchMode( Dispatcher::BEFORE_HEAD )
53            ->endDocument( $pos );
54    }
55}