From 7ef3bffb1e841c14b135e39f2ccb94cfe99e68f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartosz=20Dziewo=C5=84ski?= Date: Wed, 15 Apr 2020 21:04:09 +0200 Subject: [PATCH] Show error on pages with fostered content to avoid page corruption in Parsoid When the user clicks a "Reply" link on a page that is affected by the 'fostered' lint error (indicating fostered content in the HTML representation), display an error and refuse to edit it, as Parsoid's transformations will damage the page content. The error message includes a link to documentation about lint errors, and a link to the editor that will highlight the error location. Depends-On: I723ec766d1244d117f8d624440026fe5af0d3403 Bug: T246481 Change-Id: Ic60cb58f98d10dc9b113469e5d3bbfb2d2b0564f --- extension.json | 1 + i18n/en.json | 1 + i18n/qqq.json | 1 + includes/DiscussionToolsHooks.php | 9 +++++++++ modules/controller.js | 29 +++++++++++++++++++++++++++-- 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/extension.json b/extension.json index 2d14a5fe0..2ba4dd3d9 100644 --- a/extension.json +++ b/extension.json @@ -60,6 +60,7 @@ "ext.visualEditor.core.utils.parsing" ], "messages": [ + "discussiontools-error-lint", "discussiontools-error-comment-disappeared", "discussiontools-error-comment-is-transcluded", "discussiontools-error-comment-is-transcluded-title", diff --git a/i18n/en.json b/i18n/en.json index 025c8da89..5bae16827 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -23,6 +23,7 @@ "discussiontools-error-comment-disappeared": "Could not find the comment you're replying to on the page. It might have been deleted or moved to another page. Please reload the page and try again.", "discussiontools-error-comment-is-transcluded": "This comment can't be replied to using this tool. Please try using the full page editor instead.", "discussiontools-error-comment-is-transcluded-title": "This comment can't be replied to here (yet), because it is loaded from another page. Please go to [[$1]] to reply to it.", + "discussiontools-error-lint": "Comments on this page can't be replied to because of an error in the wikitext. You can learn about this error by [$1 reading the documentation], ask for help by [$2 posting here] or fix the error by [$3 opening the full page editor].", "tag-discussiontools": "-", "tag-discussiontools-description": "Edit made using DiscussionTools", "tag-discussiontools-edit": "Edit comment", diff --git a/i18n/qqq.json b/i18n/qqq.json index a06fd9c9f..3e9a8d1e1 100644 --- a/i18n/qqq.json +++ b/i18n/qqq.json @@ -25,6 +25,7 @@ "discussiontools-replywidget-reply": "Label for the button to submit a reply in the reply widget", "discussiontools-replywidget-terms-click": "Terms of use for posting a reply.\n\n* $1 is the label of the button to be clicked, e.g. {{msg-mw|discussiontools-replywidget-reply}}.", "discussiontools-replywidget-transcluded": "Message explaining that the comment will be saved on a different page than the one you're viewing right now (because it was transcluded from it). Parameter: $1 – page name", + "discussiontools-error-lint": "Error message. Parameters:\n* $1 – URL to documentation on mediawiki.org\n* $2 – URL to talk page on mediawiki.org\n* $3 – URL to the editor (action=edit)", "discussiontools-error-comment-disappeared": "Error message.", "discussiontools-error-comment-is-transcluded": "Error message.", "discussiontools-error-comment-is-transcluded-title": "Error message. Parameter: $1 – page name", diff --git a/includes/DiscussionToolsHooks.php b/includes/DiscussionToolsHooks.php index 57cf71f6d..e1e54383b 100644 --- a/includes/DiscussionToolsHooks.php +++ b/includes/DiscussionToolsHooks.php @@ -77,6 +77,15 @@ class DiscussionToolsHooks { 'ext.discussionTools.init' ] ); } + + if ( $actionName === 'edit' && $req->getVal( 'dtlinterror' ) ) { + // TODO: Should we copy this module from the Linter extension? + $output->addJsConfigVars( [ + 'wgLinterErrorLocation' => + array_map( 'intval', explode( '-', $req->getVal( 'dtlinterror' ), 2 ) ), + ] ); + $output->addModules( 'ext.linter.edit' ); + } } /** diff --git a/modules/controller.js b/modules/controller.js index 25463f64a..8d8b52f4a 100644 --- a/modules/controller.js +++ b/modules/controller.js @@ -350,7 +350,10 @@ function getPageData( pageName, oldId ) { } pageDataCache[ pageName ][ oldId ] = mw.loader.using( 'ext.visualEditor.targetLoader' ).then( function () { return mw.libs.ve.targetLoader.requestPageData( - 'visual', pageName, { oldId: oldId } + 'visual', pageName, { + oldId: oldId, + lint: true + } ); }, function () { // Clear on failure @@ -372,7 +375,8 @@ function getParsoidCommentData( pageName, oldId, commentId ) { return getPageData( pageName, oldId ) .then( function ( response ) { - var data, comment, transcludedFrom, transcludedErrMsg, mwTitle, follow; + var data, comment, transcludedFrom, transcludedErrMsg, mwTitle, follow, + lintErrors, lintLocation, lintType; data = response.visualeditor; parsoidDoc = ve.parseXhtml( data.content ); @@ -430,6 +434,27 @@ function getParsoidCommentData( pageName, oldId, commentId ) { } ] } ).promise(); } + if ( response.visualeditor.lint ) { + // Only lint errors that break editing, namely 'fostered' + lintErrors = response.visualeditor.lint.filter( function ( item ) { + return item.type === 'fostered'; + } ); + + if ( lintErrors.length ) { + // This only reports the first error + lintLocation = lintErrors[ 0 ].dsr.slice( 0, 2 ).join( '-' ); + lintType = lintErrors[ 0 ].type; + + return $.Deferred().reject( 'lint', { errors: [ { + code: 'lint', + html: mw.message( 'discussiontools-error-lint', + 'https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Lint_errors/' + lintType, + 'https://www.mediawiki.org/wiki/Special:MyLanguage/Help_talk:Lint_errors/' + lintType, + mw.util.getUrl( pageName, { action: 'edit', dtlinterror: lintLocation } ) ).parse() + } ] } ).promise(); + } + } + return { comment: parsoidCommentsById[ commentId ], doc: parsoidDoc,