quotes = $quotes;
}
/** @inheritDoc */
public function handle(
DOMElement $node, SerializerState $state, bool $wrapperUnmodified = false
): ?DOMNode {
if ( $this->precedingQuoteEltRequiresEscape( $node ) ) {
WTSUtils::emitStartTag( '', $node, $state );
}
WTSUtils::emitStartTag( $this->quotes, $node, $state );
if ( !$node->hasChildNodes() ) {
// Empty nodes like or need
// a in place of the empty content so that
// they parse back identically.
if ( WTSUtils::emitEndTag( $this->quotes, $node, $state, true ) ) {
WTSUtils::emitStartTag( '', $node, $state );
WTSUtils::emitEndTag( $this->quotes, $node, $state );
}
} else {
$state->serializeChildren( $node );
WTSUtils::emitEndTag( $this->quotes, $node, $state );
}
return $node->nextSibling;
}
/**
* @param DOMElement $node
* @return bool
*/
private function precedingQuoteEltRequiresEscape(
DOMElement $node
): bool {
// * and siblings don't need a separation
// as long as quote chars in text nodes are always
// properly escaped -- which they are right now.
//
// * Adjacent quote siblings need a separation
// between them if either of them will individually
// generate a sequence of quotes 4 or longer. That can
// only happen when either prev or node is of the form:
// ...
//
// For new/edited DOMs, this can never happen because
// wts.minimizeQuoteTags.js does quote tag minimization.
//
// For DOMs from existing wikitext, this can only happen
// because of auto-inserted end/start tags. (Ex: ''a''' b ''c''')
$prev = DOMUtils::previousNonDeletedSibling( $node );
return $prev && DOMUtils::isQuoteElt( $prev )
&& ( DOMUtils::isQuoteElt( DOMUtils::lastNonDeletedChild( $prev ) )
|| DOMUtils::isQuoteElt( DOMUtils::firstNonDeletedChild( $node ) ) );
}
}