Index: trunk/parsers/wikidom/tests/hype/es.DocumentModel.test.js |
— | — | @@ -204,10 +204,13 @@ |
205 | 205 | test( 'es.DocumentModel', 23, function() { |
206 | 206 | var documentModel = es.DocumentModel.newFromPlainObject( obj ); |
207 | 207 | |
| 208 | + // Test 1 |
208 | 209 | deepEqual( documentModel.getData(), data, 'Flattening plain objects results in correct data' ); |
209 | | - |
| 210 | + |
| 211 | + // Test 2 |
210 | 212 | deepEqual( documentModel.slice( 0 ), tree, 'Nodes in the model tree contain correct lengths' ); |
211 | 213 | |
| 214 | + // Test 3 |
212 | 215 | deepEqual( |
213 | 216 | documentModel[0].getContent( new es.Range( 1, 3 ) ), |
214 | 217 | [ |
— | — | @@ -216,13 +219,15 @@ |
217 | 220 | ], |
218 | 221 | 'getContent can return an ending portion of the content' |
219 | 222 | ); |
220 | | - |
| 223 | + |
| 224 | + // Test 4 |
221 | 225 | deepEqual( |
222 | 226 | documentModel[0].getContent( new es.Range( 0, 2 ) ), |
223 | 227 | ['a', ['b', { 'type': 'bold', 'hash': '#bold' }]], |
224 | 228 | 'getContent can return a beginning portion of the content' |
225 | 229 | ); |
226 | 230 | |
| 231 | + // Test 5 |
227 | 232 | deepEqual( |
228 | 233 | documentModel[0].getContent( new es.Range( 1, 2 ) ), |
229 | 234 | [['b', { 'type': 'bold', 'hash': '#bold' }]], |
— | — | @@ -232,15 +237,18 @@ |
233 | 238 | try { |
234 | 239 | documentModel[0].getContent( new es.Range( -1, 3 ) ); |
235 | 240 | } catch ( negativeIndexError ) { |
| 241 | + // Test 6 |
236 | 242 | ok( true, 'getContent throws exceptions when given a range with start < 0' ); |
237 | 243 | } |
238 | 244 | |
239 | 245 | try { |
240 | 246 | documentModel[0].getContent( new es.Range( 0, 4 ) ); |
241 | 247 | } catch ( outOfRangeError ) { |
| 248 | + // Test 7 |
242 | 249 | ok( true, 'getContent throws exceptions when given a range with end > length' ); |
243 | 250 | } |
244 | 251 | |
| 252 | + // Test 8 |
245 | 253 | deepEqual( documentModel[2].getContent(), ['a'], 'Content can be extracted from nodes' ); |
246 | 254 | |
247 | 255 | var bold = { 'type': 'bold', 'hash': '#bold' }, |
— | — | @@ -248,24 +256,28 @@ |
249 | 257 | nothing = { 'type': 'nothing', 'hash': '#nothing' }, |
250 | 258 | character = ['a', bold, italic]; |
251 | 259 | |
| 260 | + // Test 9 |
252 | 261 | equal( |
253 | 262 | es.DocumentModel.getIndexOfAnnotation( character, bold ), |
254 | 263 | 1, |
255 | 264 | 'getIndexOfAnnotation get the correct index' |
256 | 265 | ); |
257 | 266 | |
| 267 | + // Test 10 |
258 | 268 | equal( |
259 | 269 | es.DocumentModel.getIndexOfAnnotation( character, italic ), |
260 | 270 | 2, |
261 | 271 | 'getIndexOfAnnotation get the correct index' |
262 | 272 | ); |
263 | 273 | |
| 274 | + // Test 11 |
264 | 275 | equal( |
265 | 276 | es.DocumentModel.getIndexOfAnnotation( character, nothing ), |
266 | 277 | -1, |
267 | 278 | 'getIndexOfAnnotation returns -1 if the annotation was not found' |
268 | 279 | ); |
269 | 280 | |
| 281 | + // Test 12 |
270 | 282 | deepEqual( |
271 | 283 | documentModel.prepareElementAttributeChange( 0, 'set', 'test', 1234 ), |
272 | 284 | [ |
— | — | @@ -275,6 +287,7 @@ |
276 | 288 | 'prepareElementAttributeChange retains data after attribute change for first element' |
277 | 289 | ); |
278 | 290 | |
| 291 | + // Test 13 |
279 | 292 | deepEqual( |
280 | 293 | documentModel.prepareElementAttributeChange( 5, 'set', 'test', 1234 ), |
281 | 294 | [ |
— | — | @@ -288,6 +301,7 @@ |
289 | 302 | try { |
290 | 303 | documentModel.prepareElementAttributeChange( 1, 'set', 'test', 1234 ); |
291 | 304 | } catch ( invalidOffsetError ) { |
| 305 | + // Test 14 |
292 | 306 | ok( |
293 | 307 | true, |
294 | 308 | 'prepareElementAttributeChange throws an exception when offset is not an element' |
— | — | @@ -297,12 +311,14 @@ |
298 | 312 | try { |
299 | 313 | documentModel.prepareElementAttributeChange( 4, 'set', 'test', 1234 ); |
300 | 314 | } catch ( closingElementError ) { |
| 315 | + // Test 15 |
301 | 316 | ok( |
302 | 317 | true, |
303 | 318 | 'prepareElementAttributeChange throws an exception when offset is a closing element' |
304 | 319 | ); |
305 | 320 | } |
306 | 321 | |
| 322 | + // Test 16 |
307 | 323 | deepEqual( |
308 | 324 | documentModel.prepareContentAnnotation( new es.Range( 1, 4 ), 'set', { 'type': 'bold' } ), |
309 | 325 | [ |
— | — | @@ -339,6 +355,7 @@ |
340 | 356 | 'prepareContentAnnotation skips over content that is already set or cleared' |
341 | 357 | ); |
342 | 358 | |
| 359 | + // Test 17 |
343 | 360 | deepEqual( |
344 | 361 | documentModel.prepareRemoval( new es.Range( 1, 4 ) ), |
345 | 362 | [ |
— | — | @@ -356,6 +373,7 @@ |
357 | 374 | 'prepareRemoval includes the content being removed' |
358 | 375 | ); |
359 | 376 | |
| 377 | + // Test 18 |
360 | 378 | deepEqual( |
361 | 379 | documentModel.prepareRemoval( new es.Range( 15, 18 ) ), |
362 | 380 | [ |
— | — | @@ -373,6 +391,7 @@ |
374 | 392 | 'prepareRemoval removes entire elements' |
375 | 393 | ); |
376 | 394 | |
| 395 | + // Test 19 |
377 | 396 | deepEqual( |
378 | 397 | documentModel.prepareRemoval( new es.Range( 17, 19 ) ), |
379 | 398 | [ |
— | — | @@ -389,6 +408,7 @@ |
390 | 409 | 'prepareRemoval merges two list items' |
391 | 410 | ); |
392 | 411 | |
| 412 | + // Test 20 |
393 | 413 | deepEqual( |
394 | 414 | documentModel.prepareInsertion( 1, ['d', 'e', 'f'] ), |
395 | 415 | [ |
— | — | @@ -399,6 +419,7 @@ |
400 | 420 | 'prepareInsertion retains data up to the offset and includes the content being inserted' |
401 | 421 | ); |
402 | 422 | |
| 423 | + // Test 21 |
403 | 424 | deepEqual( |
404 | 425 | documentModel.prepareInsertion( |
405 | 426 | 5, |
— | — | @@ -415,6 +436,7 @@ |
416 | 437 | 'prepareInsertion inserts a paragraph between two structural elements' |
417 | 438 | ); |
418 | 439 | |
| 440 | + // Test 22 |
419 | 441 | deepEqual( |
420 | 442 | documentModel.prepareInsertion( |
421 | 443 | 5, |
— | — | @@ -431,6 +453,7 @@ |
432 | 454 | 'prepareInsertion wraps unstructured content inserted between elements in a paragraph' |
433 | 455 | ); |
434 | 456 | |
| 457 | + // Test 23 |
435 | 458 | deepEqual( |
436 | 459 | documentModel.prepareInsertion( |
437 | 460 | 5, |
Index: trunk/parsers/wikidom/lib/hype/models/es.DocumentModel.js |
— | — | @@ -502,7 +502,8 @@ |
503 | 503 | nodeLength = this[i].getElementLength(); |
504 | 504 | if ( offset >= nodeOffset && offset < nodeOffset + nodeLength ) { |
505 | 505 | return this[i].length ? |
506 | | - es.DocumentModel.prototype.getNode.call( this[i], offset - nodeOffset ) : this[i]; |
| 506 | + es.DocumentModel.prototype.getNodeFromOffset.call( this[i], offset - nodeOffset ) : |
| 507 | + this[i]; |
507 | 508 | } |
508 | 509 | nodeOffset += nodeLength; |
509 | 510 | } |
— | — | @@ -614,7 +615,7 @@ |
615 | 616 | */ |
616 | 617 | es.DocumentModel.prototype.prepareRemoval = function( range ) { |
617 | 618 | var doc = this; |
618 | | - debugger; |
| 619 | + //debugger; |
619 | 620 | |
620 | 621 | /** |
621 | 622 | * Return true if can merge the remaining contents of the elements after a selection is deleted across them. |
— | — | @@ -634,11 +635,9 @@ |
635 | 636 | // wait, some nodes don't have types? Is this the top document node? |
636 | 637 | return ( |
637 | 638 | ( |
638 | | - ( node1.type !== undefined && node2.type !== undefined ) |
639 | | - && |
| 639 | + ( node1.type !== undefined && node2.type !== undefined ) && |
640 | 640 | ( node1.type === node2.type ) |
641 | | - ) |
642 | | - && |
| 641 | + ) && |
643 | 642 | ( node1.getParent() === node2.getParent() ) |
644 | 643 | ); |
645 | 644 | } |
— | — | @@ -653,13 +652,14 @@ |
654 | 653 | function stripDelete( range, tx ) { |
655 | 654 | var lastOperation, operationStart; |
656 | 655 | |
657 | | - var ops = []; |
658 | | - debugger; |
| 656 | + var ops = [], |
| 657 | + op; |
| 658 | + //debugger; |
659 | 659 | |
660 | 660 | // get a list of operations, with 0-based indexes |
661 | 661 | for (var i = range.start; i < range.end; i++ ) { |
662 | 662 | var neededOp = doc.data[i].type === undefined ? 'remove' : 'retain'; |
663 | | - var op = ops[ ops.length - 1 ]; |
| 663 | + op = ops[ ops.length - 1 ]; |
664 | 664 | if ( op === undefined || op.type !== neededOp ) { |
665 | 665 | ops.push( { type: neededOp, start: i, end: i } ); |
666 | 666 | } else { |
— | — | @@ -667,10 +667,10 @@ |
668 | 668 | } |
669 | 669 | } |
670 | 670 | |
671 | | - debugger; |
| 671 | + //debugger; |
672 | 672 | // insert operations as transactions (end must be adjusted) |
673 | 673 | for (var j = 0; j < ops.length; j++ ) { |
674 | | - var op = ops[j]; |
| 674 | + op = ops[j]; |
675 | 675 | if ( op.type === 'retain' ) { |
676 | 676 | // we add one because retain(3,3) really means retain 1 char at pos 3 |
677 | 677 | tx.pushRetain( op.end - op.start + 1 ); |