jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/347901 )

Change subject: Introduce single-line mode for surfaces
......................................................................


Introduce single-line mode for surfaces

Or rather multi-line, defaulted to true.

For now this blocks the creation of newlines using <enter> or
via paste.

There are other ways to trigger complex creation that will need
to be addressed later, possibly at the transaction level:

* Pasting objects (e.g. HTML files)
* Sequences (e.g. '* ')
* Commands (no real-world examples)

Bug: T162808
Change-Id: I31fce3cc9ac6f7c12ec916b364b91cead2b4e6c9
---
M src/ce/keydownhandlers/ve.ce.LinearEnterKeyDownHandler.js
M src/ce/keydownhandlers/ve.ce.TableArrowKeyDownHandler.js
M src/ce/ve.ce.Surface.js
M src/dm/lineardata/ve.dm.ElementLinearData.js
M src/ui/ve.ui.Surface.js
M src/ui/widgets/ve.ui.TargetWidget.js
M tests/ce/ve.ce.Surface.test.js
M tests/dm/lineardata/ve.dm.ElementLinearData.test.js
M tests/ve.test.utils.js
9 files changed, 67 insertions(+), 3 deletions(-)

Approvals:
  jenkins-bot: Verified
  Jforrester: Looks good to me, approved



diff --git a/src/ce/keydownhandlers/ve.ce.LinearEnterKeyDownHandler.js 
b/src/ce/keydownhandlers/ve.ce.LinearEnterKeyDownHandler.js
index fa8a64d..7d05f16 100644
--- a/src/ce/keydownhandlers/ve.ce.LinearEnterKeyDownHandler.js
+++ b/src/ce/keydownhandlers/ve.ce.LinearEnterKeyDownHandler.js
@@ -49,6 +49,10 @@
 
        e.preventDefault();
 
+       if ( !surface.getSurface().isMultiline() ) {
+               return true;
+       }
+
        if ( ( e.ctrlKey || e.metaKey ) && surface.getSurface().getInDialog() ) 
{
                // We're inside a dialog. OOUI behavior is to close+submit a 
dialog if
                // ctrl/cmd+enter is pressed. If this dialog is going to close, 
we
diff --git a/src/ce/keydownhandlers/ve.ce.TableArrowKeyDownHandler.js 
b/src/ce/keydownhandlers/ve.ce.TableArrowKeyDownHandler.js
index 84cbcd2..e82a26a 100644
--- a/src/ce/keydownhandlers/ve.ce.TableArrowKeyDownHandler.js
+++ b/src/ce/keydownhandlers/ve.ce.TableArrowKeyDownHandler.js
@@ -89,6 +89,7 @@
        e.preventDefault();
 
        this.moveTableSelection( surface, rowOffset, colOffset, checkDir, 
expand, wrap );
+       return true;
 };
 
 /**
diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js
index 8d04250..5620fae 100644
--- a/src/ce/ve.ce.Surface.js
+++ b/src/ce/ve.ce.Surface.js
@@ -1100,7 +1100,10 @@
 
        } else {
                // External drop
-               this.handleDataTransfer( dataTransfer, false, targetFragment );
+               // TODO: Support sanitized drop on single line surfaces
+               if ( this.getSurface().isMultiline() ) {
+                       this.handleDataTransfer( dataTransfer, false, 
targetFragment );
+               }
        }
        this.endRelocation();
 };
diff --git a/src/dm/lineardata/ve.dm.ElementLinearData.js 
b/src/dm/lineardata/ve.dm.ElementLinearData.js
index cc96094..eb8a05d 100644
--- a/src/dm/lineardata/ve.dm.ElementLinearData.js
+++ b/src/dm/lineardata/ve.dm.ElementLinearData.js
@@ -1100,10 +1100,11 @@
  * @param {boolean} [rules.preserveHtmlWhitespace] Preserve non-semantic HTML 
whitespace
  * @param {boolean} [rules.nodeSanitization] Apply per-type node sanitizations 
via ve.dm.Node#sanitize
  * @param {boolean} [rules.keepEmptyContentBranches] Preserve empty content 
branch nodes
+ * @param {boolean} [rules.singleLine] Don't allow more that one 
ContentBranchNode
  */
 ve.dm.ElementLinearData.prototype.sanitize = function ( rules ) {
        var i, len, annotations, emptySet, setToRemove, type, oldHash, newHash,
-               canContainContent, contentElement, isOpen, nodeClass, ann,
+               canContainContent, contentElement, isOpen, nodeClass, ann, 
start,
                elementStack = [],
                store = this.getStore(),
                allAnnotations = this.getAnnotationsFromRange( new ve.Range( 0, 
this.getLength() ), true );
@@ -1228,6 +1229,16 @@
                                }
                        }
 
+                       if ( canContainContent && !isOpen && rules.singleLine ) 
{
+                               i++;
+                               start = i;
+                               while ( i < len && !( this.isOpenElementData( i 
) && this.getType( i ) === 'internalList' ) ) {
+                                       i++;
+                               }
+                               this.splice( start, i - start );
+                               break;
+                       }
+
                        // Store the current contentElement for splitting
                        if ( canContainContent ) {
                                contentElement = isOpen ? this.getData( i ) : 
null;
diff --git a/src/ui/ve.ui.Surface.js b/src/ui/ve.ui.Surface.js
index e25a74b..4c89bee 100644
--- a/src/ui/ve.ui.Surface.js
+++ b/src/ui/ve.ui.Surface.js
@@ -22,6 +22,7 @@
  * @cfg {string[]|null} [includeCommands] List of commands to include, null 
for all registered commands
  * @cfg {string[]} [excludeCommands] List of commands to exclude
  * @cfg {Object} [importRules] Import rules
+ * @cfg {boolean} [multiline=true] Multi-line surface
  * @cfg {string} [placeholder] Placeholder text to display when the surface is 
empty
  * @cfg {string} [inDialog] The name of the dialog this surface is in
  */
@@ -69,6 +70,7 @@
        this.view = this.createView( this.model );
        this.dialogs = this.createDialogWindowManager();
        this.importRules = config.importRules || {};
+       this.multiline = config.multiline !== false;
        this.context = this.createContext();
        this.progresses = [];
        this.showProgressDebounced = ve.debounce( this.showProgress.bind( this 
) );
@@ -750,7 +752,20 @@
  * @return {Object} Import rules
  */
 ve.ui.Surface.prototype.getImportRules = function () {
-       return this.importRules;
+       var singleLine = { singleLine: !this.multiline };
+       return {
+               all: ve.extendObject( {}, this.importRules.all, singleLine ),
+               external: ve.extendObject( {}, this.importRules.external, 
singleLine )
+       };
+};
+
+/**
+ * Check if the surface is multi-line
+ *
+ * @return {boolean} Surface is multi-line
+ */
+ve.ui.Surface.prototype.isMultiline = function () {
+       return this.multiline;
 };
 
 /**
diff --git a/src/ui/widgets/ve.ui.TargetWidget.js 
b/src/ui/widgets/ve.ui.TargetWidget.js
index 34b6e89..e3436ac 100644
--- a/src/ui/widgets/ve.ui.TargetWidget.js
+++ b/src/ui/widgets/ve.ui.TargetWidget.js
@@ -21,6 +21,7 @@
  * @cfg {string[]|null} [includeCommands] List of commands to include, null 
for all registered commands
  * @cfg {string[]} [excludeCommands] List of commands to exclude
  * @cfg {Object} [importRules] Import rules
+ * @cfg {boolean} [multiline] Multi-line surface
  * @cfg {string} [inDialog] The name of the dialog this surface widget is in
  */
 ve.ui.TargetWidget = function VeUiTargetWidget( config ) {
@@ -38,6 +39,7 @@
        this.tools = config.tools;
        this.includeCommands = config.includeCommands;
        this.excludeCommands = config.excludeCommands;
+       this.multiline = config.multiline !== false;
        this.importRules = config.importRules;
        this.inDialog = config.inDialog;
        // TODO: Support source widgets
@@ -94,6 +96,7 @@
                includeCommands: this.includeCommands,
                excludeCommands: this.excludeCommands,
                importRules: this.importRules,
+               multiline: this.multiline,
                inDialog: this.inDialog
        } );
 
diff --git a/tests/ce/ve.ce.Surface.test.js b/tests/ce/ve.ce.Surface.test.js
index 53aa686..8a9238c 100644
--- a/tests/ce/ve.ce.Surface.test.js
+++ b/tests/ce/ve.ce.Surface.test.js
@@ -895,6 +895,18 @@
                        },
                        {
                                rangeOrSelection: new ve.Range( 57 ),
+                               keys: [ 'ENTER' ],
+                               htmlOrDoc: ( function () {
+                                       var view = 
ve.test.utils.createSurfaceViewFromDocument( 
ve.dm.example.createExampleDocument() );
+                                       view.surface.isMultiline = function () 
{ return false; };
+                                       return view;
+                               }() ),
+                               expectedData: function () {},
+                               expectedRangeOrSelection: new ve.Range( 57 ),
+                               msg: 'Enter does nothing in single line mode'
+                       },
+                       {
+                               rangeOrSelection: new ve.Range( 57 ),
                                keys: [ 'SHIFT+ENTER' ],
                                expectedData: function ( data ) {
                                        data.splice(
diff --git a/tests/dm/lineardata/ve.dm.ElementLinearData.test.js 
b/tests/dm/lineardata/ve.dm.ElementLinearData.test.js
index 3a3c10f..e7ddb21 100644
--- a/tests/dm/lineardata/ve.dm.ElementLinearData.test.js
+++ b/tests/dm/lineardata/ve.dm.ElementLinearData.test.js
@@ -1597,6 +1597,18 @@
                                msg: 'Headings converted to paragraph in 
plainText mode'
                        },
                        {
+                               html: '<p>Bar</p><p>Baz</p><p>Quux</p>',
+                               data: [
+                                       { type: 'paragraph' },
+                                       'B', 'a', 'r',
+                                       { type: '/paragraph' },
+                                       { type: 'internalList' },
+                                       { type: '/internalList' }
+                               ],
+                               rules: { singleLine: true },
+                               msg: 'Extra lines truncated in singleline mode'
+                       },
+                       {
                                html: '<h1>Bar</h1>',
                                data: [
                                        // TODO: non-relevant attributes should 
be discarded, T130377
diff --git a/tests/ve.test.utils.js b/tests/ve.test.utils.js
index 4fbc6c5..11db900 100644
--- a/tests/ve.test.utils.js
+++ b/tests/ve.test.utils.js
@@ -319,6 +319,9 @@
                                isMobile: function () {
                                        return false;
                                },
+                               isMultiline: function () {
+                                       return true;
+                               },
                                getBoundingClientRect: function () {
                                        return {};
                                },

-- 
To view, visit https://gerrit.wikimedia.org/r/347901
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I31fce3cc9ac6f7c12ec916b364b91cead2b4e6c9
Gerrit-PatchSet: 4
Gerrit-Project: VisualEditor/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Esanders <esand...@wikimedia.org>
Gerrit-Reviewer: Esanders <esand...@wikimedia.org>
Gerrit-Reviewer: Jforrester <jforres...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to