All extension DOM processors should extend Ext\DOMProcessor

Change-Id: Ide9700747b3ecea9da59911c6eb342569be4c9b8
This commit is contained in:
C. Scott Ananian 2020-04-21 19:22:30 -04:00 committed by Subramanya Sastry
parent ded8bd5d74
commit 4f16aee1b5
2 changed files with 82 additions and 85 deletions

View file

@ -4,12 +4,10 @@ declare( strict_types = 1 );
namespace Wikimedia\Parsoid\Ext\Poem;
use DOMDocument;
use DOMElement;
use Wikimedia\Parsoid\Ext\ExtensionModule;
use Wikimedia\Parsoid\Ext\ExtensionTagHandler;
use Wikimedia\Parsoid\Ext\ParsoidExtensionAPI;
use Wikimedia\Parsoid\Utils\DOMCompat;
use Wikimedia\Parsoid\Utils\DOMUtils;
class Poem extends ExtensionTagHandler implements ExtensionModule {
@ -18,7 +16,7 @@ class Poem extends ExtensionTagHandler implements ExtensionModule {
return [
'name' => 'Poem',
'domProcessors' => [
'wt2htmlPostProcessor' => self::class
PoemProcessor::class,
],
'tags' => [
[
@ -129,86 +127,4 @@ class Poem extends ExtensionTagHandler implements ExtensionModule {
]
);
}
/**
* @param DOMElement $node
*/
private function processNowikis( DOMElement $node ): void {
$doc = $node->ownerDocument;
$c = $node->firstChild;
while ( $c ) {
if ( !$c instanceof DOMElement ) {
$c = $c->nextSibling;
continue;
}
if ( !preg_match( '/\bmw:Nowiki\b/', $c->getAttribute( 'typeof' ) ?? '' ) ) {
self::processNowikis( $c );
$c = $c->nextSibling;
continue;
}
// Replace the nowiki's text node with a combination
// of content and <br/>s. Take care to deal with
// entities that are still entity-wrapped (!!).
$cc = $c->firstChild;
while ( $cc ) {
$next = $cc->nextSibling;
if ( DOMUtils::isText( $cc ) ) {
$pieces = preg_split( '/\n/', $cc->nodeValue );
$n = count( $pieces );
$nl = '';
for ( $i = 0; $i < $n; $i++ ) {
$p = $pieces[$i];
$c->insertBefore( $doc->createTextNode( $nl . $p ), $cc );
if ( $i < $n - 1 ) {
$c->insertBefore( $doc->createElement( 'br' ), $cc );
$nl = "\n";
}
}
$c->removeChild( $cc );
}
$cc = $next;
}
$c = $c->nextSibling;
}
}
private function doPostProcessDOM(
DOMElement $node, array $options, bool $atTopLevel
): void {
if ( !$atTopLevel ) {
return;
}
$c = $node->firstChild;
while ( $c ) {
if ( $c instanceof DOMElement ) {
if ( preg_match( '#\bmw:Extension/poem\b#', $c->getAttribute( 'typeof' ) ?? '' ) ) {
// Replace newlines found in <nowiki> fragment with <br/>s
self::processNowikis( $c );
} else {
$this->doPostProcessDOM( $c, $options, $atTopLevel );
}
}
$c = $c->nextSibling;
}
}
/**
* All DOM PostProcessors are expected to implement the run method.
* Eventually, we will probably have an interface with a better name for this
* entry method. But, for now, run() method it is.
*
* @param ParsoidExtensionAPI $extApi
* @param DOMElement $body
* @param array $options
* @param bool $atTopLevel
*/
public function run(
ParsoidExtensionAPI $extApi, DOMElement $body, array $options, bool $atTopLevel
): void {
$this->doPostProcessDOM( $body, $options, $atTopLevel );
}
}

View file

@ -0,0 +1,81 @@
<?php
declare( strict_types = 1 );
namespace Wikimedia\Parsoid\Ext\Poem;
use DOMElement;
use Wikimedia\Parsoid\Ext\DOMDataUtils;
use Wikimedia\Parsoid\Ext\DOMProcessor;
use Wikimedia\Parsoid\Ext\ParsoidExtensionAPI;
use Wikimedia\Parsoid\Utils\DOMUtils;
class PoemProcessor extends DOMProcessor {
/**
* @inheritDoc
*/
public function wtPostprocess(
ParsoidExtensionAPI $extApi, DOMElement $node, array $options, bool $atTopLevel
): void {
if ( !$atTopLevel ) {
return;
}
$c = $node->firstChild;
while ( $c ) {
if ( $c instanceof DOMElement ) {
if ( DOMDataUtils::hasTypeOf( $c, 'mw:Extension/poem' ) ) {
// Replace newlines found in <nowiki> fragment with <br/>s
self::processNowikis( $c );
} else {
$this->wtPostprocess( $extApi, $c, $options, $atTopLevel );
}
}
$c = $c->nextSibling;
}
}
/**
* @param DOMElement $node
*/
private function processNowikis( DOMElement $node ): void {
$doc = $node->ownerDocument;
$c = $node->firstChild;
while ( $c ) {
if ( !$c instanceof DOMElement ) {
$c = $c->nextSibling;
continue;
}
if ( !DOMDataUtils::hasTypeOf( $c, 'mw:Nowiki' ) ) {
self::processNowikis( $c );
$c = $c->nextSibling;
continue;
}
// Replace the nowiki's text node with a combination
// of content and <br/>s. Take care to deal with
// entities that are still entity-wrapped (!!).
$cc = $c->firstChild;
while ( $cc ) {
$next = $cc->nextSibling;
if ( DOMUtils::isText( $cc ) ) {
$pieces = preg_split( '/\n/', $cc->nodeValue );
$n = count( $pieces );
$nl = '';
for ( $i = 0; $i < $n; $i++ ) {
$p = $pieces[$i];
$c->insertBefore( $doc->createTextNode( $nl . $p ), $cc );
if ( $i < $n - 1 ) {
$c->insertBefore( $doc->createElement( 'br' ), $cc );
$nl = "\n";
}
}
$c->removeChild( $cc );
}
$cc = $next;
}
$c = $c->nextSibling;
}
}
}