Add signature on separate line if wikitext comment ends with a list

Bug: T263217
Change-Id: Idd15a9add798368493ae7af5270f972895470de9
This commit is contained in:
Bartosz Dziewoński 2022-08-06 14:51:02 +02:00
parent a4d9455743
commit d223626585
5 changed files with 69 additions and 7 deletions

View file

@ -106,9 +106,8 @@ class ApiDiscussionToolsEdit extends ApiBase {
$html = $params['html']; $html = $params['html'];
if ( $wikitext !== null ) { if ( $wikitext !== null ) {
$wikitext = CommentUtils::htmlTrim( $wikitext );
if ( $signature !== null ) { if ( $signature !== null ) {
$wikitext .= $signature; $wikitext = CommentModifier::appendSignatureWikitext( $wikitext, $signature );
} }
} else { } else {
$doc = DOMUtils::parseHTML( '' ); $doc = DOMUtils::parseHTML( '' );

View file

@ -60,9 +60,8 @@ trait ApiDiscussionToolsTrait {
switch ( $type ) { switch ( $type ) {
case 'topic': case 'topic':
if ( $wikitext !== null ) { if ( $wikitext !== null ) {
$wikitext = CommentUtils::htmlTrim( $wikitext );
if ( $signature !== null ) { if ( $signature !== null ) {
$wikitext .= $signature; $wikitext = CommentModifier::appendSignatureWikitext( $wikitext, $signature );
} }
} else { } else {
$doc = DOMUtils::parseHTML( '' ); $doc = DOMUtils::parseHTML( '' );

View file

@ -446,9 +446,24 @@ class CommentModifier {
public static function appendSignature( DocumentFragment $container, string $signature ): void { public static function appendSignature( DocumentFragment $container, string $signature ): void {
$doc = $container->ownerDocument; $doc = $container->ownerDocument;
// If the last node isn't a paragraph (e.g. it's a list created in visual mode), then // If the last node isn't a paragraph (e.g. it's a list created in visual mode),
// add another paragraph to contain the signature. // or looks like a list item created in wikitext mode (T263217),
if ( !$container->lastChild || strtolower( $container->lastChild->nodeName ) !== 'p' ) { // then add another paragraph to contain the signature.
$wrapperNode = $container->lastChild;
if (
!( $wrapperNode instanceof Element ) ||
strtolower( $wrapperNode->tagName ) !== 'p' ||
(
// This would be easier to check in prepareWikitextReply(), but that would result
// in an empty list item being added at the end if we don't need to add a signature.
( $wtNode = $wrapperNode->lastChild ) &&
$wtNode instanceof Element &&
( $dataMw = json_decode( $wtNode->getAttribute( 'data-mw' ) ?? '', true ) ) &&
( $wikitextLine = $dataMw['parts'][0] ?? null ) &&
is_string( $wikitextLine ) &&
in_array( $wikitextLine[0], [ '*', '#', ':', ';' ] )
)
) {
$container->appendChild( $doc->createElement( 'p' ) ); $container->appendChild( $doc->createElement( 'p' ) );
} }
// If the last node is empty, trim the signature to prevent leading whitespace triggering // If the last node is empty, trim the signature to prevent leading whitespace triggering
@ -465,6 +480,29 @@ class CommentModifier {
); );
} }
/**
* Append a user signature to the comment in the provided wikitext.
*
* @param string $wikitext
* @param string $signature
* @return string
*/
public static function appendSignatureWikitext( string $wikitext, string $signature ): string {
$wikitext = CommentUtils::htmlTrim( $wikitext );
$lines = explode( "\n", $wikitext );
$lastLine = end( $lines );
// If last line looks like a list item, add an empty line afterwards for the signature (T263217)
if ( $lastLine && in_array( $lastLine[0], [ '*', '#', ':', ';' ] ) ) {
$wikitext .= "\n";
// Trim the signature to prevent leading whitespace triggering preformatted text (T269188, T276612)
$signature = ltrim( $signature, ' ' );
}
return $wikitext . $signature;
}
/** /**
* Add a reply to a specific comment * Add a reply to a specific comment
* *

View file

@ -4,11 +4,21 @@
"html": "<p>Foo bar</p>", "html": "<p>Foo bar</p>",
"expected": "<p>Foo bar<span typeof=\"mw:Transclusion\" data-mw=\"{&quot;parts&quot;:[&quot; ~~~~&quot;]}\"></span></p>" "expected": "<p>Foo bar<span typeof=\"mw:Transclusion\" data-mw=\"{&quot;parts&quot;:[&quot; ~~~~&quot;]}\"></span></p>"
}, },
{
"msg": "Simple message (from wikitext mode)",
"html": "<p><span typeof=\"mw:Transclusion\" data-mw=\"{&quot;parts&quot;:[&quot;Foo bar&quot;]}\"></span></p>",
"expected": "<p><span typeof=\"mw:Transclusion\" data-mw=\"{&quot;parts&quot;:[&quot;Foo bar&quot;]}\"></span><span typeof=\"mw:Transclusion\" data-mw=\"{&quot;parts&quot;:[&quot; ~~~~&quot;]}\"></span></p>"
},
{ {
"msg": "List", "msg": "List",
"html": "<p>Foo bar</p><ul><li>A</li><li>B</li></ul>", "html": "<p>Foo bar</p><ul><li>A</li><li>B</li></ul>",
"expected": "<p>Foo bar</p><ul><li>A</li><li>B</li></ul><p><span typeof=\"mw:Transclusion\" data-mw=\"{&quot;parts&quot;:[&quot;~~~~&quot;]}\"></span></p>" "expected": "<p>Foo bar</p><ul><li>A</li><li>B</li></ul><p><span typeof=\"mw:Transclusion\" data-mw=\"{&quot;parts&quot;:[&quot;~~~~&quot;]}\"></span></p>"
}, },
{
"msg": "List (from wikitext mode)",
"html": "<p><span typeof=\"mw:Transclusion\" data-mw=\"{&quot;parts&quot;:[&quot;Foo bar&quot;]}\"></span></p><p><span typeof=\"mw:Transclusion\" data-mw=\"{&quot;parts&quot;:[&quot;*A&quot;]}\"></span></p><p><span typeof=\"mw:Transclusion\" data-mw=\"{&quot;parts&quot;:[&quot;*B&quot;]}\"></span></p>",
"expected": "<p><span typeof=\"mw:Transclusion\" data-mw=\"{&quot;parts&quot;:[&quot;Foo bar&quot;]}\"></span></p><p><span typeof=\"mw:Transclusion\" data-mw=\"{&quot;parts&quot;:[&quot;*A&quot;]}\"></span></p><p><span typeof=\"mw:Transclusion\" data-mw=\"{&quot;parts&quot;:[&quot;*B&quot;]}\"></span></p><p><span typeof=\"mw:Transclusion\" data-mw=\"{&quot;parts&quot;:[&quot;~~~~&quot;]}\"></span></p>"
},
{ {
"msg": "Empty trailing paragraph", "msg": "Empty trailing paragraph",
"html": "<p>Foo bar</p><p></p>", "html": "<p>Foo bar</p><p></p>",

View file

@ -147,6 +147,22 @@ class CommentModifierTest extends IntegrationTestCase {
return static::getJson( '../cases/appendSignature.json' ); return static::getJson( '../cases/appendSignature.json' );
} }
/**
* @covers ::appendSignatureWikitext
*/
public function testAppendSignatureWikitext(): void {
static::assertEquals(
'Foo bar ~~~~',
CommentModifier::appendSignatureWikitext( 'Foo bar', ' ~~~~' ),
'Simple message'
);
static::assertEquals(
"Foo bar\n*A\n*B\n~~~~",
CommentModifier::appendSignatureWikitext( "Foo bar\n*A\n*B", ' ~~~~' ),
'List'
);
}
/** /**
* @dataProvider provideSanitizeWikitextLinebreaks * @dataProvider provideSanitizeWikitextLinebreaks
* @covers ::sanitizeWikitextLinebreaks * @covers ::sanitizeWikitextLinebreaks