Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | 1x 6x 1x 1x 1x 1x 4x 4x 4x 1x 2x 2x 1x 2x 2x 1x 5x 5x 5x 5x 5x 3x 5x 5x 5x 5x 5x 5x 5x 2x 2x 2x 3x 3x 3x 3x 3x 3x 5x 3x 5x 1x 1x 1x 1x 1x 1x 1x 1x 1x 3x 1x 1x 1x 1x | /*! * VisualEditor UserInterface ListAction class. * * @copyright See AUTHORS.txt */ /** * List action. * * @class * @extends ve.ui.Action * @constructor * @param {ve.ui.Surface} surface Surface to act on * @param {string} [source] */ ve.ui.ListAction = function VeUiListAction() { // Parent constructor ve.ui.ListAction.super.apply( this, arguments ); }; /* Inheritance */ OO.inheritClass( ve.ui.ListAction, ve.ui.Action ); /* Static Properties */ ve.ui.ListAction.static.name = 'list'; ve.ui.ListAction.static.methods = [ 'wrap', 'unwrap', 'toggle', 'wrapOnce' ]; /* Methods */ /** * Check if the current selection is wrapped in a list of a given style * * @param {string|null} style List style, e.g. 'number' or 'bullet', or null for any style * @param {string} [listType='list'] List type * @return {boolean} Current selection is all wrapped in a list */ ve.ui.ListAction.prototype.allWrapped = function ( style, listType ) { listType = listType || 'list'; const attributes = style ? { style: style } : undefined; return this.surface.getModel().getFragment().hasMatchingAncestor( listType, attributes, true ); }; /** * Toggle a list around content. * * @param {string} style List style, e.g. 'number' or 'bullet' * @param {boolean} noBreakpoints Don't create breakpoints * @param {string} [listType='list'] List type * @return {boolean} Action was executed */ ve.ui.ListAction.prototype.toggle = function ( style, noBreakpoints, listType ) { Iif ( this.allWrapped( style, listType ) ) { return this.unwrap( noBreakpoints, listType ); } else { return this.wrap( style, noBreakpoints, listType ); } }; /** * Add a list around content only if it has no list already. * * @param {string} style List style, e.g. 'number' or 'bullet' * @param {boolean} noBreakpoints Don't create breakpoints * @param {string} [listType='list'] List type * @return {boolean} Action was executed */ ve.ui.ListAction.prototype.wrapOnce = function ( style, noBreakpoints, listType ) { // Check for a list of any style Eif ( !this.allWrapped( null, listType ) ) { return this.wrap( style, noBreakpoints, listType ); } return false; }; /** * Add a list around content. * * TODO: Refactor functionality into {ve.dm.SurfaceFragment}. * * @param {string} style List style, e.g. 'number' or 'bullet' * @param {boolean} noBreakpoints Don't create breakpoints * @param {string} [listType='list'] List type * @return {boolean} Action was executed */ ve.ui.ListAction.prototype.wrap = function ( style, noBreakpoints, listType ) { const surfaceModel = this.surface.getModel(), selection = surfaceModel.getSelection(); Iif ( !( selection instanceof ve.dm.LinearSelection ) ) { return false; } listType = listType || 'list'; if ( !noBreakpoints ) { surfaceModel.breakpoint(); } const documentModel = surfaceModel.getDocument(); let range = selection.getRange(); // TODO: Would be good to refactor at some point and avoid/abstract path split for block slug // and not block slug. Iif ( range.isCollapsed() && !documentModel.data.isContentOffset( range.to ) && documentModel.hasSlugAtOffset( range.to ) ) { // Inside block level slug const fragment = surfaceModel.getFragment( null, true ) .insertContent( [ { type: 'paragraph' }, { type: '/paragraph' } ] ) .collapseToStart() .adjustLinearSelection( 1, 1 ) .select(); range = fragment.getSelection().getRange(); } let previousList; const groups = documentModel.getCoveredSiblingGroups( range ); for ( let i = 0; i < groups.length; i++ ) { const group = groups[ i ]; // TODO: Allow conversion between different list types if ( group.grandparent && group.grandparent.getType() === listType ) { Eif ( group.grandparent !== previousList ) { surfaceModel.getLinearFragment( group.grandparent.getOuterRange(), true ) // Change the list style .changeAttributes( { style: style } ); previousList = group.grandparent; } } else { // Get a range that covers the whole group const groupRange = new ve.Range( group.nodes[ 0 ].getOuterRange().start, group.nodes[ group.nodes.length - 1 ].getOuterRange().end ); const element = { type: listType }; Eif ( style ) { element.attributes = { style: style }; } const itemElement = ve.dm.modelRegistry.lookup( listType ).static.createItem(); surfaceModel.getLinearFragment( groupRange, true ) // Convert everything to paragraphs first .convertNodes( 'paragraph', null, { generated: 'wrapper' } ) // Wrap everything in a list and each content branch in a listItem .wrapAllNodes( element, itemElement ); } } if ( !noBreakpoints ) { surfaceModel.breakpoint(); } return true; }; /** * Remove list around content. * * TODO: Refactor functionality into {ve.dm.SurfaceFragment}. * * @param {boolean} noBreakpoints Don't create breakpoints * @param {string} [listType='list'] List type * @return {boolean} Action was executed */ ve.ui.ListAction.prototype.unwrap = function ( noBreakpoints, listType ) { const surfaceModel = this.surface.getModel(); Iif ( !( surfaceModel.getSelection() instanceof ve.dm.LinearSelection ) ) { return false; } Eif ( !noBreakpoints ) { surfaceModel.breakpoint(); } const indentationAction = ve.ui.actionFactory.create( 'indentation', this.surface ); const documentModel = surfaceModel.getDocument(); listType = listType || 'list'; let node; do { node = documentModel.getBranchNodeFromOffset( surfaceModel.getSelection().getRange().start ); } while ( node.hasMatchingAncestor( listType ) && indentationAction.decrease() ); Eif ( !noBreakpoints ) { surfaceModel.breakpoint(); } return true; }; /* Registration */ ve.ui.actionFactory.register( ve.ui.ListAction ); |