Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
55 / 55 |
|
100.00% |
7 / 7 |
CRAP | |
100.00% |
1 / 1 |
InsertionMode | |
100.00% |
55 / 55 |
|
100.00% |
7 / 7 |
16 | |
100.00% |
1 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
doctype | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
comment | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
error | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
splitInitialMatch | |
100.00% |
19 / 19 |
|
100.00% |
1 / 1 |
4 | |||
handleFramesetWhitespace | |
100.00% |
19 / 19 |
|
100.00% |
1 / 1 |
4 | |||
stripNulls | |
100.00% |
12 / 12 |
|
100.00% |
1 / 1 |
4 | |||
characters | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
startTag | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
endTag | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
endDocument | n/a |
0 / 0 |
n/a |
0 / 0 |
0 |
1 | <?php |
2 | |
3 | namespace Wikimedia\RemexHtml\TreeBuilder; |
4 | |
5 | use Wikimedia\RemexHtml\PropGuard; |
6 | use Wikimedia\RemexHtml\Tokenizer\Attributes; |
7 | |
8 | abstract class InsertionMode { |
9 | use PropGuard; |
10 | |
11 | /** @var TreeBuilder */ |
12 | protected $builder; |
13 | |
14 | /** @var Dispatcher */ |
15 | protected $dispatcher; |
16 | |
17 | public function __construct( TreeBuilder $builder, Dispatcher $dispatcher ) { |
18 | $this->builder = $builder; |
19 | $this->dispatcher = $dispatcher; |
20 | } |
21 | |
22 | public function doctype( $name, $public, $system, $quirks, $sourceStart, $sourceLength ) { |
23 | $this->builder->error( "unexpected doctype", $sourceStart ); |
24 | } |
25 | |
26 | public function comment( $text, $sourceStart, $sourceLength ) { |
27 | $this->builder->comment( null, $text, $sourceStart, $sourceLength ); |
28 | } |
29 | |
30 | public function error( $text, $pos ) { |
31 | $this->builder->error( $text, $pos ); |
32 | } |
33 | |
34 | protected function splitInitialMatch( $isStartOfToken, $mask, $text, $start, $length, |
35 | $sourceStart, $sourceLength |
36 | ) { |
37 | $matchLength = strspn( $text, $mask, $start, $length ); |
38 | if ( $isStartOfToken && $matchLength ) { |
39 | // Do some extra work to figure out a plausible start position if |
40 | // the text node started with <![CDATA[ |
41 | // FIXME: make this optional? |
42 | $sourceText = $this->builder->tokenizer->getPreprocessedText(); |
43 | $isCdata = substr_compare( $sourceText, '<![CDATA[', $sourceStart, $sourceLength ) === 0; |
44 | $cdataLength = $isCdata ? strlen( '<![CDATA[' ) : 0; |
45 | } else { |
46 | $cdataLength = 0; |
47 | } |
48 | |
49 | return [ |
50 | [ |
51 | $start, |
52 | $matchLength, |
53 | $sourceStart, |
54 | $matchLength + $cdataLength, |
55 | ], [ |
56 | $start + $matchLength, |
57 | $length - $matchLength, |
58 | $sourceStart + $matchLength + $cdataLength, |
59 | $sourceLength - $matchLength - $cdataLength |
60 | ] |
61 | ]; |
62 | } |
63 | |
64 | protected function handleFramesetWhitespace( $inBody, $text, $start, $length, |
65 | $sourceStart, $sourceLength |
66 | ) { |
67 | $isStartOfToken = true; |
68 | $builder = $this->builder; |
69 | |
70 | do { |
71 | [ $part1, $part2 ] = $this->splitInitialMatch( |
72 | $isStartOfToken, "\t\n\f\r ", $text, $start, $length, $sourceStart, $sourceLength ); |
73 | $isStartOfToken = false; |
74 | |
75 | [ $start, $length, $sourceStart, $sourceLength ] = $part1; |
76 | if ( $length ) { |
77 | if ( $inBody ) { |
78 | $this->dispatcher->inBody->characters( $text, $start, $length, |
79 | $sourceStart, $sourceLength ); |
80 | } else { |
81 | $builder->insertCharacters( $text, $start, $length, $sourceStart, $sourceLength ); |
82 | } |
83 | } |
84 | |
85 | [ $start, $length, $sourceStart, $sourceLength ] = $part2; |
86 | if ( $length ) { |
87 | $builder->error( "unexpected non-whitespace character", $sourceStart ); |
88 | $start++; |
89 | $length--; |
90 | $sourceStart++; |
91 | $sourceLength--; |
92 | } |
93 | } while ( $length > 0 ); |
94 | } |
95 | |
96 | protected function stripNulls( $callback, $text, $start, $length, $sourceStart, $sourceLength ) { |
97 | $errorOffset = $sourceStart - $start; |
98 | while ( $length > 0 ) { |
99 | $validLength = strcspn( $text, "\0", $start, $length ); |
100 | if ( $validLength ) { |
101 | $callback( $text, $start, $validLength, $sourceStart, $sourceLength ); |
102 | $start += $validLength; |
103 | $length -= $validLength; |
104 | } |
105 | if ( $length <= 0 ) { |
106 | break; |
107 | } |
108 | $this->error( 'unexpected null character', $start + $errorOffset ); |
109 | $start++; |
110 | $length--; |
111 | } |
112 | } |
113 | |
114 | abstract public function characters( $text, $start, $length, $sourceStart, $sourceLength ); |
115 | |
116 | abstract public function startTag( $name, Attributes $attrs, $selfClose, |
117 | $sourceStart, $sourceLength ); |
118 | |
119 | abstract public function endTag( $name, $sourceStart, $sourceLength ); |
120 | |
121 | abstract public function endDocument( $pos ); |
122 | } |