Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 121 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
ParserHook | |
0.00% |
0 / 121 |
|
0.00% |
0 / 4 |
702 | |
0.00% |
0 / 1 |
sourceToDom | |
0.00% |
0 / 50 |
|
0.00% |
0 / 1 |
240 | |||
processAttributeEmbeddedDom | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
domToWikitext | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
56 | |||
getConfig | |
0.00% |
0 / 47 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | declare( strict_types = 1 ); |
3 | |
4 | namespace Wikimedia\Parsoid\ParserTests; |
5 | |
6 | use Error; |
7 | use Wikimedia\Parsoid\DOM\DocumentFragment; |
8 | use Wikimedia\Parsoid\DOM\Element; |
9 | use Wikimedia\Parsoid\Ext\ExtensionModule; |
10 | use Wikimedia\Parsoid\Ext\ExtensionTagHandler; |
11 | use Wikimedia\Parsoid\Ext\ParsoidExtensionAPI; |
12 | use Wikimedia\Parsoid\Utils\DOMCompat; |
13 | use Wikimedia\Parsoid\Utils\DOMDataUtils; |
14 | use Wikimedia\Parsoid\Utils\WTUtils; |
15 | |
16 | /** |
17 | * See tests/parser/ParserTestParserHook.php in core. |
18 | */ |
19 | class ParserHook extends ExtensionTagHandler implements ExtensionModule { |
20 | |
21 | /** @inheritDoc */ |
22 | public function sourceToDom( |
23 | ParsoidExtensionAPI $extApi, string $content, array $args |
24 | ): DocumentFragment { |
25 | $extName = $extApi->extTag->getName(); |
26 | if ( $extApi->extTag->isSelfClosed() ) { |
27 | $content = null; |
28 | } |
29 | switch ( $extName ) { |
30 | case 'tag': |
31 | case 'tåg': |
32 | return $extApi->htmlToDom( |
33 | "<pre>\n" . |
34 | var_export( $content, true ) . "\n" . |
35 | var_export( $extApi->extArgsToArray( $args ), true ) . "\n" . |
36 | "</pre>" |
37 | ); |
38 | |
39 | case 'statictag': |
40 | // FIXME: Choose a better DOM representation that doesn't mess with |
41 | // newline constraints. |
42 | return $extApi->htmlToDom( '<span />' ); |
43 | |
44 | case 'asidetag': |
45 | // T278565 |
46 | return $extApi->htmlToDom( '<aside>Some aside content</aside>' ); |
47 | |
48 | case 'pwraptest': |
49 | return $extApi->htmlToDom( '<!--CMT--><style>p{}</style>' ); |
50 | |
51 | case 'divtag': |
52 | case 'spantag': |
53 | // "Transparent" tag which wraps wikitext in a <span> or <div>; |
54 | // useful in testing various parsoid wrapping scenarios |
55 | // (we used to use <ref> for this) |
56 | // |
57 | // NOTE: When using <spantag>, p-wrapping and indent-pre |
58 | // transforms are disabled. |
59 | $argArray = $extApi->extArgsToArray( $args ); |
60 | $isDiv = ( $extName === 'divtag' ); |
61 | $isRaw = $argArray['raw'] ?? false; |
62 | $tag = $isDiv ? 'div' : 'span'; |
63 | if ( $isRaw ) { |
64 | return $extApi->htmlToDom( "<$tag>$content</$tag>" ); |
65 | } |
66 | return $extApi->extTagToDOM( $args, $content, [ |
67 | 'wrapperTag' => $tag, |
68 | 'parseOpts' => [ |
69 | 'extTag' => $extName, |
70 | 'context' => $isDiv ? 'block' : 'inline', |
71 | ], |
72 | ] ); |
73 | |
74 | case 'embedtag': |
75 | $dataMw = $extApi->extTag->getDefaultDataMw(); |
76 | $domFragment = $extApi->extTagToDOM( $args, $content, [ |
77 | 'parseOpts' => [ |
78 | 'extTag' => $extName, |
79 | 'context' => 'inline', |
80 | ], |
81 | ] ); |
82 | $dataMw->body = (object)[ |
83 | 'html' => $extApi->domToHtml( $domFragment, true ) |
84 | ]; |
85 | $span = $domFragment->ownerDocument->createElement( 'span' ); |
86 | DOMDataUtils::setDataMw( $span, $dataMw ); |
87 | DOMCompat::replaceChildren( $domFragment, $span ); |
88 | return $domFragment; |
89 | |
90 | case 'sealtag': |
91 | return $extApi->htmlToDom( '<span />' ); |
92 | |
93 | default: |
94 | throw new Error( "Unexpected tag name: $extName in ParserHook" ); |
95 | } |
96 | } |
97 | |
98 | /** @inheritDoc */ |
99 | public function processAttributeEmbeddedDom( |
100 | ParsoidExtensionAPI $extApi, Element $elt, callable $proc |
101 | ): void { |
102 | $dataMw = DOMDataUtils::getDataMw( $elt ); |
103 | if ( isset( $dataMw->body->html ) ) { |
104 | $dom = $extApi->htmlToDom( $dataMw->body->html ); |
105 | $ret = $proc( $dom ); |
106 | if ( $ret ) { |
107 | $dataMw->body->html = $extApi->domToHtml( $dom, true, true ); |
108 | } |
109 | } |
110 | } |
111 | |
112 | /** @inheritDoc */ |
113 | public function domToWikitext( |
114 | ParsoidExtensionAPI $extApi, Element $node, bool $wrapperUnmodified |
115 | ) { |
116 | $dataMw = DOMDataUtils::getDataMw( $node ); |
117 | $extName = WTUtils::getExtTagName( $node ) ?? $dataMw->name; |
118 | if ( !in_array( $extName, [ 'spantag', 'divtag', 'embedtag' ], true ) ) { |
119 | return false; // use default serialization |
120 | } |
121 | if ( in_array( $extName, [ 'spantag', 'divtag' ], true ) ) { |
122 | if ( $dataMw->attrs->raw ?? false ) { |
123 | return false; // use default serialization in 'raw' mode |
124 | } |
125 | } |
126 | $html2wtOpts = [ |
127 | 'extName' => $extName, |
128 | // FIXME: One-off PHP parser state leak. This needs a better solution. |
129 | 'inPHPBlock' => true |
130 | ]; |
131 | $src = ''; |
132 | if ( $wrapperUnmodified && isset( $dataMw->body->extsrc ) ) { |
133 | $src = $dataMw->body->extsrc; |
134 | } elseif ( $extName === 'embedtag' ) { |
135 | // First look for the extension's content in data-mw.body.html |
136 | $src = $extApi->htmlToWikitext( $html2wtOpts, $dataMw->body->html ); |
137 | } else { |
138 | $src = $extApi->htmlToWikitext( $html2wtOpts, DOMCompat::getInnerHTML( $node ) ); |
139 | } |
140 | return "<$extName>" . $src . "</$extName>"; |
141 | } |
142 | |
143 | /** @inheritDoc */ |
144 | public function getConfig(): array { |
145 | return [ |
146 | 'name' => 'ParserHook', |
147 | 'tags' => [ |
148 | [ 'name' => 'tag', 'handler' => self::class ], |
149 | [ 'name' => 'tåg', 'handler' => self::class ], |
150 | [ 'name' => 'statictag', 'handler' => self::class ], |
151 | [ 'name' => 'asidetag', 'handler' => self::class ], |
152 | [ 'name' => 'pwraptest', 'handler' => self::class ], |
153 | [ |
154 | 'name' => 'divtag', |
155 | 'handler' => self::class, |
156 | 'options' => [ |
157 | 'outputHasCoreMwDomSpecMarkup' => true, |
158 | ], |
159 | ], |
160 | [ |
161 | 'name' => 'spantag', |
162 | 'handler' => self::class, |
163 | 'options' => [ |
164 | 'outputHasCoreMwDomSpecMarkup' => true, |
165 | ], |
166 | ], |
167 | [ |
168 | 'name' => 'embedtag', |
169 | 'handler' => self::class, |
170 | 'options' => [ |
171 | 'wt2html' => [ |
172 | 'embedsDomInAttributes' => true, |
173 | 'customizesDataMw' => true, |
174 | ], |
175 | 'outputHasCoreMwDomSpecMarkup' => true, |
176 | ], |
177 | ], |
178 | [ |
179 | 'name' => 'sealtag', |
180 | 'handler' => self::class, |
181 | 'options' => [ |
182 | 'wt2html' => [ |
183 | 'unpackOutput' => false, |
184 | ], |
185 | ], |
186 | ], |
187 | ], |
188 | 'domProcessors' => [ |
189 | ParserHookProcessor::class |
190 | ] |
191 | ]; |
192 | } |
193 | } |