From 2e4f69a49241ffdb07f6c233f0090dc7d906f884 Mon Sep 17 00:00:00 2001 From: Arlo Breault Date: Thu, 28 Oct 2021 17:24:08 -0400 Subject: [PATCH] Implement diffHandler for Cite extension Bug: T214651 Change-Id: I64585cd89135887e095e3ab17d10c3c7d82af1c9 --- src/Parsoid/Ref.php | 60 ++++++++++++++++++++++++++++++++++++++ src/Parsoid/References.php | 27 +++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/src/Parsoid/Ref.php b/src/Parsoid/Ref.php index b5954eab9..511c4c3d5 100644 --- a/src/Parsoid/Ref.php +++ b/src/Parsoid/Ref.php @@ -182,4 +182,64 @@ class Ref extends ExtensionTagHandler { return $startTagSrc . $src . 'name . '>'; } + + /** @inheritDoc */ + public function diffHandler( + ParsoidExtensionAPI $extApi, callable $domDiff, Element $origNode, + Element $editedNode + ): bool { + $origDataMw = DOMDataUtils::getDataMw( $origNode ); + $editedDataMw = DOMDataUtils::getDataMw( $editedNode ); + + if ( isset( $origDataMw->body->id ) && isset( $editedDataMw->body->id ) ) { + $origId = $origDataMw->body->id; + $editedId = $editedDataMw->body->id; + + // So far, this is specified for Cite and relies on the "id" + // referring to an element in the top level dom, even though the + // itself may be in embedded content, + // https://www.mediawiki.org/wiki/Specs/HTML/Extensions/Cite#Ref_and_References + // FIXME: This doesn't work if the section + // itself is in embedded content, since we aren't traversing + // in there. + $origHtml = DOMCompat::getElementById( $origNode->ownerDocument, $origId ); + $editedHtml = DOMCompat::getElementById( $editedNode->ownerDocument, $editedId ); + + if ( $origHtml && $editedHtml ) { + return call_user_func( $domDiff, $origHtml, $editedHtml ); + } else { + // Log error + if ( !$origHtml ) { + $extApi->log( + 'error/domdiff/orig/ref', + "extension src id {$origId} points to non-existent element for:", + DOMCompat::getOuterHTML( $origNode ) + ); + } + if ( !$editedHtml ) { + $extApi->log( + 'error/domdiff/edited/ref', + "extension src id {$editedId} points to non-existent element for:", + DOMCompat::getOuterHTML( $editedNode ) + ); + } + } + } elseif ( isset( $origDataMw->body->html ) && isset( $editedDataMw->body->html ) ) { + $origFragment = $extApi->htmlToDom( + $origDataMw->body->html, $origNode->ownerDocument, + [ 'markNew' => true ] + ); + $editedFragment = $extApi->htmlToDom( + $editedDataMw->body->html, $editedNode->ownerDocument, + [ 'markNew' => true ] + ); + return call_user_func( $domDiff, $origFragment, $editedFragment ); + } + + // FIXME: Similar to DOMDiff::subtreeDiffers, maybe $editNode should + // be marked as inserted to avoid losing any edits, at the cost of + // more normalization + + return false; + } } diff --git a/src/Parsoid/References.php b/src/Parsoid/References.php index 5849b9a4c..2fcfd1ee8 100644 --- a/src/Parsoid/References.php +++ b/src/Parsoid/References.php @@ -792,4 +792,31 @@ class References extends ExtensionTagHandler { // Ignoring for now. return $refs->nextSibling; } + + /** @inheritDoc */ + public function diffHandler( + ParsoidExtensionAPI $extApi, callable $domDiff, Element $origNode, + Element $editedNode + ): bool { + $origDataMw = DOMDataUtils::getDataMw( $origNode ); + $editedDataMw = DOMDataUtils::getDataMw( $editedNode ); + + if ( isset( $origDataMw->body->html ) && isset( $editedDataMw->body->html ) ) { + $origFragment = $extApi->htmlToDom( + $origDataMw->body->html, $origNode->ownerDocument, + [ 'markNew' => true ] + ); + $editedFragment = $extApi->htmlToDom( + $editedDataMw->body->html, $editedNode->ownerDocument, + [ 'markNew' => true ] + ); + return call_user_func( $domDiff, $origFragment, $editedFragment ); + } + + // FIXME: Similar to DOMDiff::subtreeDiffers, maybe $editNode should + // be marked as inserted to avoid losing any edits, at the cost of + // more normalization + + return false; + } }