Файловый менеджер - Редактировать - /var/www/html/mediawiki-1.43.1/extensions/VisualEditor/lib/ve/src/ui/actions/ve.ui.IndentationAction.js
Ðазад
/*! * VisualEditor UserInterface IndentationAction class. * * @copyright See AUTHORS.txt */ /** * Indentation action. * * @class * @extends ve.ui.Action * * @constructor * @param {ve.ui.Surface} surface Surface to act on * @param {string} [source] */ ve.ui.IndentationAction = function VeUiIndentationAction() { // Parent constructor ve.ui.IndentationAction.super.apply( this, arguments ); }; /* Inheritance */ OO.inheritClass( ve.ui.IndentationAction, ve.ui.Action ); /* Static Properties */ ve.ui.IndentationAction.static.name = 'indentation'; ve.ui.IndentationAction.static.methods = [ 'increase', 'decrease' ]; /* Methods */ /** * Indent content. * * @return {boolean} Indentation increase occurred */ ve.ui.IndentationAction.prototype.increase = function () { return this.changeIndentation( 1 ); }; /** * Unindent content. * * @return {boolean} Indentation decrease occurred */ ve.ui.IndentationAction.prototype.decrease = function () { return this.changeIndentation( -1 ); }; /** * Change indentation of content. * * @param {number} indent Indentation change, 1 or -1 * @return {boolean} Indentation decrease occurred */ ve.ui.IndentationAction.prototype.changeIndentation = function ( indent ) { const surfaceModel = this.surface.getModel(), selection = surfaceModel.getSelection(); if ( !( selection instanceof ve.dm.LinearSelection ) ) { return false; } const documentModel = surfaceModel.getDocument(); const groups = documentModel.getCoveredSiblingGroups( selection.getRange() ); const fragments = []; let changed = false; // Build fragments from groups (we need their ranges since the nodes will be rebuilt on change) groups.forEach( ( group ) => { if ( group.grandparent && group.grandparent.getType() === 'list' ) { fragments.push( surfaceModel.getLinearFragment( group.parent.getRange(), true ) ); changed = true; } else if ( group.parent && group.parent.getType() === 'list' ) { // In a slug, the node will be the listItem. fragments.push( surfaceModel.getLinearFragment( group.nodes[ 0 ].getRange(), true ) ); changed = true; } } ); // Process each fragment (their ranges are automatically adjusted on change) fragments.forEach( ( fragment ) => { const listItem = documentModel.getBranchNodeFromOffset( fragment.getSelection().getRange().start ); if ( indent > 0 ) { this.indentListItem( listItem ); } else { this.unindentListItem( listItem ); } } ); return changed; }; /** * Indent a list item. * * @param {ve.dm.ListItemNode} listItem List item to indent * @throws {Error} listItem must be a ve.dm.ListItemNode */ ve.ui.IndentationAction.prototype.indentListItem = function ( listItem ) { // This check should never fail /* istanbul ignore next */ if ( !( listItem instanceof ve.dm.ListItemNode ) ) { throw new Error( 'listItem must be a ve.dm.ListItemNode' ); } /* * Indenting a list item is done as follows: * * 1. Wrap the listItem in a list and a listItem (<li> --> <li><ul><li>) * 2. Merge this wrapped listItem into the previous listItem if present * (<li>Previous</li><li><ul><li>This --> <li>Previous<ul><li>This) * 3. If this results in the wrapped list being preceded by another list, * merge those lists. */ const listType = listItem.getParent().getAttribute( 'style' ); const listItemRange = listItem.getOuterRange(); // CAREFUL: after initializing the variables above, we cannot use the model tree! // The first transaction will cause rebuilds so the nodes we have references to now // will be detached and useless after the first transaction. Instead, inspect // documentModel.data to find out things about the current structure. const surfaceModel = this.surface.getModel(); // (1) Wrap the listItem in a list and a listItem surfaceModel.getLinearFragment( listItemRange, true ) .wrapNodes( [ { type: 'listItem' }, { type: 'list', attributes: { style: listType } } ] ); const documentModel = surfaceModel.getDocument(); // (2) Merge the listItem into the previous listItem (if there is one) if ( documentModel.data.getData( listItemRange.start ).type === 'listItem' && documentModel.data.getData( listItemRange.start - 1 ).type === '/listItem' ) { let mergeStart = listItemRange.start - 1; let mergeEnd = listItemRange.start + 1; // (3) If this results in adjacent lists, merge those too if ( documentModel.data.getData( mergeEnd ).type === 'list' && documentModel.data.getData( mergeStart - 1 ).type === '/list' ) { mergeStart--; mergeEnd++; } surfaceModel.getLinearFragment( new ve.Range( mergeStart, mergeEnd ), true ).removeContent(); } // TODO If this listItem has a child list, split&unwrap it }; /** * Unindent a list item. * * TODO: Refactor functionality into {ve.dm.SurfaceFragment}. * * @param {ve.dm.ListItemNode} listItem List item to unindent * @throws {Error} listItem must be a ve.dm.ListItemNode */ ve.ui.IndentationAction.prototype.unindentListItem = function ( listItem ) { // This check should never fail /* istanbul ignore next */ if ( !( listItem instanceof ve.dm.ListItemNode ) ) { throw new Error( 'listItem must be a ve.dm.ListItemNode' ); } let tx; const surfaceModel = this.surface.getModel(); const documentModel = surfaceModel.getDocument(); const fragment = surfaceModel.getLinearFragment( listItem.getOuterRange(), true ); const list = listItem.getParent(); const listElement = list.getClonedElement(); const grandParentType = list.getParent().getType(); let listItemRange = listItem.getOuterRange(); /* * Outdenting a list item is done as follows: * 1. Split the parent list to isolate the listItem in its own list * 1a. Split the list before the listItem if it's not the first child * 1b. Split the list after the listItem if it's not the last child * 2. If this isolated list's parent is not a listItem, unwrap the listItem and the isolated list, and stop. * 3. Split the parent listItem to isolate the list in its own listItem * 3a. Split the listItem before the list if it's not the first child * 3b. Split the listItem after the list if it's not the last child * 4. Unwrap the now-isolated listItem and the isolated list */ // TODO: Child list handling, gotta figure that out. // CAREFUL: after initializing the variables above, we cannot use the model tree! // The first transaction will cause rebuilds so the nodes we have references to now // will be detached and useless after the first transaction. Instead, inspect // documentModel.data to find out things about the current structure. // (1) Split the listItem into a separate list if ( documentModel.data.getData( listItemRange.start - 1 ).type !== 'list' ) { // (1a) listItem is not the first child, split the list before listItem tx = ve.dm.TransactionBuilder.static.newFromInsertion( documentModel, listItemRange.start, [ { type: '/list' }, listElement ] ); surfaceModel.change( tx ); // tx.translateRange( listItemRange ) doesn't do what we want listItemRange = listItemRange.translate( 2 ); } if ( documentModel.data.getData( listItemRange.end ).type !== '/list' ) { // (1b) listItem is not the last child, split the list after listItem tx = ve.dm.TransactionBuilder.static.newFromInsertion( documentModel, listItemRange.end, [ { type: '/list' }, listElement ] ); surfaceModel.change( tx ); // listItemRange is not affected by this transaction } let splitListRange = new ve.Range( listItemRange.start - 1, listItemRange.end + 1 ); if ( grandParentType !== 'listItem' ) { // The user is trying to unindent a list item that's not nested // (2) Unwrap both the list and the listItem, dumping the listItem's contents // into the list's parent surfaceModel.getLinearFragment( new ve.Range( listItemRange.start + 1, listItemRange.end - 1 ), true ) .unwrapNodes( 2 ); // Ensure paragraphs are not generated paragraphs now that they are not in a list const children = fragment.getSiblingNodes(); for ( let i = 0, length = children.length; i < length; i++ ) { const child = children[ i ].node; if ( child.type === 'paragraph' && ve.getProp( child.element, 'internal', 'generated' ) ) { surfaceModel.getLinearFragment( child.getOuterRange(), true ).convertNodes( 'paragraph', child.getAttributes(), {} ); } } } else { // (3) Split the list away from parentListItem into its own listItem // TODO factor common split logic somehow? if ( documentModel.data.getData( splitListRange.start - 1 ).type !== 'listItem' ) { // (3a) Split parentListItem before list tx = ve.dm.TransactionBuilder.static.newFromInsertion( documentModel, splitListRange.start, [ { type: '/listItem' }, { type: 'listItem' } ] ); surfaceModel.change( tx ); // tx.translateRange( splitListRange ) doesn't do what we want splitListRange = splitListRange.translate( 2 ); } if ( documentModel.data.getData( splitListRange.end ).type !== '/listItem' ) { // (3b) Split parentListItem after list tx = ve.dm.TransactionBuilder.static.newFromInsertion( documentModel, splitListRange.end, [ { type: '/listItem' }, { type: 'listItem' } ] ); surfaceModel.change( tx ); // splitListRange is not affected by this transaction } // (4) Unwrap the list and its containing listItem surfaceModel.getLinearFragment( new ve.Range( splitListRange.start + 1, splitListRange.end - 1 ), true ) .unwrapNodes( 2 ); } }; /* Registration */ ve.ui.actionFactory.register( ve.ui.IndentationAction );
| ver. 1.1 | |
.
| PHP 8.4.18 | Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñтраницы: 0 |
proxy
|
phpinfo
|
ÐаÑтройка