Файловый менеджер - Редактировать - /var/www/html/mediawiki-1.43.1/vendor/wikimedia/parsoid/src/Wt2Html/DOM/Handlers/Headings.php
Ðазад
<?php declare( strict_types = 1 ); namespace Wikimedia\Parsoid\Wt2Html\DOM\Handlers; use Wikimedia\Parsoid\Config\Env; use Wikimedia\Parsoid\Core\DomSourceRange; use Wikimedia\Parsoid\Core\Sanitizer; use Wikimedia\Parsoid\DOM\Element; use Wikimedia\Parsoid\DOM\Node; use Wikimedia\Parsoid\DOM\Text; use Wikimedia\Parsoid\Utils\DOMCompat; use Wikimedia\Parsoid\Utils\DOMDataUtils; use Wikimedia\Parsoid\Utils\DOMUtils; use Wikimedia\Parsoid\Utils\DTState; use Wikimedia\Parsoid\Utils\TitleException; use Wikimedia\Parsoid\Utils\Utils; use Wikimedia\Parsoid\Utils\WTUtils; class Headings { /** * See the safe-heading transform code in Parser::finalizeHeadings in core * * Allowed HTML tags are: * - <sup> and <sub> (T10393) * - <i> (T28375) * - <b> (r105284) * - <bdi> (T74884) * - <span dir="rtl"> and <span dir="ltr"> (T37167) * (handled separately in code below) * - <s> and <strike> (T35715) * - <q> (T251672) */ private const ALLOWED_NODES_IN_ANCHOR = [ 'span', 'sup', 'sub', 'i', 'b', 'bdi', 's', 'strike', 'q' ]; /** * This method implements the equivalent of the regexp-based safe-headline * transform in Parser::finalizeHeadings in core. * * @param Node $node */ private static function processHeadingContent( Node $node ): void { $c = $node->firstChild; while ( $c ) { $next = $c->nextSibling; if ( $c instanceof Element ) { $cName = DOMCompat::nodeName( $c ); if ( DOMUtils::hasTypeOf( $c, 'mw:LanguageVariant' ) ) { // Special case for -{...}- $dp = DOMDataUtils::getDataParsoid( $c ); $node->replaceChild( $node->ownerDocument->createTextNode( $dp->src ?? '' ), $c ); } elseif ( in_array( $cName, [ 'style', 'script' ], true ) ) { # Remove any <style> or <script> tags (T198618) $node->removeChild( $c ); } else { self::processHeadingContent( $c ); if ( !$c->firstChild ) { // Empty now - strip it! $node->removeChild( $c ); } elseif ( !in_array( $cName, self::ALLOWED_NODES_IN_ANCHOR, true ) || ( $cName === 'span' && DOMUtils::hasTypeOf( $c, 'mw:Entity' ) ) ) { # Strip all unallowed tag wrappers DOMUtils::migrateChildren( $c, $node, $next ); $next = $c->nextSibling; $node->removeChild( $c ); } else { # We strip any parameter from accepted tags except dir="rtl|ltr" from <span>, # to allow setting directionality in toc items. foreach ( DOMUtils::attributes( $c ) as $key => $val ) { if ( $cName === 'span' ) { if ( $key !== 'dir' || ( $val !== 'ltr' && $val !== 'rtl' ) ) { $c->removeAttribute( $key ); } } else { $c->removeAttribute( $key ); } } } } } elseif ( !( $c instanceof Text ) ) { // Strip everying else but text nodes $node->removeChild( $c ); } $c = $next; } } /** * Generate anchor ids that the PHP parser assigns to headings. * This is to ensure that links that are out there in the wild * continue to be valid links into Parsoid HTML. * @param Node $node * @param DTState $state * @return bool */ public static function genAnchors( Node $node, DTState $state ): bool { if ( !DOMUtils::isHeading( $node ) ) { return true; } '@phan-var Element $node'; /** @var Element $node */ // Deep clone the heading to mutate it to strip unwanted tags and attributes. $clone = DOMDataUtils::cloneNode( $node, true ); '@phan-var Element $clone'; // @var Element $clone // Don't bother storing data-attribs on $clone, // processHeadingContent is about to strip them self::processHeadingContent( $clone ); $buf = DOMCompat::getInnerHTML( $clone ); $line = trim( $buf ); $dp = DOMDataUtils::getDataParsoid( $node ); $tmp = $dp->getTemp(); // Cannot generate an anchor id if the heading already has an id! // // NOTE: Divergence from PHP parser behavior. // // The PHP parser generates a <h*><span id="anchor-id-here-">..</span><h*> // So, it can preserve the existing id if any. However, in Parsoid, we are // generating a <h* id="anchor-id-here"> ..</h*> => we either overwrite or // preserve the existing id and use it for TOC, etc. We choose to preserve it. if ( $node->hasAttribute( 'id' ) ) { $linkAnchorId = DOMCompat::getAttribute( $node, 'id' ); $dp->reusedId = true; $tmp->section = [ 'line' => $line, 'linkAnchor' => $linkAnchorId, ]; return true; } // Additional processing for $anchor $anchorText = $clone->textContent; // strip all tags $anchorText = Sanitizer::normalizeSectionNameWhiteSpace( $anchorText ); $anchorText = self::normalizeSectionName( $anchorText, $state->env ); # NOTE: Parsoid defaults to html5 mode. So, if we want to replicate # legacy output, we should handle that explicitly. $anchorId = Sanitizer::escapeIdForAttribute( $anchorText ); $linkAnchorId = Sanitizer::escapeIdForLink( $anchorText ); $fallbackId = Sanitizer::escapeIdForAttribute( $anchorText, Sanitizer::ID_FALLBACK ); if ( $anchorId === $fallbackId ) { $fallbackId = null; /* not needed */ } // The ids need to be unique, but we'll enforce this in a post-processing step. $node->setAttribute( 'id', $anchorId ); $tmp->section = [ 'line' => $line, 'linkAnchor' => $linkAnchorId, ]; if ( $fallbackId ) { $span = $node->ownerDocument->createElement( 'span' ); $span->setAttribute( 'id', $fallbackId ); DOMUtils::addTypeOf( $span, 'mw:FallbackId' ); $nodeDsr = DOMDataUtils::getDataParsoid( $node )->dsr ?? null; // Set a zero-width dsr range for the fallback id if ( Utils::isValidDSR( $nodeDsr ) ) { $offset = $nodeDsr->innerStart(); DOMDataUtils::getDataParsoid( $span )->dsr = new DomSourceRange( $offset, $offset, null, null ); } $node->insertBefore( $span, $node->firstChild ); } return true; } /** * see Parser::normalizeSectionName in Parser.php and T90902 * @param string $text * @param Env $env * @return string */ private static function normalizeSectionName( string $text, Env $env ): string { try { $title = $env->makeTitleFromURLDecodedStr( "#{$text}" ); return $title->getFragment(); } catch ( TitleException $e ) { return $text; } } public static function dedupeHeadingIds( Node $node, DTState $state ): bool { // NOTE: This is not completely compliant with how PHP parser does it. // If there is an id in the doc elsewhere, this will assign // the heading a suffixed id, whereas the PHP parser processes // headings in textual order and can introduce duplicate ids // in a document in the process. // // However, we believe this implementation behavior is more // consistent when handling this edge case, and in the common // case (where heading ids won't conflict with ids elsewhere), // matches PHP parser behavior. // FIXME: Maybe we should lint this issue away if ( !$node instanceof Element ) { // Not an Element return true; } $origKey = DOMCompat::getAttribute( $node, 'id' ); if ( $origKey === null ) { return true; } // IE 7 required attributes to be case-insensitively unique (T12721) // but it did not support non-ASCII IDs. We don't support IE 7 anymore, // but changing the algorithm would change the relevant fragment URLs. // This case folding and matching algorithm has to stay exactly the // same to preserve external links to the page. $key = strtolower( $origKey ); $seenIds = &$state->seenIds; if ( !isset( $seenIds[$key] ) ) { $seenIds[$key] = 1; return true; } // Only update headings and legacy links (first children of heading) $isHeading = DOMUtils::isHeading( $node ); if ( $isHeading || WTUtils::isFallbackIdSpan( $node ) ) { $suffix = ++$seenIds[$key]; while ( !empty( $seenIds[$key . '_' . $suffix] ) ) { $suffix++; $seenIds[$key]++; } $node->setAttribute( 'id', $origKey . '_' . $suffix ); if ( $isHeading ) { $tmp = DOMDataUtils::getDataParsoid( $node )->getTemp(); $linkAnchorId = $tmp->section['linkAnchor']; $tmp->section['linkAnchor'] = $linkAnchorId . '_' . $suffix; } $seenIds[$key . '_' . $suffix] = 1; } return true; } }
| ver. 1.1 | |
.
| PHP 8.4.18 | Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñтраницы: 0 |
proxy
|
phpinfo
|
ÐаÑтройка