Файловый менеджер - Редактировать - /var/www/html/mediawiki-1.43.1/vendor/wikimedia/parsoid/src/Wt2Html/TT/ExtensionHandler.php
Ðазад
<?php declare( strict_types = 1 ); namespace Wikimedia\Parsoid\Wt2Html\TT; use Wikimedia\Assert\Assert; use Wikimedia\Assert\UnreachableException; use Wikimedia\Parsoid\Config\SiteConfig; use Wikimedia\Parsoid\DOM\DocumentFragment; use Wikimedia\Parsoid\Ext\ExtensionError; use Wikimedia\Parsoid\Ext\ExtensionTag; use Wikimedia\Parsoid\Ext\ParsoidExtensionAPI; use Wikimedia\Parsoid\NodeData\DataMw; use Wikimedia\Parsoid\NodeData\DataMwError; use Wikimedia\Parsoid\Tokens\Token; use Wikimedia\Parsoid\Utils\DOMDataUtils; use Wikimedia\Parsoid\Utils\DOMUtils; use Wikimedia\Parsoid\Utils\PipelineUtils; use Wikimedia\Parsoid\Utils\TokenUtils; use Wikimedia\Parsoid\Utils\Utils; use Wikimedia\Parsoid\Utils\WTUtils; use Wikimedia\Parsoid\Wt2Html\TokenTransformManager; class ExtensionHandler extends TokenHandler { public function __construct( TokenTransformManager $manager, array $options ) { parent::__construct( $manager, $options ); } private static function normalizeExtOptions( array $options ): array { // Mimics Sanitizer::decodeTagAttributes from the PHP parser // // Extension options should always be interpreted as plain text. The // tokenizer parses them to tokens in case they are for an HTML tag, // but here we use the text source instead. $n = count( $options ); for ( $i = 0; $i < $n; $i++ ) { $o = $options[$i]; // Use the source if present. If not use the value, but ensure it's a // string, as it can be a token stream if the parser has recognized it // as a directive. $v = $o->vsrc ?? TokenUtils::tokensToString( $o->v, false, [ 'includeEntities' => true ] ); // Normalize whitespace in extension attribute values // FIXME: If the option is parsed as wikitext, this normalization // can mess with src offsets. $o->v = trim( preg_replace( '/[\t\r\n ]+/', ' ', $v ) ); // Decode character references $o->v = Utils::decodeWtEntities( $o->v ); } return $options; } private function onExtension( Token $token ): TokenHandlerResult { $env = $this->env; $siteConfig = $env->getSiteConfig(); $pageConfig = $env->getPageConfig(); $extensionName = $token->getAttributeV( 'name' ); $extConfig = $env->getSiteConfig()->getExtTagConfig( $extensionName ); $metrics = $siteConfig->metrics(); if ( $metrics ) { // Track uses of extensions $wiki = $siteConfig->iwp(); $ns = $env->getContextTitle()->getNamespace(); if ( $ns === 0 ) { // Article space $nsName = 'main'; } elseif ( $siteConfig->namespaceIsTalk( $ns ) ) { // Any talk namespace $nsName = 'talk'; } else { // Everything else $nsName = "ns-$ns"; } $metrics->increment( "extension.{$wiki}.{$nsName}.{$extensionName}" ); $siteConfig->incrementCounter( "extension_total", [ "wiki" => $wiki, "namespace" => $nsName, "name" => $extensionName, ] ); } $nativeExt = $siteConfig->getExtTagImpl( $extensionName ); $cachedExpansion = $env->extensionCache[$token->dataParsoid->src] ?? null; $options = $token->getAttributeV( 'options' ); $token->setAttribute( 'options', self::normalizeExtOptions( $options ) ); // Call after normalizing extension options, since that can affect the result $dataMw = Utils::getExtArgInfo( $token ); if ( $nativeExt !== null ) { $extArgs = $token->getAttributeV( 'options' ); $extApi = new ParsoidExtensionAPI( $env, [ 'wt2html' => [ 'frame' => $this->manager->getFrame(), 'parseOpts' => $this->options, 'extTag' => new ExtensionTag( $token ), ], ] ); try { $extSrc = $dataMw->body->extsrc ?? ''; if ( !( $extConfig['options']['hasWikitextInput'] ?? true ) ) { $extSrc = $this->stripAnnotations( $extSrc, $env->getSiteConfig() ); } $domFragment = $nativeExt->sourceToDom( $extApi, $extSrc ?? '', $extArgs ); $errors = $extApi->getErrors(); if ( $extConfig['options']['wt2html']['customizesDataMw'] ?? false ) { $firstNode = $domFragment->firstChild; DOMUtils::assertElt( $firstNode ); $dataMw = DOMDataUtils::getDataMw( $firstNode ); } } catch ( ExtensionError $e ) { $domFragment = WTUtils::createInterfaceI18nFragment( $env->topLevelDoc, $e->err->key, $e->err->params ?: null ); $errors = [ $e->err ]; // FIXME: Should we include any errors collected // from $extApi->getErrors() here? Also, what's the correct $dataMw // to apply in this case? } if ( $domFragment !== false ) { if ( $domFragment !== null ) { // Turn this document fragment into a token $toks = $this->onDocumentFragment( $token, $domFragment, $dataMw, $errors ); return new TokenHandlerResult( $toks ); } else { // The extension dropped this instance completely (!!) // Should be a rarity and presumably the extension // knows what it is doing. Ex: nested refs are dropped // in some scenarios. return new TokenHandlerResult( [] ); } } // Fall through: this extension is electing not to use // a custom sourceToDom method (by returning false from // sourceToDom). } if ( $cachedExpansion ) { // WARNING: THIS HAS BEEN UNUSED SINCE 2015, SEE T98995. // THIS CODE WAS WRITTEN BUT APPARENTLY NEVER TESTED. // NO WARRANTY. MAY HALT AND CATCH ON FIRE. throw new UnreachableException( 'Should not be here!' ); /* $toks = PipelineUtils::encapsulateExpansionHTML( $env, $token, $cachedExpansion, [ 'fromCache' => true ] ); */ } else { $start = microtime( true ); $domFragment = PipelineUtils::fetchHTML( $env, $token->getAttributeV( 'source' ) ); if ( $env->profiling() ) { $profile = $env->getCurrentProfile(); $profile->bumpMWTime( "Extension", 1000 * ( microtime( true ) - $start ), "api" ); $profile->bumpCount( "Extension" ); } if ( !$domFragment ) { $domFragment = DOMUtils::parseHTMLToFragment( $env->topLevelDoc, '' ); } $toks = $this->onDocumentFragment( $token, $domFragment, $dataMw, [] ); } return new TokenHandlerResult( $toks ); } /** * DOMFragment-based encapsulation * * @param Token $extToken * @param DocumentFragment $domFragment * @param DataMw $dataMw * @param list<DataMwError> $errors * @return array */ private function onDocumentFragment( Token $extToken, DocumentFragment $domFragment, DataMw $dataMw, array $errors ): array { $env = $this->env; $extensionName = $extToken->getAttributeV( 'name' ); if ( $env->hasDumpFlag( 'extoutput' ) ) { $logger = $env->getSiteConfig()->getLogger(); $logger->warning( str_repeat( '=', 80 ) ); $logger->warning( 'EXTENSION INPUT: ' . $extToken->getAttributeV( 'source' ) ); $logger->warning( str_repeat( '=', 80 ) ); $logger->warning( "EXTENSION OUTPUT:\n" ); $logger->warning( DOMUtils::getFragmentInnerHTML( $domFragment ) ); $logger->warning( str_repeat( '-', 80 ) ); } $opts = [ 'setDSR' => true, 'wrapperName' => $extensionName, ]; // Check if the tag wants its DOM fragment not to be unpacked. // The default setting is to unpack the content DOM fragment automatically. $extConfig = $env->getSiteConfig()->getExtTagConfig( $extensionName ); if ( isset( $extConfig['options']['wt2html'] ) ) { $opts += $extConfig['options']['wt2html']; } // This special case is only because, from the beginning, Parsoid has // treated <nowiki>s as core functionality with lean markup (no about, // no data-mw, custom typeof). // // We'll keep this hardcoded to avoid exposing the functionality to // other native extensions until it's needed. if ( $extensionName !== 'nowiki' ) { if ( !$domFragment->hasChildNodes() ) { // RT extensions expanding to nothing. $domFragment->appendChild( $domFragment->ownerDocument->createElement( 'link' ) ); } // Wrap the top-level nodes so that we have a firstNode element // to annotate with the typeof and to apply about ids. PipelineUtils::addSpanWrappers( $domFragment->childNodes ); // Now get the firstNode $firstNode = $domFragment->firstChild; DOMUtils::assertElt( $firstNode ); // Adds the wrapper attributes to the first element DOMUtils::addTypeOf( $firstNode, "mw:Extension/{$extensionName}" ); // FIXME: What happens if $firstNode is template generated, since // they have higher precedence? These questions and more in T214241 Assert::invariant( !DOMUtils::hasTypeOf( $firstNode, 'mw:Transclusion' ), 'First node of extension content is transcluded.' ); if ( count( $errors ) > 0 ) { DOMUtils::addTypeOf( $firstNode, 'mw:Error' ); $dataMw->errors = is_array( $dataMw->errors ?? null ) ? array_merge( $dataMw->errors, $errors ) : $errors; } // Set data-mw // FIXME: Similar to T214241, we're clobbering $firstNode DOMDataUtils::setDataMw( $firstNode, $dataMw ); // Add about to all wrapper tokens. $about = $env->newAboutId(); $n = $firstNode; while ( $n ) { $n->setAttribute( 'about', $about ); $n = $n->nextSibling; } // Update data-parsoid $dp = DOMDataUtils::getDataParsoid( $firstNode ); $dp->tsr = clone $extToken->dataParsoid->tsr; $dp->src = $extToken->dataParsoid->src; DOMDataUtils::setDataParsoid( $firstNode, $dp ); } return PipelineUtils::tunnelDOMThroughTokens( $env, $extToken, $domFragment, $opts ); } /** * @inheritDoc */ public function onTag( Token $token ): ?TokenHandlerResult { return $token->getName() === 'extension' ? $this->onExtension( $token ) : null; } private function stripAnnotations( string $s, SiteConfig $siteConfig ): string { $annotationStrippers = $siteConfig->getAnnotationStrippers(); $res = $s; foreach ( $annotationStrippers as $annotationStripper ) { $res = $annotationStripper->stripAnnotations( $s ); } return $res; } }
| ver. 1.1 | |
.
| PHP 8.4.18 | Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñтраницы: 0 |
proxy
|
phpinfo
|
ÐаÑтройка