Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
ListHandler
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 4
306
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 handle
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
42
 before
0.00% covered (danger)
0.00%
0 / 14
0.00% covered (danger)
0.00%
0 / 1
90
 after
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2declare( strict_types = 1 );
3
4namespace Wikimedia\Parsoid\Html2Wt\DOMHandlers;
5
6use Wikimedia\Parsoid\DOM\Element;
7use Wikimedia\Parsoid\DOM\Node;
8use Wikimedia\Parsoid\Html2Wt\SerializerState;
9use Wikimedia\Parsoid\Utils\DOMCompat;
10use Wikimedia\Parsoid\Utils\DOMUtils;
11use Wikimedia\Parsoid\Utils\WTUtils;
12
13class ListHandler extends DOMHandler {
14
15    /** @var string[] List of tag names which van be first children of the list */
16    public $firstChildNames;
17
18    /**
19     * @param string[] $firstChildNames List of tag names which van be first children of the list
20     */
21    public function __construct( array $firstChildNames ) {
22        parent::__construct( true );
23        $this->firstChildNames = $firstChildNames;
24    }
25
26    /** @inheritDoc */
27    public function handle(
28        Element $node, SerializerState $state, bool $wrapperUnmodified = false
29    ): ?Node {
30        // Disable single-line context here so that separators aren't
31        // suppressed between nested list elements.
32        $state->singleLineContext->disable();
33
34        $firstChildElt = DOMUtils::firstNonSepChild( $node );
35
36        // Skip builder-inserted wrappers
37        // Ex: <ul><s auto-inserted-start-and-end-><li>..</li><li>..</li></s>...</ul>
38        // output from: <s>\n*a\n*b\n*c</s>
39        while ( $firstChildElt && $this->isBuilderInsertedElt( $firstChildElt ) ) {
40            $firstChildElt = DOMUtils::firstNonSepChild( $firstChildElt );
41        }
42
43        if ( !$firstChildElt || !in_array( DOMCompat::nodeName( $firstChildElt ), $this->firstChildNames, true )
44            || WTUtils::isLiteralHTMLNode( $firstChildElt )
45        ) {
46            $state->emitChunk( $this->getListBullets( $state, $node ), $node );
47        }
48
49        $liHandler = static function ( $state, $text, $opts ) use ( $node ) {
50            return $state->serializer->wteHandlers->liHandler( $node, $state, $text, $opts );
51        };
52        $state->serializeChildren( $node, $liHandler );
53        $state->singleLineContext->pop();
54        return $node->nextSibling;
55    }
56
57    /** @inheritDoc */
58    public function before( Element $node, Node $otherNode, SerializerState $state ): array {
59        if ( DOMUtils::atTheTop( $otherNode ) ) {
60            return [ 'min' => 0, 'max' => 0 ];
61        }
62
63        // node is in a list & otherNode has the same list parent
64        // => exactly 1 newline
65        if ( DOMUtils::isListItem( $node->parentNode ) && $otherNode->parentNode === $node->parentNode ) {
66            return [ 'min' => 1, 'max' => 1 ];
67        }
68
69        // A list in a block node (<div>, <td>, etc) doesn't need a leading empty line
70        // if it is the first non-separator child (ex: <div><ul>...</div>)
71        if (
72            DOMUtils::isWikitextBlockNode( $node->parentNode ) &&
73            DOMUtils::firstNonSepChild( $node->parentNode ) === $node
74        ) {
75            return [ 'min' => 1, 'max' => 2 ];
76        } elseif ( DOMUtils::isFormattingElt( $otherNode ) ) {
77            return [ 'min' => 1, 'max' => 1 ];
78        } else {
79            return [
80                'min' => WTUtils::isNewElt( $node ) && !WTUtils::isMarkerAnnotation( $otherNode )
81                    ? 2 : 1,
82                'max' => 2
83            ];
84        }
85    }
86
87    /** @inheritDoc */
88    public function after( Element $node, Node $otherNode, SerializerState $state ): array {
89        return $this->wtListEOL( $node, $otherNode );
90    }
91
92}