Page MenuHomePhabricator

Unparsed unordered-list wikitext marker in first element of multi-error notice on page save
Closed, ResolvedPublic

Description

A message box is displayed to users on top of the edit area if the submit process fails. This notice may list several errors, internally represented by a *-list in wikitext. The parse result seems somewhat broken because of the first element of this list displaying a raw asterisk, while all subsequent elements do show up as correct HTML <li>s. See attached screenshot below.

A possible way to reproduce this:

  • Go to any WMF wiki having the TemplateStyles extension installed.
  • Find or create a page with the "Sanitized CSS" content model.
  • Edit this page, trying to mess it up a bit. I'd suggest writing correct CSS, yet not fully supported by the sanitizer, e.g. add some rule with property width: fit-content;. Replicate that property several times so that the sanitizer later reports one error per offending line.
  • Attempt to save the page (the submit action is triggered).
  • On page load, instead of a successful save, the faulty error notice is displayed on top.

Screenshot_2021-05-13 Editing Wikisłownikarz Peter Bowman potencjalnie styles css - Wikisłownik.png (223×2 px, 46 KB)

MW version: 1.37.0-wmf.4 (rMWacb4178d2a6b).

Event Timeline

From Status::getWikiText:

$errors = $this->getErrorMessageArray( $rawErrors, $lang );
foreach ( $errors as &$error ) {
	$error = $error->plain();
}
$s = '* ' . implode( "\n* ", $errors ) . "\n";
if ( $longContext ) {
	$s = $this->msgInLang( $longContext, $lang, $s )->plain();
} elseif ( $shortContext ) {
	$s = $this->msgInLang( $shortContext, $lang, "\n$s\n" )->plain();
}

I gave it a try and replaced line 213 with $s = "\n* " . implode( "\n* ", $errors ) . "\n";, which resulted in a correct 3-element HTML list with no stray raw wikitext. Yet this feels like a hack because of the leading newline, so I believe the source of the actual problem might be somewhere else, on the parser side incorrectly processing the wikitext generated by this method.

Umherirrender subscribed.

The reported message is templatestyles-error-bad-value-for-property in TemplateStyles.

It is wrapped in message templatestyles-errorcomment which provided one newline in the default message, but for multi errors the message itself is wrappred in rawmessage which is only $1 and possible is the cause here. Without that message it could work (not tested).

It is not a parser issue, there are other strange things with that syntax, see T14974

I'm confused how Status formatting code is involved at all. The code generating those warnings should be TemplateStylesContent::getParserOutput and the ParserOutput is processed in EditPage::getPreviewText() and neither invoke it.

And in any case, there's no need to have a newline before a list construct.

>>> (new RawMessage("* x\n*y\n"))->parse()
=> """
   <ul><li>x</li>\n
   <li>y</li></ul>\n
   """
PeterBowman renamed this task from Unparsed unordered-list wikitext marker in first element of multi-error notice to Unparsed unordered-list wikitext marker in first element of multi-error notice on page save.May 17 2021, 3:19 PM

The code generating those warnings should be TemplateStylesContent::getParserOutput and the ParserOutput is processed in EditPage::getPreviewText() and neither invoke it.

Is this getParserOutput method meant to render the resulting HTML on ?action=view? I'm actually observing this bug on page save, therefore we should be looking at TemplateStylesContent::prepareSave instead. In fact, that method is not called at all in the edit-submit scenario (I just commented it out and saw no difference). I've updated the task's title to make this clear, sorry for the confusion.

It is wrapped in message templatestyles-errorcomment which provided one newline in the default message, but for multi errors the message itself is wrappred in rawmessage which is only $1 and possible is the cause here. Without that message it could work (not tested).

The only occurrences of errorcomment and rawmessage I can grep in this extension's sources are located inside an if clause (ref) and don't seem to be called either.

I've tracked down the Status::getWikiText call, it is invoked from inside the default clause in EditPage::handleStatus. Turns out this is a regression introduced in T280766 by c87462097c89dd0711fa05c3bcec275ad6176f44, i.e. switching back from Html::errorBox to a plain <div class="error"> fixes the formatting of list elements.

By the way, please note there was a newline prepended to the box contents in the old code:

$this->hookError = '<div class="error">' . "\n" .
  $status->getWikiText( false, false, $this->context->getLanguage() ) .
  '</div>';

And here is the rationale for said newline (9b530b2b5a5008765ab0a226df8b5ec5f7182bd2):

If a status object returns failure with multiple messages (like in Content::prepareSave()), then previously the first list item would have a raw asterisk in front of it instead of being a list item because the <div> tag was on the same line. Adding a newline before the status object's wikitext will ensure that the first item is interpreted as part of the list.

Change 698173 had a related patch set uploaded (by Peter Bowman; author: Peter Bowman):

[mediawiki/core@master] EditPage: Fix raw asterisk in multi-error message box

https://gerrit.wikimedia.org/r/698173

Change 698173 merged by jenkins-bot:

[mediawiki/core@master] EditPage: Fix raw asterisk in multi-error message box

https://gerrit.wikimedia.org/r/698173