r113440 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r113439‎ | r113440 | r113441 >
Date:01:14, 9 March 2012
Author:catrope
Status:deferred
Tags:
Comment:
Make prepareWrap() use the data from the model rather than the unwrap
parameters. This fixes the case where rolling back a list unwrap would
restore the list items without their attributes
Modified paths:
  • /trunk/extensions/VisualEditor/modules/ve/dm/nodes/ve.dm.DocumentNode.js (modified) (history)
  • /trunk/extensions/VisualEditor/tests/ve/ve.dm.DocumentNode.test.js (modified) (history)

Diff [purge]

Index: trunk/extensions/VisualEditor/tests/ve/ve.dm.DocumentNode.test.js
@@ -822,13 +822,13 @@
823823 [
824824 { 'type': 'retain', 'length': 11 },
825825 { 'type': 'replace', 'remove': [ { 'type': 'list' } ], 'replacement': [] },
826 - { 'type': 'replace', 'remove': [ { 'type': 'listItem' } ], 'replacement': [] },
 826+ { 'type': 'replace', 'remove': [ { 'type': 'listItem', 'attributes': { 'styles': ['bullet'] } } ], 'replacement': [] },
827827 { 'type': 'retain', 'length': 3 },
828828 { 'type': 'replace', 'remove': [ { 'type': '/listItem' } ], 'replacement': [] },
829 - { 'type': 'replace', 'remove': [ { 'type': 'listItem' } ], 'replacement': [] },
 829+ { 'type': 'replace', 'remove': [ { 'type': 'listItem', 'attributes': { 'styles': ['bullet', 'bullet'] } } ], 'replacement': [] },
830830 { 'type': 'retain', 'length': 3 },
831831 { 'type': 'replace', 'remove': [ { 'type': '/listItem' } ], 'replacement': [] },
832 - { 'type': 'replace', 'remove': [ { 'type': 'listItem' } ], 'replacement': [] },
 832+ { 'type': 'replace', 'remove': [ { 'type': 'listItem', 'attributes': { 'styles': ['number'] } } ], 'replacement': [] },
833833 { 'type': 'retain', 'length': 3 },
834834 { 'type': 'replace', 'remove': [ { 'type': '/listItem' } ], 'replacement': [] },
835835 { 'type': 'replace', 'remove': [ { 'type': '/list' } ], 'replacement': [] },
Index: trunk/extensions/VisualEditor/modules/ve/dm/nodes/ve.dm.DocumentNode.js
@@ -1124,8 +1124,13 @@
11251125 /**
11261126 * Generates a transaction which wraps, unwraps or replaces structure.
11271127 *
 1128+ * The unwrap parameters are checked against the actual model data, and
 1129+ * an exception is thrown if the type fields don't match. This means you
 1130+ * can omit attributes from the unwrap parameters, those are automatically
 1131+ * picked up from the model data instead.
 1132+ *
11281133 * @param {ve.Range} range Range to wrap/unwrap/replace around
1129 - * @param {Array} unwrapOuter Array of opening elements to unwrap. These must be immediately *outside* the range
 1134+ * @param {Array} unwrapOuter Array of opening elements to unwrap. These must be immediately *outside* the range.
11301135 * @param {Array} wrapOuter Array of opening elements to wrap around the range.
11311136 * @param {Array} unwrapEach Array of opening elements to unwrap from each top-level element in the range.
11321137 * @param {Array} wrapEach Array of opening elements to wrap around each top-level element in the range.
@@ -1159,18 +1164,28 @@
11601165 // * unwraps actually match
11611166 // * result is valid
11621167
1163 - var tx = new ve.dm.Transaction();
 1168+ var tx = new ve.dm.Transaction(), i, j, unwrapOuterData;
11641169 range.normalize();
11651170 if ( range.start > unwrapOuter.length ) {
11661171 // Retain up to the first thing we're unwrapping
11671172 // The outer unwrapping takes place *outside*
11681173 // the range, so compensate for that
1169 - tx.pushRetain ( range.start - unwrapOuter.length );
 1174+ tx.pushRetain( range.start - unwrapOuter.length );
11701175 }
11711176
11721177 // Replace the opening elements for the outer unwrap&wrap
11731178 if ( wrapOuter.length > 0 || unwrapOuter.length > 0 ) {
1174 - tx.pushReplace( unwrapOuter, wrapOuter );
 1179+ // Verify that wrapOuter matches the data at this position
 1180+ unwrapOuterData = this.data.slice( range.start - unwrapOuter.length, range.start );
 1181+ for ( i = 0; i < unwrapOuterData.length; i++ ) {
 1182+ if ( unwrapOuterData[i].type !== unwrapOuter[i].type ) {
 1183+ throw 'Element in unwrapOuter does not match: expected ' +
 1184+ unwrapOuter[i].type + ' but found ' + unwrapOuterData[i].type;
 1185+ }
 1186+ }
 1187+ // Instead of putting in unwrapOuter as given, put it in the
 1188+ // way it appears in the mode,l so we pick up any attributes
 1189+ tx.pushReplace( unwrapOuterData, wrapOuter );
11751190 }
11761191
11771192 if ( wrapEach.length > 0 || unwrapEach.length > 0 ) {
@@ -1178,7 +1193,7 @@
11791194 closingWrapEach = closingArray( wrapEach ),
11801195 depth = 0,
11811196 startOffset,
1182 - i;
 1197+ unwrapEachData;
11831198 // Visit each top-level child and wrap/unwrap it
11841199 // TODO figure out if we should use the tree/node functions here
11851200 // rather than iterating over offsets, it may or may not be faster
@@ -1192,7 +1207,20 @@
11931208 if ( depth == 0 ) {
11941209 // We are at the start of a top-level element
11951210 // Replace the opening elements
1196 - tx.pushReplace( unwrapEach, wrapEach );
 1211+
 1212+ // Verify that unwrapEach matches the data at this position
 1213+ unwrapEachData = this.data.slice( i, i + unwrapEach.length );
 1214+ for ( j = 0; j < unwrapEachData.length; j++ ) {
 1215+ if ( unwrapEachData[j].type !== unwrapEach[j].type ) {
 1216+ throw 'Element in unwrapEach does not match: expected ' +
 1217+ unwrapEach[j].type + ' but found ' +
 1218+ unwrapEachData[j].type;
 1219+ }
 1220+ }
 1221+ // Instead of putting in unwrapEach as given, put it in the
 1222+ // way it appears in the model, so we pick up any attributes
 1223+ tx.pushReplace( unwrapEachData, wrapEach );
 1224+
11971225 // Store this offset for later
11981226 startOffset = i;
11991227 }

Status & tagging log