Use 'id' attributes rather than heading text for edit autosummaries

Ideally the edit autosummary would be generated in the same
way as in the old wikitext editor: from the wikitext of the
heading. But on the JS side, we don't have access to the
wikitext, or to the PHP method that generates autosummaries.

This might seem crazy at first, but ultimately the point of
the autosummaries is to link to the section heading by its
'id' attribute, so it is perfectly reliable.

Doing it this way depends on $wgFragmentMode being set to
[ 'html5', 'legacy' ] or [ 'html5' ], otherwise the escaped IDs
are super garbled (particularly in non-Latin-alphabet languages)
and can't be unescaped reliably. Conveniently, we already
require that since 9ee0fd69f5.

Bug: T264561
Bug: T266725
Change-Id: I7d35098d672d0edb50d49e22de1686d5cc83b60e
This commit is contained in:
Bartosz Dziewoński 2020-11-04 22:59:42 +01:00
parent bed717d329
commit 203a4dcb42
2 changed files with 27 additions and 6 deletions

View file

@ -161,12 +161,23 @@ class ApiDiscussionToolsEdit extends ApiBase {
$heading = $comment->getHeading(); $heading = $comment->getHeading();
if ( $heading->isPlaceholderHeading() ) { if ( $heading->isPlaceholderHeading() ) {
// This comment is in 0th section, there's no section title for the edit summary // This comment is in 0th section, there's no section title for the edit summary
$summaryPrefix = ''; $summary = '';
} else { } else {
$summaryPrefix = '/* ' . $heading->getRange()->startContainer->textContent . ' */ '; $headingNode =
CommentUtils::getHeadlineNodeAndOffset( $heading->getRange()->startContainer )['node'];
$id = $headingNode->getAttribute( 'id' );
if ( $id ) {
// Replace underscores with spaces to undo Sanitizer::escapeIdInternal().
// This assumes that $wgFragmentMode is [ 'html5', 'legacy' ] or [ 'html5' ],
// otherwise the escaped IDs are super garbled and can't be unescaped reliably.
$summary = '/* ' . str_replace( '_', ' ', $id ) . ' */ ';
} else {
// Not a real section, probably just HTML markup in wikitext, bleh
$summary = '';
}
$summary = '/* ' . $heading->getRange()->startContainer->textContent . ' */ ';
} }
$summary = $summaryPrefix . $summary .= $this->msg( 'discussiontools-defaultsummary-reply' )->inContentLanguage()->text();
$this->msg( 'discussiontools-defaultsummary-reply' )->inContentLanguage()->text();
} }
$api = new ApiMain( $api = new ApiMain(

View file

@ -376,7 +376,7 @@ ReplyWidget.prototype.onModeTabSelectChoose = function ( option ) {
* @return {ReplyWidget} * @return {ReplyWidget}
*/ */
ReplyWidget.prototype.setup = function ( data ) { ReplyWidget.prototype.setup = function ( data ) {
var heading, summary; var heading, headingNode, id, summary;
data = data || {}; data = data || {};
@ -394,7 +394,17 @@ ReplyWidget.prototype.setup = function ( data ) {
// This comment is in 0th section, there's no section title for the edit summary // This comment is in 0th section, there's no section title for the edit summary
summary = ''; summary = '';
} else { } else {
summary = '/* ' + heading.getNativeRange().toString().trim() + ' */ '; headingNode = utils.getHeadlineNodeAndOffset( heading.range.startContainer ).node;
id = headingNode.getAttribute( 'id' );
if ( id ) {
// Replace underscores with spaces to undo Sanitizer::escapeIdInternal().
// This assumes that $wgFragmentMode is [ 'html5', 'legacy' ] or [ 'html5' ],
// otherwise the escaped IDs are super garbled and can't be unescaped reliably.
summary = '/* ' + id.replace( /_/g, ' ' ) + ' */ ';
} else {
// Not a real section, probably just HTML markup in wikitext, bleh
summary = '';
}
} }
summary += mw.msg( 'discussiontools-defaultsummary-reply' ); summary += mw.msg( 'discussiontools-defaultsummary-reply' );
} }