diff --git a/includes/CommentModifier.php b/includes/CommentModifier.php index 8537d35a9..eaf841c77 100644 --- a/includes/CommentModifier.php +++ b/includes/CommentModifier.php @@ -2,7 +2,6 @@ namespace MediaWiki\Extension\DiscussionTools; -use DOMComment; use DOMDocument; use DOMDocumentFragment; use DOMElement; @@ -140,13 +139,14 @@ class CommentModifier { $target = $target->parentNode; } - // Parsoid puts HTML comments which appear at the end of the line in wikitext outside the paragraph, + // Parsoid puts HTML comments (and other "rendering-transparent nodes", e.g. category links) + // which appear at the end of the line in wikitext outside the paragraph, // but we usually shouldn't insert replies between the paragraph and such comments. (T257651) // Skip over comments and whitespace, but only update target when skipping past comments. $pointer = $target; while ( $pointer->nextSibling && ( - $pointer->nextSibling instanceof DOMComment || + CommentUtils::isRenderingTransparentNode( $pointer->nextSibling ) || ( $pointer->nextSibling instanceof DOMText && CommentUtils::htmlTrim( $pointer->nextSibling->nodeValue ) === '' && @@ -157,7 +157,7 @@ class CommentModifier { ) ) { $pointer = $pointer->nextSibling; - if ( $pointer instanceof DOMComment ) { + if ( CommentUtils::isRenderingTransparentNode( $pointer ) ) { $target = $pointer; } } diff --git a/includes/CommentUtils.php b/includes/CommentUtils.php index 465005e44..a0fecbe9a 100644 --- a/includes/CommentUtils.php +++ b/includes/CommentUtils.php @@ -2,6 +2,7 @@ namespace MediaWiki\Extension\DiscussionTools; +use DOMComment; use DOMElement; use DOMNode; use DOMXPath; @@ -37,6 +38,20 @@ class CommentUtils { in_array( strtolower( $node->tagName ), self::$blockElementTypes ); } + /** + * @param DOMNode $node + * @return bool Node is considered a rendering-transparent node in Parsoid + */ + public static function isRenderingTransparentNode( DOMNode $node ) : bool { + return ( + $node instanceof DOMComment || + $node instanceof DOMElement && ( + strtolower( $node->tagName ) === 'meta' || + strtolower( $node->tagName ) === 'link' + ) + ); + } + /** * Get the index of $child in its parent * diff --git a/modules/modifier.js b/modules/modifier.js index fb9d00e4e..c3d330773 100644 --- a/modules/modifier.js +++ b/modules/modifier.js @@ -130,13 +130,14 @@ function addListItem( comment ) { target = target.parentNode; } - // Parsoid puts HTML comments which appear at the end of the line in wikitext outside the paragraph, + // Parsoid puts HTML comments (and other "rendering-transparent nodes", e.g. category links) + // which appear at the end of the line in wikitext outside the paragraph, // but we usually shouldn't insert replies between the paragraph and such comments. (T257651) // Skip over comments and whitespace, but only update target when skipping past comments. pointer = target; while ( pointer.nextSibling && ( - pointer.nextSibling.nodeType === Node.COMMENT_NODE || + utils.isRenderingTransparentNode( pointer.nextSibling ) || ( pointer.nextSibling.nodeType === Node.TEXT_NODE && utils.htmlTrim( pointer.nextSibling.textContent ) === '' && @@ -147,7 +148,7 @@ function addListItem( comment ) { ) ) { pointer = pointer.nextSibling; - if ( pointer.nodeType === Node.COMMENT_NODE ) { + if ( utils.isRenderingTransparentNode( pointer ) ) { target = pointer; } } diff --git a/modules/utils.js b/modules/utils.js index 6dd67d2ce..926cafe7c 100644 --- a/modules/utils.js +++ b/modules/utils.js @@ -13,6 +13,20 @@ function isBlockElement( node ) { return node instanceof HTMLElement && ve.isBlockElement( node ); } +/** + * @param {Node} node + * @return {boolean} Node is considered a rendering-transparent node in Parsoid + */ +function isRenderingTransparentNode( node ) { + return ( + node.nodeType === Node.COMMENT_NODE || + node.nodeType === Node.ELEMENT_NODE && ( + node.tagName.toLowerCase() === 'meta' || + node.tagName.toLowerCase() === 'link' + ) + ); +} + /** * Get the index of a node in its parentNode's childNode list * @@ -283,6 +297,7 @@ function getFullyCoveredSiblings( item ) { module.exports = { isBlockElement: isBlockElement, + isRenderingTransparentNode: isRenderingTransparentNode, childIndexOf: childIndexOf, closestElement: closestElement, getIndentLevel: getIndentLevel, diff --git a/tests/cases/signatures-comments/signatures-comments-modified.html b/tests/cases/signatures-comments/signatures-comments-modified.html index a19d68cf5..52c8d8f6c 100644 --- a/tests/cases/signatures-comments/signatures-comments-modified.html +++ b/tests/cases/signatures-comments/signatures-comments-modified.html @@ -10,7 +10,9 @@

hello Matma Rex (talk) 18:44, 22 July 2020 (UTC)

Reply to c|Matma Rex|2020-07-22T18:44:00.000Z|comments_T257651
-

hello Matma Rex (talk) 18:45, 22 July 2020 (UTC)

Reply to c|Matma Rex|2020-07-22T18:45:00.000Z|comments_T257651
+

hello Matma Rex (talk) 18:45, 22 July 2020 (UTC)

Reply to c|Matma Rex|2020-07-22T18:45:00.000Z|comments_T257651
+ +

hello Matma Rex (talk) 18:46, 22 July 2020 (UTC)

Reply to c|Matma Rex|2020-07-22T18:46:00.000Z|comments_T257651
diff --git a/tests/cases/signatures-comments/signatures-comments.html b/tests/cases/signatures-comments/signatures-comments.html index 040fa92bc..6b74e24f5 100644 --- a/tests/cases/signatures-comments/signatures-comments.html +++ b/tests/cases/signatures-comments/signatures-comments.html @@ -10,7 +10,9 @@

hello Matma Rex (talk) 18:44, 22 July 2020 (UTC)

-

hello Matma Rex (talk) 18:45, 22 July 2020 (UTC)

+

hello Matma Rex (talk) 18:45, 22 July 2020 (UTC)

+ +

hello Matma Rex (talk) 18:46, 22 July 2020 (UTC)