nodeName ) ) { return true; } '@phan-var DOMElement $node'; /** @var DOMElement $node */ // Cannot generate an anchor id if the heading already has an id! // // NOTE: Divergence from PHP parser behavior. // // The PHP parser generates a .. // So, it can preserve the existing id if any. However, in Parsoid, we are // generating a .. => we either overwrite or // preserve the existing id and use it for TOC, etc. We choose to preserve it. if ( $node->hasAttribute( 'id' ) ) { DOMDataUtils::getDataParsoid( $node )->reusedId = true; return true; } $anchorText = Sanitizer::normalizeSectionIdWhiteSpace( self::textContentOf( $node ) ); $anchorText = self::normalizeSectionName( $anchorText, $env ); // Create an anchor with a sanitized id $anchorId = Sanitizer::escapeIdForAttribute( $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 ); 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; } /** * Our own version of node.textContent which handles LanguageVariant * markup the same way PHP does (ie, uses the source wikitext), and * handles