/*! * VisualEditor DataModel example data sets. * * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt * @license The MIT License (MIT); see LICENSE.txt */ /** * @class * @singleton * @ignore */ ve.dm.example = {}; /* Methods */ /** * Convert arrays of shorthand annotations in a data fragment to AnnotationSets with real * annotation objects, and wraps the result in a ve.dm.ElementLinearData object. * * Shorthand notation for annotations is: * [ 'a', [ { 'type': 'link', 'attributes': { 'href': '...' } ] ] * * The actual storage format has an instance of ve.dm.LinkAnnotation instead of the plain object, * and an instance of ve.dm.AnnotationSet instead of the array. * * @method * @param {Array} data Linear model data * @param {ve.dm.IndexValueStore} [store] Index-value store to use, creates one if undefined * @returns {ve.dm.ElementLinearData} Element linear data store * @throws {Error} Example data passed to preprocessAnnotations by reference */ ve.dm.example.preprocessAnnotations = function ( data, store ) { var i, key; // Sanity check to make sure ve.dm.example data has not been passed in // by reference. Always use ve.copyArray. for ( i in ve.dm.example ) { if ( data === ve.dm.example[i] ) { throw new Error( 'Example data passed to preprocessAnnotations by reference' ); } } store = store || new ve.dm.IndexValueStore(); for ( i = 0; i < data.length; i++ ) { key = data[i].annotations ? 'annotations' : 1; // check for shorthand annotation objects in array if ( ve.isArray( data[i][key] ) && data[i][key][0].type ) { data[i][key] = ve.dm.example.createAnnotationSet( store, data[i][key] ).getIndexes(); } } return new ve.dm.ElementLinearData( store, data ); }; /** * Create an annotation object from shorthand notation. * @method * @param {Object} annotation Plain object with type and attributes properties * @return {ve.dm.Annotation} Instance of the right ve.dm.Annotation subclass */ ve.dm.example.createAnnotation = function ( annotation ) { return ve.dm.annotationFactory.create( annotation.type, annotation ); }; /** * Create an AnnotationSet from an array of shorthand annotations. * * This calls ve.dm.example.createAnnotation() for each element and puts the result in an * AnnotationSet. * * @method * @param {Array} annotations Array of annotations in shorthand format * @return {ve.dm.AnnotationSet} */ ve.dm.example.createAnnotationSet = function ( store, annotations ) { var i; for ( i = 0; i < annotations.length; i++ ) { annotations[i] = ve.dm.example.createAnnotation( annotations[i] ); } return new ve.dm.AnnotationSet( store, store.indexes( annotations ) ); }; /* Some common annotations in shorthand format */ ve.dm.example.bold = { 'type': 'textStyle/bold' }; ve.dm.example.italic = { 'type': 'textStyle/italic' }; ve.dm.example.underline = { 'type': 'textStyle/underline' }; ve.dm.example.span = { 'type': 'textStyle/span' }; /** * Creates a document from example data. * * Defaults to ve.dm.example.data if no name is supplied. * * @param {string} [name='data'] Named element of ve.dm.example * @param {ve.dm.IndexValueStore} [store] A specific index-value store to use, optionally. * @returns {ve.dm.Document} Document * @throws {Error} Example data not found */ ve.dm.example.createExampleDocument = function ( name, store ) { name = name || 'data'; store = store || new ve.dm.IndexValueStore(); if ( ve.dm.example[name] === undefined ) { throw new Error( 'Example data \'' + name + '\' not found' ); } return new ve.dm.Document( ve.dm.example.preprocessAnnotations( ve.copyArray( ve.dm.example[name] ), store ) ); }; ve.dm.example.testDir = window.mw ? ( window.mw.config.get( 'wgExtensionAssetsPath' ) + '/VisualEditor/modules/ve/test' ) : '.'; ve.dm.example.imgSrc = ve.dm.example.testDir + '/example.png'; /** * Serialized HTML. * * This is what the parser will emit. * TODO remove some of the
s here to test automatic wrapping */ ve.dm.example.html = '
' +
' d ' + '
| ' +
'
hi'+ '
j
' + 'k
' + 'l
' + 'm
'; /* * Linear data. * * This is what we convert serialized HTML from the parser into so we can work with it more easily. * * There are three types of components in content data: * * {string} Plain text character * * {Array} Annotated character * 0: {string} Character * 1: {Object} List of references to immutable annotation objects, keyed by JSON * serializations of their values (hashes) * * {Object} Opening or closing structural element * type: {string} Symbolic node type name, if closing element first character will be "/" * [attributes]: {Object} List of symbolic attribute name and literal value pairs */ ve.dm.example.data = [ // 0 - Beginning of heading { 'type': 'heading', 'attributes': { 'level': 1 } }, // 1 - Plain "a" 'a', // 2 - Bold "b" ['b', [ ve.dm.example.bold ]], // 3 - Italic "c" ['c', [ ve.dm.example.italic ]], // 4 - End of heading { 'type': '/heading' }, // 5 - Beginning of table { 'type': 'table' }, // 6 - Beginning of body { 'type': 'tableSection', 'attributes': { 'style': 'body' } }, // 7 - Beginning of row { 'type': 'tableRow' }, // 8 - Beginning of cell { 'type': 'tableCell', 'attributes': { 'style': 'data' } }, // 9 - Beginning of paragraph { 'type': 'paragraph' }, // 10 - Plain "d" 'd', // 11 - End of paragraph { 'type': '/paragraph' }, // 12 - Beginning of bullet list { 'type': 'list', 'attributes': { 'style': 'bullet' } }, // 13 - Beginning of list item { 'type': 'listItem' }, // 14 - Beginning of paragraph { 'type': 'paragraph' }, // 15 - Plain "e" 'e', // 16 - End of paragraph { 'type': '/paragraph' }, // 17 - Beginning of nested bullet list { 'type': 'list', 'attributes': { 'style': 'bullet' } }, // 18 - Beginning of nested bullet list item { 'type': 'listItem' }, // 19 - Beginning of paragraph { 'type': 'paragraph' }, // 20 - Plain "f" 'f', // 21 - End of paragraph { 'type': '/paragraph' }, // 22 - End of nested bullet list item { 'type': '/listItem' }, // 23 - End of nested bullet list { 'type': '/list' }, // 24 - End of bullet list item { 'type': '/listItem' }, // 25 - End of bullet list { 'type': '/list' }, // 26 - Beginning of numbered list { 'type': 'list', 'attributes': { 'style': 'number' } }, // 27 - Beginning of numbered list item { 'type': 'listItem' }, // 28 - Beginning of paragraph { 'type': 'paragraph' }, // 29 - Plain "g" 'g', // 30 - End of paragraph { 'type': '/paragraph' }, // 31 - End of item { 'type': '/listItem' }, // 32 - End of lis t { 'type': '/list' }, // 33 - End of cell { 'type': '/tableCell' }, // 34 - End of row { 'type': '/tableRow' }, // 35 - End of body { 'type': '/tableSection' }, // 36 - End of table { 'type': '/table' }, // 37 - Beginning of preformatted { 'type': 'preformatted' }, // 38 - Plain "h" 'h', // 39 - Beginning of inline image { 'type': 'image', 'attributes': { 'src': ve.dm.example.imgSrc, 'width': null, 'height': null }, 'htmlAttributes': [ { 'keys': [ 'src' ], 'values': { 'src': ve.dm.example.imgSrc } } ] }, // 40 - End of inline image { 'type': '/image' }, // 41 - Plain "i" 'i', // 42 - End of preformatted { 'type': '/preformatted' }, // 43 - Beginning of definition list { 'type': 'definitionList' }, // 44 - Beginning of definition list term item { 'type': 'definitionListItem', 'attributes': { 'style': 'term' } }, // 45 - Beginning of paragraph { 'type': 'paragraph' }, // 46 - Plain "j" 'j', // 47 - End of paragraph { 'type': '/paragraph' }, // 48 - End of definition list term item { 'type': '/definitionListItem' }, // 49 - Beginning of definition list definition item { 'type': 'definitionListItem', 'attributes': { 'style': 'definition' } }, // 50 - Beginning of paragraph { 'type': 'paragraph' }, // 51 - Plain "k" 'k', // 52 - End of paragraph { 'type': '/paragraph' }, // 53 - End of definition list definition item { 'type': '/definitionListItem' }, // 54 - End of definition list { 'type': '/definitionList' }, // 55 - Beginning of paragraph { 'type': 'paragraph' }, // 56 - Plain "l" 'l', // 57 - End of paragraph { 'type': '/paragraph' }, // 58 - Beginning of paragraph { 'type': 'paragraph' }, // 59 - Plain "m" 'm', // 60 - End of paragraph { 'type': '/paragraph' } // 61 - End of document ]; ve.dm.example.alienData = [ // 0 - Open alienBlock { 'type': 'alienBlock' }, // 1 - Close alienBlock { 'type': '/alienBlock' }, // 2 - Open paragraph { 'type': 'paragraph' }, // 3 - Plain character 'a' 'a', // 4 - Open alienInline { 'type': 'alienBlock' }, // 5 - Close alienInline { 'type': '/alienBlock' }, // 6 - Plain character 'b' 'b', // 7 - Close paragraph { 'type': '/paragraph' }, // 8 - Open alienBlock { 'type': 'alienBlock' }, // 9 - Close alienBlock { 'type': '/alienBlock' } // 10 - End of document ]; ve.dm.example.internalData = [ { 'type': 'paragraph' }, 'F', 'o', 'o', { 'type': '/paragraph' }, { 'type': 'internalList' }, { 'type': 'internalItem' }, { 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } }, 'B', 'a', 'r', { 'type': '/paragraph' }, { 'type': '/internalItem' }, { 'type': 'internalItem' }, { 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } }, 'B', 'a', 'z', { 'type': '/paragraph' }, { 'type': '/internalItem' }, { 'type': '/internalList' }, { 'type': 'paragraph' }, 'Q', 'u', 'u', 'x', { 'type': '/paragraph' } ]; ve.dm.example.withMeta = [ { 'type': 'alienMeta', 'attributes': { 'style': 'comment', 'text': ' No content conversion ' } }, { 'type': '/alienMeta' }, { 'type': 'alienMeta', 'attributes': { 'style': 'meta', 'key': 'mw:PageProp/nocc' }, 'htmlAttributes': [ { 'keys': [ 'property' ], 'values': { 'property': 'mw:PageProp/nocc' } } ] }, { 'type': '/alienMeta' }, { 'type': 'paragraph' }, 'F', 'o', 'o', { 'type': 'MWcategory', 'attributes': { 'hrefPrefix': './', 'category': 'Category:Bar', 'origCategory': 'Category:Bar', 'sortkey': '', 'origSortkey': '' }, 'htmlAttributes': [ { 'keys': [ 'rel', 'href' ], 'values': { 'rel': 'mw:WikiLink/Category', 'href': './Category:Bar' } } ] }, { 'type': '/MWcategory' }, 'B', 'a', 'r', { 'type': 'alienMeta', 'attributes': { 'style': 'meta', 'key': 'mw:foo', 'value': 'bar' }, 'htmlAttributes': [ { 'keys': [ 'property', 'content' ], 'values': { 'property': 'mw:foo', 'content': 'bar' } } ] }, { 'type': '/alienMeta' }, 'B', 'a', { 'type': 'alienMeta', 'attributes': { 'style': 'comment', 'text': ' inline ' } }, { 'type': '/alienMeta' }, 'z', { 'type': '/paragraph' }, { 'type': 'alienMeta', 'attributes': { 'style': 'meta', 'key': 'mw:bar', 'value': 'baz' }, 'htmlAttributes': [ { 'keys': [ 'property', 'content' ], 'values': { 'property': 'mw:bar', 'content': 'baz' } } ] }, { 'type': '/alienMeta' }, { 'type': 'alienMeta', 'attributes': { 'style': 'comment', 'text': 'barbaz' } }, { 'type': '/alienMeta' }, { 'type': 'MWcategory', 'attributes': { 'hrefPrefix': './', 'category': 'Category:Foo foo', 'origCategory': 'Category:Foo_foo', 'sortkey': 'Bar baz#quux', 'origSortkey': 'Bar baz%23quux' }, 'htmlAttributes': [ { 'keys': [ 'rel', 'href' ], 'values': { 'rel': 'mw:WikiLink/Category', 'href': './Category:Foo_foo#Bar baz%23quux' } } ] }, { 'type': '/MWcategory' }, { 'type': 'alienMeta', 'attributes': { 'style': 'meta', 'key': null }, 'htmlAttributes': [ { 'keys': [ 'typeof', 'data-parsoid' ], 'values': { 'typeof': 'mw:Placeholder', 'data-parsoid': 'foobar' } } ] }, { 'type': '/alienMeta' } ]; ve.dm.example.withMetaPlainData = [ { 'type': 'paragraph' }, 'F', 'o', 'o', 'B', 'a', 'r', 'B', 'a', 'z', { 'type': '/paragraph' } ]; ve.dm.example.withMetaMetaData = [ [ { 'type': 'alienMeta', 'attributes': { 'style': 'comment', 'text': ' No content conversion ' } }, { 'type': 'alienMeta', 'attributes': { 'style': 'meta', 'key': 'mw:PageProp/nocc' }, 'htmlAttributes': [ { 'keys': [ 'property' ], 'values': { 'property': 'mw:PageProp/nocc' } } ] } ], undefined, undefined, undefined, [ { 'type': 'MWcategory', 'attributes': { 'hrefPrefix': './', 'category': 'Category:Bar', 'origCategory': 'Category:Bar', 'sortkey': '', 'origSortkey': '' }, 'htmlAttributes': [ { 'keys': [ 'rel', 'href' ], 'values': { 'rel': 'mw:WikiLink/Category', 'href': './Category:Bar' } } ] } ], undefined, undefined, [ { 'type': 'alienMeta', 'attributes': { 'style': 'meta', 'key': 'mw:foo', 'value': 'bar' }, 'htmlAttributes': [ { 'keys': [ 'property', 'content' ], 'values': { 'property': 'mw:foo', 'content': 'bar' } } ] } ], undefined, [ { 'type': 'alienMeta', 'attributes': { 'style': 'comment', 'text': ' inline ' } } ], undefined, [ { 'type': 'alienMeta', 'attributes': { 'style': 'meta', 'key': 'mw:bar', 'value': 'baz' }, 'htmlAttributes': [ { 'keys': [ 'property', 'content' ], 'values': { 'property': 'mw:bar', 'content': 'baz' } } ] }, { 'type': 'alienMeta', 'attributes': { 'style': 'comment', 'text': 'barbaz' } }, { 'type': 'MWcategory', 'attributes': { 'hrefPrefix': './', 'category': 'Category:Foo foo', 'origCategory': 'Category:Foo_foo', 'sortkey': 'Bar baz#quux', 'origSortkey': 'Bar baz%23quux' }, 'htmlAttributes': [ { 'keys': [ 'rel', 'href' ], 'values': { 'rel': 'mw:WikiLink/Category', 'href': './Category:Foo_foo#Bar baz%23quux' } } ] }, { 'type': 'alienMeta', 'attributes': { 'style': 'meta', 'key': null }, 'htmlAttributes': [ { 'keys': [ 'typeof', 'data-parsoid' ], 'values': { 'typeof': 'mw:Placeholder', 'data-parsoid': 'foobar' } } ] } ] ]; ve.dm.example.complexTableHtml = 'Bar | |
---|---|
Baz | |
Quux | Whee |
Hello, world!
', 'blockData': { 'type': 'MWtemplateBlock', 'attributes': { 'mw': { 'id': 'mwt1', 'target': { 'wt' : 'Test' }, 'params': { '1': { 'wt': 'Hello, world!' } } }, 'mwOriginal': { 'id': 'mwt1', 'target': { 'wt' : 'Test' }, 'params': { '1': { 'wt': 'Hello, world!' } } }, }, 'htmlAttributes': [ { 'keys': [ 'about', 'typeof', 'data-mw', 'data-parsoid' ], 'values': { 'about': '#mwt1', 'data-mw': '{\"id\":\"mwt1\",\"target\":{\"wt\":\"Test\"},\"params\":{\"1\":{\"wt\":\"Hello, world!\"}}}', 'data-parsoid': '{\"tsr\":[18,40],\"src\":\"{{Test|Hello, world!}}\",\"dsr\":[18,40,null,null]}', 'typeof': 'mw:Object/Template' } }, { 'keys': [ 'about', 'data-parsoid' ], 'values': { 'about': '#mwt1', 'data-parsoid': '{}' } } ] }, 'inlineOpen': '', 'inlineOpenModified': '', 'inlineContent': '$1,234.00', 'inlineClose': '', 'inlineData': { 'type': 'MWtemplateInline', 'attributes': { 'mw': { 'id': 'mwt1', 'target': { 'wt' : 'Inline' }, 'params': { '1': { 'wt': '1,234' } } }, 'mwOriginal': { 'id': 'mwt1', 'target': { 'wt' : 'Inline' }, 'params': { '1': { 'wt': '1,234' } } } }, 'htmlAttributes': [ { 'keys': [ 'about', 'typeof', 'data-mw', 'data-parsoid' ], 'values': { 'about': '#mwt1', 'data-mw': '{\"id\":\"mwt1\",\"target\":{\"wt\":\"Inline\"},\"params\":{\"1\":{\"wt\":\"1,234\"}}}', 'data-parsoid': '{\"tsr\":[18,34],\"src\":\"{{Inline|1,234}}\",\"dsr\":[18,34,null,null]}', 'typeof': 'mw:Object/Template' } } ] }, 'mixed': 'Foo', 'mixedDataOpen': { 'type': 'MWtemplateInline', 'attributes': { 'mw': { 'id': 'mwt1', 'target': { 'wt': 'Inline' }, 'params': { '1': { 'wt': '5,678' } } }, 'mwOriginal': { 'id': 'mwt1', 'target': { 'wt': 'Inline' }, 'params': { '1': { 'wt': '5,678' } } } }, 'htmlAttributes': [ { 'keys': [ 'about', 'rel', 'typeof', 'data-mw' ], 'values': { 'about': '#mwt1', 'rel': 'mw:WikiLink/Category', 'typeof': 'mw:Object/Template', 'data-mw': '{\"id\":\"mwt1\",\"target\":{\"wt\":\"Inline\"},\"params\":{\"1\":{\"wt\":\"5,678\"}}}' } }, { 'keys': [ 'about' ], 'values': { 'about': '#mwt1' } } ] }, 'mixedDataClose' : { 'type': '/MWtemplateInline' } }; ve.dm.example.MWTemplate.blockParamsHash = ve.getHash( ve.dm.MWTemplateNode.static.getHashObject( ve.dm.example.MWTemplate.blockData ) ); ve.dm.example.MWTemplate.blockStoreItems = { 'hash': ve.dm.example.MWTemplate.blockParamsHash, 'value': $( ve.dm.example.MWTemplate.blockSpan + ve.dm.example.MWTemplate.blockContent ).get() }; ve.dm.example.MWTemplate.inlineParamsHash = ve.getHash( ve.dm.MWTemplateNode.static.getHashObject( ve.dm.example.MWTemplate.inlineData ) ); ve.dm.example.MWTemplate.inlineStoreItems = { 'hash': ve.dm.example.MWTemplate.inlineParamsHash, 'value': $( ve.dm.example.MWTemplate.inlineOpen + ve.dm.example.MWTemplate.inlineContent + ve.dm.example.MWTemplate.inlineClose ).get() }; ve.dm.example.MWTemplate.mixedParamsHash = ve.getHash( ve.dm.MWTemplateNode.static.getHashObject( ve.dm.example.MWTemplate.mixedDataOpen ) ); ve.dm.example.MWTemplate.mixedStoreItems = { 'hash': ve.dm.example.MWTemplate.mixedParamsHash, 'value': $( ve.dm.example.MWTemplate.mixed ).get() }; ve.dm.example.domToDataCases = { 'paragraph with plain text': { 'html': 'abc
', 'data': [ { 'type': 'paragraph' }, 'a', 'b', 'c', { 'type': '/paragraph' } ] }, 'annotated text with bold, italic, underline formatting': { 'html': 'abc
', 'data': [ { 'type': 'paragraph' }, ['a', [ ve.dm.example.bold ]], ['b', [ ve.dm.example.italic ]], ['c', [ ve.dm.example.underline ]], { 'type': '/paragraph' } ] }, 'image': { 'html': '', 'data': [ { 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } }, { 'type': 'image', 'attributes' : { 'width': null, 'height': null, 'src': ve.dm.example.imgSrc }, 'htmlAttributes': [ { 'keys': [ 'src' ], 'values': { 'src': ve.dm.example.imgSrc } } ] }, { 'type' : '/image' }, { 'type': '/paragraph' } ] }, 'mw:Image': { 'html': '' + ve.dm.example.MWInlineImageHtml + '
', 'data': [ { 'type': 'paragraph' }, { 'type': 'MWinlineimage', 'attributes': { 'src': '/index.php?title=Special:FilePath/Wiki.png&width=500', 'width': 500, 'height': null, 'isLinked': true }, 'htmlAttributes': [ { 'keys': [ 'rel', 'href', 'data-parsoid' ], 'values': { 'data-parsoid': '{"tsr":[158,216],"src":"[[Image:Wiki.png|500px|thumb|center|Example wiki file]]","optNames":{"width":"$1px"},"dsr":[158,216,null,null]}', 'href': './File:Wiki.png', 'rel': 'mw:Image' }, 'children': [ { 'keys': [ 'height', 'width', 'src', 'alt' ], 'values': { 'alt': 'Wiki.png', 'height': '', 'src': '/index.php?title=Special:FilePath/Wiki.png&width=500', 'width': '500' } } ] } ] }, { 'type': '/MWinlineimage' }, { 'type': '/paragraph' } ] }, 'mw:Template (block level)': { 'html': '' + ve.dm.example.MWTemplate.blockSpan + ve.dm.example.MWTemplate.blockContent + '', 'data': [ ve.dm.example.MWTemplate.blockData, { 'type': '/MWtemplateBlock' }, ], 'storeItems': [ ve.dm.example.MWTemplate.blockStoreItems ], 'normalizedHtml': ve.dm.example.MWTemplate.blockSpan + ve.dm.example.MWTemplate.blockContent }, 'mw:Template (block level - modified)': { 'html': '' + ve.dm.example.MWTemplate.blockSpan + ve.dm.example.MWTemplate.blockContent + '', 'data': [ ve.dm.example.MWTemplate.blockData, { 'type': '/MWtemplateBlock' }, ], 'storeItems': [ ve.dm.example.MWTemplate.blockStoreItems ], 'modify': function ( data ) { data[0].attributes.mw.params['1'].wt = 'Hello, globe!'; }, 'normalizedHtml': ve.dm.example.MWTemplate.blockSpanModified }, 'mw:Template (inline)': { 'html': '' + ve.dm.example.MWTemplate.inlineOpen + ve.dm.example.MWTemplate.inlineContent + ve.dm.example.MWTemplate.inlineClose + '', 'data': [ { 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } }, ve.dm.example.MWTemplate.inlineData, { 'type': '/MWtemplateInline' }, { 'type': '/paragraph' } ], 'storeItems': [ ve.dm.example.MWTemplate.inlineStoreItems ], 'normalizedHtml': ve.dm.example.MWTemplate.inlineOpen + ve.dm.example.MWTemplate.inlineContent + ve.dm.example.MWTemplate.inlineClose }, 'mw:Template (inline - modified)': { 'html': '' + ve.dm.example.MWTemplate.inlineOpen + ve.dm.example.MWTemplate.inlineContent + ve.dm.example.MWTemplate.inlineClose + '', 'data': [ { 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } }, ve.dm.example.MWTemplate.inlineData, { 'type': '/MWtemplateInline' }, { 'type': '/paragraph' } ], 'storeItems': [ ve.dm.example.MWTemplate.inlineStoreItems ], 'modify': function ( data ) { data[1].attributes.mw.params['1'].wt = '5,678'; }, 'normalizedHtml': ve.dm.example.MWTemplate.inlineOpenModified + ve.dm.example.MWTemplate.inlineClose }, 'mw:Reference': { 'html': '' + 'Foo' + 'Bar"}">'+ '[1]' + '' + ' Baz' + 'Quux"}">' + '[2]' + '' + ' Whee' + '"}">' + '[1]' + '
' + ' Yay' + 'No name"}">' + '[3]' + '' + '' + 'Foo' + 'Bar"}">'+ '' + ' Baz' + 'Quux"}">' + '' + ' Whee' + '"}">' + '' + ' Yay' + 'No name"}">' + '' + '
' + 'abc
', 'data': [ { 'type': 'paragraph' }, 'a', { 'type': 'alienInline', 'attributes': { 'domElements': $( 'b' ).get() } }, { 'type': '/alienInline' }, 'c', { 'type': '/paragraph' } ] }, 'paragraphs with an alienBlock between them': { 'html': 'abc
def
', 'data': [ { 'type': 'paragraph' }, 'a', 'b', 'c', { 'type': '/paragraph' }, { 'type': 'alienBlock', 'attributes': { 'domElements': $( '' ).get() } }, { 'type': '/alienBlock' }, { 'type': 'paragraph' }, 'd', 'e', 'f', { 'type': '/paragraph' } ] }, 'annotated inline nodes': { 'html': 'abc' +
'
de
abc
def', 'data': [ { 'type': 'paragraph' }, 'a', 'b', 'c', { 'type': '/paragraph' }, { 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } }, 'd', 'e', 'f', { 'type': '/paragraph' }, { 'type': 'paragraph' }, { 'type': '/paragraph' } ] }, 'wrapping prevents empty list items': { 'html': 'Foo
' }, 'empty list item with content added by the editor': { 'html': null, 'data': [ { 'type': 'list', 'attributes': { 'style': 'bullet' } }, { 'type': 'listItem' }, { 'type': 'paragraph', 'internal': { 'generated': 'empty' } }, 'F', 'o', 'o', { 'type': '/paragraph' }, { 'type': '/listItem' }, { 'type': '/list' } ], 'normalizedHtml': 'Foo
Foo
', 'data': [ { 'type': 'paragraph', 'internal': { 'whitespace': [ undefined, ' ', ' ' ] } }, [ ' ', [ ve.dm.example.italic ] ], [ ' ', [ ve.dm.example.italic ] ], [ 'F', [ ve.dm.example.italic ] ], [ 'o', [ ve.dm.example.italic ] ], [ 'o', [ ve.dm.example.italic ] ], [ ' ', [ ve.dm.example.italic ] ], [ ' ', [ ve.dm.example.italic ] ], [ ' ', [ ve.dm.example.italic ] ], { 'type': '/paragraph' } ] }, 'outer whitespace preservation in a list with bare text and a wrapper paragraph': { 'html': '\n\t\tP\t\t\t
\t\t\t\tP
A B C\t\t\tD\t\t\t
\nE\n\nF\n\n\n\n\n\n\nG H ', 'data': [ { 'type': 'paragraph', 'internal': { 'whitespace': [ undefined, ' ', '\t\t\t', '\n' ] } }, 'A', ' ', ' ', 'B', ' ', ' ', ' ', [ ' ', [ ve.dm.example.bold ] ], [ ' ', [ ve.dm.example.bold ] ], [ ' ', [ ve.dm.example.bold ] ], [ ' ', [ ve.dm.example.bold ] ], [ 'C', [ ve.dm.example.bold ] ], [ '\t', [ ve.dm.example.bold ] ], '\t', '\t', 'D', { 'type': '/paragraph' }, { 'type': 'paragraph', 'internal': { 'generated': 'wrapper', 'whitespace': [ '\n', undefined, undefined, ' ' ] } }, 'E', '\n', '\n', 'F', '\n', '\n', '\n', [ '\n', [ ve.dm.example.bold ] ], [ '\n', [ ve.dm.example.bold ] ], [ '\n', [ ve.dm.example.bold ] ], [ '\n', [ ve.dm.example.bold ] ], [ 'G', [ ve.dm.example.bold ] ], [ ' ', [ ve.dm.example.bold ] ], ' ', ' ', 'H', { 'type': '/paragraph' } ] }, 'whitespace preservation with non-edge content whitespace with nested annotations': { 'html': 'A B C\t\t\tD\t\t\t\t\t\t\tE\n\n\nF\n\n\n
', 'data': [ { 'type': 'paragraph', 'internal': { 'whitespace': [ undefined, ' ', '\n\n\n' ] } }, 'A', ' ', ' ', 'B', ' ', ' ', ' ', [ ' ', [ ve.dm.example.bold ] ], [ ' ', [ ve.dm.example.bold ] ], [ ' ', [ ve.dm.example.bold ] ], [ ' ', [ ve.dm.example.bold ] ], [ 'C', [ ve.dm.example.bold ] ], [ '\t', [ ve.dm.example.bold ] ], [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ 'D', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ '\t', [ ve.dm.example.bold ] ], [ '\t', [ ve.dm.example.bold ] ], [ '\t', [ ve.dm.example.bold ] ], [ '\t', [ ve.dm.example.bold ] ], [ 'E', [ ve.dm.example.bold ] ], [ '\n', [ ve.dm.example.bold ] ], '\n', '\n', 'F', { 'type': '/paragraph' } ] }, 'whitespace preservation with tightly nested annotations': { 'html': 'A B \t\tC\t\t\t\n\nD\n\n\n
', 'data': [ { 'type': 'paragraph', 'internal': { 'whitespace': [ undefined, ' ', '\n\n\n' ] } }, 'A', ' ', ' ', 'B', ' ', ' ', ' ', [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ 'C', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], '\n', '\n', 'D', { 'type': '/paragraph' } ] }, 'whitespace preservation with nested annotations with whitespace on the left side': { 'html': 'A B \n\t\t\tC\t\t\t\n\nD\n\n\n
', 'data': [ { 'type': 'paragraph', 'internal': { 'whitespace': [ undefined, ' ', '\n\n\n' ] } }, 'A', ' ', ' ', 'B', ' ', ' ', ' ', [ '\n', [ ve.dm.example.bold ] ], [ '\t', [ ve.dm.example.bold ] ], [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ 'C', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], '\n', '\n', 'D', { 'type': '/paragraph' } ] }, 'whitespace preservation with nested annotations with whitespace on the right side': { 'html': 'A B \t\tC\t\t\t\n\t\n\nD\n\n\n
', 'data': [ { 'type': 'paragraph', 'internal': { 'whitespace': [ undefined, ' ', '\n\n\n' ] } }, 'A', ' ', ' ', 'B', ' ', ' ', ' ', [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ 'C', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ '\t', [ ve.dm.example.bold, ve.dm.example.italic ] ], [ '\n', [ ve.dm.example.bold ] ], [ '\t', [ ve.dm.example.bold ] ], '\n', '\n', 'D', { 'type': '/paragraph' } ] }, 'whitespace preservation with aliens': { 'html': '
\tFoo\t\t\t\t\tBar\t\t\t\t\nBaz\n\n\n\n\nQuux\n\n\n\n \tWhee \n
\t\n \n ', 'data': [ { 'type': 'alienBlock', 'attributes': { 'domElements': $( '
': { 'html': '\n\n\n\nFoo\n\n\nBar\n\n\n\n\n\n\n\n\n', 'data': [ { 'type': 'preformatted', 'internal': { 'whitespace': ['\n', undefined, undefined, '\n\n\n\n\n' ] } }, '\n', '\n', 'F', 'o', 'o', '\n', '\n', '\n', 'B', 'a', 'r', '\n', '\n', '\n', '\n', { 'type': '/preformatted' } ] }, 'whitespace preservation in table cell starting with text and ending with annotation': { 'html': '
Foo Bar |
bar
', 'data': [ { 'type': 'paragraph', 'internal': { 'whitespace': [ undefined, ' ', ' ' ] } }, { 'type': 'alienMeta', 'attributes': { 'style': 'comment', 'text': ' foo ' } }, { 'type': '/alienMeta' }, 'b', 'a', 'r', { 'type': 'alienMeta', 'attributes': { 'style': 'comment', 'text': ' baz ' } }, { 'type': '/alienMeta' }, { 'type': '/paragraph' } ] }, 'mismatching whitespace data is ignored': { 'html': null, 'data': [ { 'type': 'list', 'attributes': { 'style': 'bullet' }, 'internal': { 'whitespace': [ ' ', ' ', ' ', ' ' ] } }, { 'type': 'listItem', 'internal': { 'whitespace': [ ' ', ' ', ' ', ' ' ] } }, { 'type': 'paragraph', 'internal': { 'whitespace': [ ' ', '\t', '\n', ' ' ] } }, 'A', { 'type': '/paragraph' }, { 'type': 'paragraph', 'internal': { 'whitespace': [ ' ' ] } }, 'B', { 'type': '/paragraph' }, { 'type': '/listItem' }, { 'type': '/list' } ], 'normalizedHtml': '\tA\n
B
Foobarbaz
', 'data': [ { 'type': 'paragraph' }, [ 'F', [ { 'type': 'link/MWinternal', 'attributes': { 'hrefPrefix': '', 'origTitle': 'Foo', 'title': 'Foo' }, 'htmlAttributes': [ { 'keys': [ 'rel', 'href' ], 'values': { 'href': 'Foo', 'rel': 'mw:WikiLink' } } ] } ] ], [ 'o', [ { 'type': 'link/MWinternal', 'attributes': { 'hrefPrefix': '', 'origTitle': 'Foo', 'title': 'Foo' }, 'htmlAttributes': [ { 'keys': [ 'rel', 'href' ], 'values': { 'href': 'Foo', 'rel': 'mw:WikiLink' } } ] }, ve.dm.example.bold ] ], [ 'o', [ { 'type': 'link/MWinternal', 'attributes': { 'hrefPrefix': '', 'origTitle': 'Foo', 'title': 'Foo' }, 'htmlAttributes': [ { 'keys': [ 'rel', 'href' ], 'values': { 'href': 'Foo', 'rel': 'mw:WikiLink' } } ] }, ve.dm.example.bold, ve.dm.example.italic ] ], [ 'b', [ { 'type': 'link/MWinternal', 'attributes': { 'hrefPrefix': '', 'origTitle': 'Foo', 'title': 'Foo' }, 'htmlAttributes': [ { 'keys': [ 'rel', 'href' ], 'values': { 'href': 'Foo', 'rel': 'mw:WikiLink' } } ] }, ve.dm.example.italic ] ], [ 'a', [ ve.dm.example.italic ] ], [ 'r', [ ve.dm.example.italic, ve.dm.example.bold ] ], [ 'b', [ ve.dm.example.italic ] ], [ 'a', [ ve.dm.example.italic, ve.dm.example.underline ] ], [ 'z', [ ve.dm.example.italic ] ], { 'type': '/paragraph' } ] }, 'document with meta elements': { 'html': 'Foo' + 'Bar' + 'Baz
' + '' + '' + '', 'data': ve.dm.example.withMeta }, 'RDFa types spread across two attributes, about grouping is forced': { 'html': '' + ve.dm.example.MWTemplate.mixed + '', 'data': [ { 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } }, ve.dm.example.MWTemplate.mixedDataOpen, ve.dm.example.MWTemplate.mixedDataClose, { 'type': '/paragraph' } ], 'storeItems': [ ve.dm.example.MWTemplate.mixedStoreItems ] }, 'about grouping': { 'html': 'Whee
Yay' + 'a¢b¥™
', 'data': [ { 'type': 'paragraph' }, 'a', { 'type': 'MWentity', 'attributes': { 'character': '¢' }, 'htmlAttributes': [ { 'keys': [ 'typeof' ], 'values': { 'typeof': 'mw:Entity' } } ] }, { 'type': '/MWentity' }, 'b', { 'type': 'MWentity', 'attributes': { 'character': '¥' }, 'htmlAttributes': [ { 'keys': [ 'typeof' ], 'values': { 'typeof': 'mw:Entity' } } ] }, { 'type': '/MWentity' }, { 'type': 'MWentity', 'attributes': { 'character': '™' }, 'htmlAttributes': [ { 'keys': [ 'typeof' ], 'values': { 'typeof': 'mw:Entity' } } ] }, { 'type': '/MWentity' }, { 'type': '/paragraph' } ] }, 'wrapping with mw:Entity': { 'html': 'a¢b¥™', 'data': [ { 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } }, 'a', { 'type': 'MWentity', 'attributes': { 'character': '¢' }, 'htmlAttributes': [ { 'keys': [ 'typeof' ], 'values': { 'typeof': 'mw:Entity' } } ] }, { 'type': '/MWentity' }, 'b', { 'type': 'MWentity', 'attributes': { 'character': '¥' }, 'htmlAttributes': [ { 'keys': [ 'typeof' ], 'values': { 'typeof': 'mw:Entity' } } ] }, { 'type': '/MWentity' }, { 'type': 'MWentity', 'attributes': { 'character': '™' }, 'htmlAttributes': [ { 'keys': [ 'typeof' ], 'values': { 'typeof': 'mw:Entity' } } ] }, { 'type': '/MWentity' }, { 'type': '/paragraph' } ] }, 'whitespace preservation with mw:Entity': { 'html': 'a b ¥\t™
', 'data': [ { 'type': 'paragraph', 'internal': { 'whitespace': [ undefined, ' ' ] } }, 'a', ' ', ' ', { 'type': 'MWentity', 'attributes': { 'character': ' ' }, 'htmlAttributes': [ { 'keys': [ 'typeof' ], 'values': { 'typeof': 'mw:Entity' } } ] }, { 'type': '/MWentity' }, ' ', ' ', ' ', 'b', ' ', ' ', ' ', ' ', { 'type': 'MWentity', 'attributes': { 'character': '¥' }, 'htmlAttributes': [ { 'keys': [ 'typeof' ], 'values': { 'typeof': 'mw:Entity' } } ] }, { 'type': '/MWentity' }, '\t', { 'type': 'MWentity', 'attributes': { 'character': '™' }, 'htmlAttributes': [ { 'keys': [ 'typeof' ], 'values': { 'typeof': 'mw:Entity' } } ] }, { 'type': '/MWentity' }, { 'type': '/paragraph' } ] }, 'block node inside annotation node is alienated': { 'html': '\nBar
', 'data': [ { 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } }, [ '\n', [ ve.dm.example.span ] ], { 'type': 'alienInline', 'attributes': { 'domElements': $( 'Bar
' ).get() }, 'annotations': [ ve.dm.example.span ] }, { 'type': '/alienInline' }, { 'type': '/paragraph' } ] }, 'block node inside annotation node surrounded by tables': { 'html': 'Bar
Bar
' ).get() }, 'annotations': [ ve.dm.example.span ] }, { 'type': '/alienInline' }, { 'type': '/paragraph' }, { 'type': 'table' }, { 'type': '/table' } ] }, 'block node inside annotation node is alienated and continues wrapping': { 'html': 'Foo\nBar
Baz', 'data': [ { 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } }, 'F', 'o', 'o', [ '\n', [ ve.dm.example.span ] ], { 'type': 'alienInline', 'attributes': { 'domElements': $( 'Bar
' ).get() }, 'annotations': [ ve.dm.example.span ] }, { 'type': '/alienInline' }, 'B', 'a', 'z', { 'type': '/paragraph' } ] }, 'whitespace before meta node in wrapping mode': { 'html': 'Foo\n |
abcde
', 'data': [ { 'type': 'div', 'htmlAttributes': [ { 'keys': [ 'style' ], 'values': { 'style': 'direction: rtl;' } } ] }, { 'type': 'paragraph' }, 'a', ['b', [ ve.dm.example.bold ]], 'c', ['d', [ ve.dm.example.italic ]], 'e', { 'type': '/paragraph' }, { 'type': '/div' } ] }, 'thumb image': { 'html': '', 'data': [ { 'type': 'MWblockimage', 'attributes': { 'type': 'thumb', 'align': 'right', 'href': 'Foo', 'src': 'Bar', 'width': '1', 'height': '2', 'resource': 'FooBar' } }, { 'type': 'MWimagecaption' }, { 'type': '/MWimagecaption' }, { 'type': '/MWblockimage' } ] } }; ve.dm.example.isolationHTML = 'Cell 1 | Cell 2 | Cell 3 |
Cell 4 |
Preformatted in list
P1
P2
P3