diff --git a/VisualEditor.php b/VisualEditor.php index 3be6ccf5ce..0eb7be1ed6 100644 --- a/VisualEditor.php +++ b/VisualEditor.php @@ -271,6 +271,7 @@ $wgResourceModules += array( 've/dm/nodes/ve.dm.ListNode.js', 've/dm/nodes/ve.dm.ParagraphNode.js', 've/dm/nodes/ve.dm.PreformattedNode.js', + 've/dm/nodes/ve.dm.TableCaptionNode.js', 've/dm/nodes/ve.dm.TableCellNode.js', 've/dm/nodes/ve.dm.TableNode.js', 've/dm/nodes/ve.dm.TableRowNode.js', @@ -324,6 +325,7 @@ $wgResourceModules += array( 've/ce/nodes/ve.ce.ListNode.js', 've/ce/nodes/ve.ce.ParagraphNode.js', 've/ce/nodes/ve.ce.PreformattedNode.js', + 've/ce/nodes/ve.ce.TableCaptionNode.js', 've/ce/nodes/ve.ce.TableCellNode.js', 've/ce/nodes/ve.ce.TableNode.js', 've/ce/nodes/ve.ce.TableRowNode.js', @@ -516,7 +518,6 @@ $wgResourceModules += array( ), ), ); - // Parsoid Wrapper API $wgAutoloadClasses['ApiVisualEditor'] = $dir . 'ApiVisualEditor.php'; $wgAPIModules['visualeditor'] = 'ApiVisualEditor'; diff --git a/demos/ve/index.php b/demos/ve/index.php index ca7deaea26..af9385e92f 100644 --- a/demos/ve/index.php +++ b/demos/ve/index.php @@ -155,6 +155,7 @@ $html = file_get_contents( $page ); + @@ -208,6 +209,7 @@ $html = file_get_contents( $page ); + diff --git a/modules/ve/ce/nodes/ve.ce.TableCaptionNode.js b/modules/ve/ce/nodes/ve.ce.TableCaptionNode.js new file mode 100644 index 0000000000..67741ed1fc --- /dev/null +++ b/modules/ve/ce/nodes/ve.ce.TableCaptionNode.js @@ -0,0 +1,31 @@ +/*! + * VisualEditor ContentEditable TableCaptionNode class. + * + * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt + * @license The MIT License (MIT); see LICENSE.txt + */ + +/** + * ContentEditable table caption node. + * + * @class + * @extends ve.ce.BranchNode + * @constructor + * @param {ve.dm.TableCaptionNode} model Model to observe + */ +ve.ce.TableCaptionNode = function VeCeTableCaptionNode( model ) { + // Parent constructor + ve.ce.BranchNode.call( this, model, $( '' ) ); +}; + +/* Inheritance */ + +ve.inheritClass( ve.ce.TableCaptionNode, ve.ce.BranchNode ); + +/* Static Properties */ + +ve.ce.TableCaptionNode.static.name = 'tableCaption'; + +/* Registration */ + +ve.ce.nodeFactory.register( ve.ce.TableCaptionNode ); diff --git a/modules/ve/dm/nodes/ve.dm.TableCaptionNode.js b/modules/ve/dm/nodes/ve.dm.TableCaptionNode.js new file mode 100644 index 0000000000..0ec55a2ee3 --- /dev/null +++ b/modules/ve/dm/nodes/ve.dm.TableCaptionNode.js @@ -0,0 +1,44 @@ +/*! + * VisualEditor DataModel TableCaptionNode class. + * + * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt + * @license The MIT License (MIT); see LICENSE.txt + */ + +/** + * DataModel table caption node. + * + * @class + * @extends ve.dm.BranchNode + * @constructor + * @param {ve.dm.BranchNode[]} [children] Child nodes to attach + * @param {Object} [element] Reference to element in linear model + */ +ve.dm.TableCaptionNode = function VeDmTableCaptionNode( children, element ) { + // Parent constructor + ve.dm.BranchNode.call( this, children, element ); +}; + +/* Inheritance */ + +ve.inheritClass( ve.dm.TableCaptionNode, ve.dm.BranchNode ); + +/* Static Properties */ + +ve.dm.TableCaptionNode.static.name = 'tableCaption'; + +ve.dm.TableCaptionNode.static.parentNodeTypes = [ 'table' ]; + +ve.dm.TableCaptionNode.static.matchTagNames = [ 'caption' ]; + +ve.dm.TableCaptionNode.static.toDataElement = function () { + return { 'type': 'tableCaption' }; +}; + +ve.dm.TableCaptionNode.static.toDomElements = function ( dataElement, doc ) { + return [ doc.createElement( 'caption' ) ]; +}; + +/* Registration */ + +ve.dm.modelRegistry.register( ve.dm.TableCaptionNode ); diff --git a/modules/ve/test/dm/ve.dm.example.js b/modules/ve/test/dm/ve.dm.example.js index 2caeddfb2e..01086f50aa 100644 --- a/modules/ve/test/dm/ve.dm.example.js +++ b/modules/ve/test/dm/ve.dm.example.js @@ -570,6 +570,63 @@ ve.dm.example.withMetaMetaData = [ ] ]; +ve.dm.example.complexTableHtml = '' + + '
Foo
Bar
Baz
QuuxWhee
'; + +ve.dm.example.complexTable = [ + { 'type': 'table' }, + { 'type': 'tableCaption' }, + { 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } }, + 'F', + 'o', + 'o', + { 'type': '/paragraph' }, + { 'type': '/tableCaption' }, + { 'type': 'tableSection', 'attributes': { 'style': 'header' } }, + { 'type': 'tableRow' }, + { 'type': 'tableCell', 'attributes': { 'style': 'header' } }, + { 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } }, + 'B', + 'a', + 'r', + { 'type': '/paragraph' }, + { 'type': '/tableCell' }, + { 'type': '/tableRow' }, + { 'type': '/tableSection' }, + { 'type': 'tableSection', 'attributes': { 'style': 'footer' } }, + { 'type': 'tableRow' }, + { 'type': 'tableCell', 'attributes': { 'style': 'data' } }, + { 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } }, + 'B', + 'a', + 'z', + { 'type': '/paragraph' }, + { 'type': '/tableCell' }, + { 'type': '/tableRow' }, + { 'type': '/tableSection' }, + { 'type': 'tableSection', 'attributes': { 'style': 'body' } }, + { 'type': 'tableRow' }, + { 'type': 'tableCell', 'attributes': { 'style': 'data' } }, + { 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } }, + 'Q', + 'u', + 'u', + 'x', + { 'type': '/paragraph' }, + { 'type': '/tableCell' }, + { 'type': 'tableCell', 'attributes': { 'style': 'data' } }, + { 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } }, + 'W', + 'h', + 'e', + 'e', + { 'type': '/paragraph' }, + { 'type': '/tableCell' }, + { 'type': '/tableRow' }, + { 'type': '/tableSection' }, + { 'type': '/table' } +]; + /** * Sample content data index. * @@ -2370,26 +2427,6 @@ ve.dm.example.domToDataCases = { { 'type': '/paragraph' } ] }, - 'context-sensitive nodes are alienated correctly': { - 'html': '
Foo
Bar
', - 'data': [ - { 'type': 'table' }, - { 'type': 'alienBlock', 'attributes': { 'html': 'Foo' } }, - { 'type': '/alienBlock' }, - { 'type': 'tableSection', 'attributes': { 'style': 'body' } }, - { 'type': 'tableRow' }, - { 'type': 'tableCell', 'attributes': { 'style': 'data' } }, - { 'type': 'paragraph', 'internal': { 'generated': 'wrapper' } }, - 'B', - 'a', - 'r', - { 'type': '/paragraph' }, - { 'type': '/tableCell' }, - { 'type': '/tableRow' }, - { 'type': '/tableSection' }, - { 'type': '/table' } - ] - }, 'whitespace before meta node in wrapping mode': { 'html': '
Foo\n
', 'data': [ @@ -2429,6 +2466,10 @@ ve.dm.example.domToDataCases = { { 'type': '/tableSection' }, { 'type': '/table' } ] + }, + 'table with caption, head, foot and body': { + 'html': ve.dm.example.complexTableHtml, + 'data': ve.dm.example.complexTable } }; diff --git a/modules/ve/test/index.php b/modules/ve/test/index.php index 49bc925310..138fc64c65 100644 --- a/modules/ve/test/index.php +++ b/modules/ve/test/index.php @@ -98,6 +98,7 @@ + @@ -151,6 +152,7 @@ +