Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 42
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 / 42
0.00% covered (danger)
0.00%
0 / 3
110
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 / 23
0.00% covered (danger)
0.00%
0 / 1
56
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        $dataMw->html = $extApi->domToHtml( $domFragment, true );
82
83        // Use a meta tag whose data-mw we will stuff this HTML into later.
84        // NOTE: Till T214994 is resolved, this HTML will not get processed
85        // by all the top-level DOM passes that may need to process this (ex: linting)
86        $meta = $domFragment->ownerDocument->createElement( 'meta' );
87
88        DOMDataUtils::setDataMw( $meta, $dataMw );
89
90        DOMCompat::replaceChildren( $domFragment, $meta );
91        return $domFragment;
92    }
93}