���ѧۧݧ�ӧ�� �ާ֧ߧ֧էا֧� - ���֧էѧܧ�ڧ��ӧѧ�� - /home/rickpfrv/wiki.craftaro.com/vendor/wikimedia/parsoid/src/Wt2Html/PP/Processors/MigrateTrailingNLs.php
���ѧ٧ѧ�
<?php declare( strict_types = 1 ); namespace Wikimedia\Parsoid\Wt2Html\PP\Processors; use Wikimedia\Parsoid\Config\Env; use Wikimedia\Parsoid\DOM\Comment; use Wikimedia\Parsoid\DOM\DocumentFragment; use Wikimedia\Parsoid\DOM\Element; use Wikimedia\Parsoid\DOM\Node; use Wikimedia\Parsoid\DOM\Text; use Wikimedia\Parsoid\NodeData\DataParsoid; use Wikimedia\Parsoid\Utils\DOMCompat; use Wikimedia\Parsoid\Utils\DOMDataUtils; use Wikimedia\Parsoid\Utils\DOMUtils; use Wikimedia\Parsoid\Utils\PHPUtils; use Wikimedia\Parsoid\Utils\WTUtils; use Wikimedia\Parsoid\Wt2Html\Wt2HtmlDOMProcessor; class MigrateTrailingNLs implements Wt2HtmlDOMProcessor { private static $nodesToMigrateFrom; /** * @param Node $node * @param DataParsoid $dp * @return bool */ private function nodeEndsLineInWT( Node $node, DataParsoid $dp ): bool { // These nodes either end a line in wikitext (tr, li, dd, ol, ul, dl, caption, // p) or have implicit closing tags that can leak newlines to those that end a // line (th, td) // // SSS FIXME: Given condition 2, we may not need to check th/td anymore // (if we can rely on auto inserted start/end tags being present always). if ( !isset( self::$nodesToMigrateFrom ) ) { self::$nodesToMigrateFrom = PHPUtils::makeSet( [ 'pre', 'th', 'td', 'tr', 'li', 'dd', 'ol', 'ul', 'dl', 'caption', 'p' ] ); } return isset( self::$nodesToMigrateFrom[DOMCompat::nodeName( $node )] ) && !WTUtils::hasLiteralHTMLMarker( $dp ); } /** * @param Node $node * @return Node|null */ private function getTableParent( Node $node ): ?Node { $nodeName = DOMCompat::nodeName( $node ); if ( in_array( $nodeName, [ 'td', 'th' ], true ) ) { $node = $node->parentNode; $nodeName = DOMCompat::nodeName( $node ); } if ( $nodeName === 'tr' ) { $node = $node->parentNode; $nodeName = DOMCompat::nodeName( $node ); } if ( in_array( $nodeName, [ 'tbody', 'thead', 'tfoot', 'caption' ], true ) ) { $node = $node->parentNode; $nodeName = DOMCompat::nodeName( $node ); } return ( $nodeName === 'table' ) ? $node : null; } /** * We can migrate a newline out of a node if one of the following is true: * (1) The node ends a line in wikitext (=> not a literal html tag) * (2) The node has an auto-closed end-tag (wikitext-generated or literal html tag) * and hasn't been fostered out of a table. * (3) It is the rightmost node in the DOM subtree rooted at a node * that ends a line in wikitext * @param Node $node * @return bool */ private function canMigrateNLOutOfNode( Node $node ): bool { if ( DOMCompat::nodeName( $node ) === 'table' || DOMUtils::atTheTop( $node ) ) { return false; } // Don't allow migration out of a table if the table has had // content fostered out of it. $tableParent = $this->getTableParent( $node ); if ( $tableParent && $tableParent->previousSibling instanceof Element ) { $previousSibling = $tableParent->previousSibling; '@phan-var Element $previousSibling'; // @var Element $previousSibling if ( !empty( DOMDataUtils::getDataParsoid( $previousSibling )->fostered ) ) { return false; } } DOMUtils::assertElt( $node ); $dp = DOMDataUtils::getDataParsoid( $node ); return empty( $dp->fostered ) && ( $this->nodeEndsLineInWT( $node, $dp ) || !empty( $dp->autoInsertedEnd ) || ( !$node->nextSibling && // FIXME: bug compatibility, previously the end meta caused // $node->nextSibling to be true for elements with end tags empty( $dp->tmp->endTSR ) && $node->parentNode && $this->canMigrateNLOutOfNode( $node->parentNode ) ) ); } /** * A node has zero wt width if: * - tsr->start == tsr->end * - only has children with zero wt width * @param Element $node * @return bool */ private function hasZeroWidthWT( Element $node ): bool { $tsr = DOMDataUtils::getDataParsoid( $node )->tsr ?? null; if ( !$tsr || $tsr->start === null || $tsr->start !== $tsr->end ) { return false; } $c = $node->firstChild; while ( $c instanceof Element && $this->hasZeroWidthWT( $c ) ) { $c = $c->nextSibling; } return $c === null; } /** * @param Node $elt * @param Env $env */ public function doMigrateTrailingNLs( Node $elt, Env $env ) { if ( !( $elt instanceof Element ) && !( $elt instanceof DocumentFragment ) ) { return; } // 1. Process DOM rooted at 'elt' first // // Process children backward so that a table // is processed before its fostered content. // See subtle changes in newline migration with this wikitext: // "<table>\n<tr> || ||\n<td> a\n</table>" // when walking backward vs. forward. // // Separately, walking backward also lets us ignore // newly added children after child (because of // migrated newline nodes from child's DOM tree). $child = $elt->lastChild; while ( $child !== null ) { $this->doMigrateTrailingNLs( $child, $env ); $child = $child->previousSibling; } // 2. Process 'elt' itself after -- skip literal-HTML nodes if ( $this->canMigrateNLOutOfNode( $elt ) ) { $firstEltToMigrate = null; $migrationBarrier = null; $partialContent = false; $n = $elt->lastChild; // We can migrate trailing newlines across nodes that have zero-wikitext-width. while ( $n instanceof Element && $this->hasZeroWidthWT( $n ) ) { $migrationBarrier = $n; $n = $n->previousSibling; } $isTdTh = DOMCompat::nodeName( $elt ) === 'td' || DOMCompat::nodeName( $elt ) === 'th'; // Find nodes that need to be migrated out: // - a sequence of comment and newline nodes that is preceded by // a non-migratable node (text node with non-white-space content // or an element node). $foundNL = false; $tsrCorrection = 0; while ( $n instanceof Text || $n instanceof Comment ) { if ( $n instanceof Comment ) { if ( $isTdTh ) { break; } $firstEltToMigrate = $n; $tsrCorrection += WTUtils::decodedCommentLength( $n ); } else { if ( !$isTdTh && preg_match( '/^[ \t\r\n]*\n[ \t\r\n]*$/D', $n->nodeValue ) ) { $foundNL = true; $firstEltToMigrate = $n; $partialContent = false; // all whitespace is moved $tsrCorrection += strlen( $n->nodeValue ); } elseif ( str_ends_with( $n->nodeValue, "\n" ) ) { $foundNL = true; $firstEltToMigrate = $n; $partialContent = true; // only newlines moved preg_match( '/\n+$/D', $n->nodeValue, $matches ); $tsrCorrection += strlen( $matches[0] ?? '' ); break; } else { break; } } $n = $n->previousSibling; } if ( $firstEltToMigrate && $foundNL ) { $eltParent = $elt->parentNode; $insertPosition = $elt->nextSibling; $n = $firstEltToMigrate; while ( $n !== $migrationBarrier ) { $next = $n->nextSibling; if ( $partialContent ) { $nls = $n->nodeValue; $n->nodeValue = preg_replace( '/\n+$/D', '', $n->nodeValue, 1 ); $nls = substr( $nls, strlen( $n->nodeValue ) ); $n = $n->ownerDocument->createTextNode( $nls ); $partialContent = false; } $eltParent->insertBefore( $n, $insertPosition ); $n = $next; } // Adjust tsr of any nodes after migrationBarrier. // Ex: zero-width nodes that have valid tsr on them // By definition (zero-width), these are synthetic nodes added by Parsoid // that aren't present in the original wikitext. $n = $migrationBarrier; while ( $n ) { // TSR is guaranteed to exist and be valid // (checked by hasZeroWidthWT above) DOMUtils::assertElt( $n ); $dp = DOMDataUtils::getDataParsoid( $n ); $dp->tsr = $dp->tsr->offset( -$tsrCorrection ); $n = $n->nextSibling; } } } } /** * @inheritDoc */ public function run( Env $env, Node $root, array $options = [], bool $atTopLevel = false ): void { $this->doMigrateTrailingNLs( $root, $env ); } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | ���֧ߧ֧�ѧ�ڧ� ����ѧߧڧ��: 0.1 |
proxy
|
phpinfo
|
���ѧ����ۧܧ�