Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 46
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
Indicator
0.00% covered (danger)
0.00%
0 / 46
0.00% covered (danger)
0.00%
0 / 3
132
0.00% covered (danger)
0.00%
0 / 1
 getConfig
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
2
 processAttributeEmbeddedHTML
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 sourceToDom
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
72
1<?php
2declare( strict_types = 1 );
3
4namespace Wikimedia\Parsoid\Ext\Indicator;
5
6use Closure;
7use Wikimedia\Parsoid\DOM\DocumentFragment;
8use Wikimedia\Parsoid\DOM\Element;
9use Wikimedia\Parsoid\Ext\DiffDOMUtils;
10use Wikimedia\Parsoid\Ext\DOMDataUtils;
11use Wikimedia\Parsoid\Ext\DOMUtils;
12use Wikimedia\Parsoid\Ext\ExtensionModule;
13use Wikimedia\Parsoid\Ext\ExtensionTagHandler;
14use Wikimedia\Parsoid\Ext\ParsoidExtensionAPI;
15use Wikimedia\Parsoid\Utils\DOMCompat;
16
17/**
18 * Implements the php parser's `indicator` hook natively.
19 */
20class Indicator extends ExtensionTagHandler implements ExtensionModule {
21    /** @inheritDoc */
22    public function getConfig(): array {
23        return [
24            'name' => 'Indicator',
25            'tags' => [
26                [
27                    'name' => 'indicator',
28                    'handler' => self::class,
29                    'options' => [
30                        'wt2html' => [
31                            'embedsHTMLInAttributes' => true,
32                            'customizesDataMw' => true,
33                        ],
34                        'outputHasCoreMwDomSpecMarkup' => true
35                    ],
36                ]
37            ],
38        ];
39    }
40
41    /** @inheritDoc */
42    public function processAttributeEmbeddedHTML(
43        ParsoidExtensionAPI $extApi, Element $elt, Closure $proc
44    ): void {
45        $dmw = DOMDataUtils::getDataMw( $elt );
46        if ( isset( $dmw->html ) ) {
47            $dmw->html = $proc( $dmw->html );
48        }
49    }
50
51    /** @inheritDoc */
52    public function sourceToDom(
53        ParsoidExtensionAPI $extApi, string $content, array $args
54    ): DocumentFragment {
55        $dataMw = $extApi->extTag->getDefaultDataMw();
56        $kvArgs = $extApi->extArgsToArray( $args );
57        $name = $kvArgs['name'] ?? '';
58        if ( trim( $name ) === '' ) {
59            $out = $extApi->pushError( 'invalid-indicator-name' );
60            DOMDataUtils::setDataMw( $out->firstChild, $dataMw );
61            return $out;
62        }
63
64        // Convert indicator wikitext to DOM
65        $domFragment = $extApi->extTagToDOM( [] /* No args to apply */, $content, [
66                'parseOpts' => [ 'extTag' => 'indicator' ],
67            ] );
68
69        // Strip an outer paragraph if it is the sole paragraph without additional attributes
70        $content = DiffDOMUtils::firstNonSepChild( $domFragment );
71        if ( $content &&
72            DOMCompat::nodeName( $content ) === 'p' &&
73            DiffDOMUtils::nextNonSepSibling( $content ) === null &&
74            $content instanceof Element && // Needed to mollify Phan
75            DOMDataUtils::noAttrs( $content )
76        ) {
77            DOMUtils::migrateChildren( $content, $domFragment, $content->nextSibling );
78            $domFragment->removeChild( $content );
79        }
80
81        // Save HTML and remove content from the fragment
82        $dataMw->html = $extApi->domToHtml( $domFragment, true );
83
84        $c = $domFragment->firstChild;
85        while ( $c ) {
86            $domFragment->removeChild( $c );
87            $c = $domFragment->firstChild;
88        }
89
90        // Use a meta tag whose data-mw we will stuff this HTML into later.
91        // NOTE: Till T214994 is resolved, this HTML will not get processed
92        // by all the top-level DOM passes that may need to process this (ex: linting)
93        $meta = $domFragment->ownerDocument->createElement( 'meta' );
94
95        DOMDataUtils::setDataMw( $meta, $dataMw );
96
97        // Append meta
98        $domFragment->appendChild( $meta );
99
100        return $domFragment;
101    }
102}