/
indentblockcommand.js
122 lines (103 loc) · 3.29 KB
/
indentblockcommand.js
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
/**
* @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
*/
/**
* @module indent/indentblockcommand
*/
import Command from '@ckeditor/ckeditor5-core/src/command';
import first from '@ckeditor/ckeditor5-utils/src/first';
/**
* The indent block command.
*
* The command is registered by the {@link module:indent/indentblock~IndentBlock} as `'indentBlock'` for indenting blocks and
* `'outdentBlock'` for outdenting blocks.
*
* To increase block indentation at the current selection, execute the command:
*
* editor.execute( 'indentBlock' );
*
* To decrease block indentation at the current selection, execute the command:
*
* editor.execute( 'outdentBlock' );
*
* @extends module:core/command~Command
*/
export default class IndentBlockCommand extends Command {
/**
* Creates an instance of the command.
*
* @param {module:core/editor/editor~Editor} editor The editor instance.
* @param {module:indent/indentblockcommand~IndentBehavior} indentBehavior
*/
constructor( editor, indentBehavior ) {
super( editor );
/**
* The command's indentation behavior.
*
* @type {module:indent/indentblockcommand~IndentBehavior}
* @private
*/
this._indentBehavior = indentBehavior;
}
/**
* @inheritDoc
*/
refresh() {
// Check whether any of the position's ancestors is a list item.
const editor = this.editor;
const model = editor.model;
const block = first( model.document.selection.getSelectedBlocks() );
if ( !block || !model.schema.checkAttribute( block, 'blockIndent' ) ) {
this.isEnabled = false;
return;
}
this.isEnabled = this._indentBehavior.checkEnabled( block.getAttribute( 'blockIndent' ) );
}
/**
* @inheritDoc
*/
execute() {
const model = this.editor.model;
const blocksToChange = getBlocksToChange( model );
model.change( writer => {
for ( const block of blocksToChange ) {
const currentIndent = block.getAttribute( 'blockIndent' );
const nextIndent = this._indentBehavior.getNextIndent( currentIndent );
if ( nextIndent ) {
writer.setAttribute( 'blockIndent', nextIndent, block );
} else {
writer.removeAttribute( 'blockIndent', block );
}
}
} );
}
}
// Returns blocks from selection that should have blockIndent selection set.
//
// @param {module:engine/model/model~model} model A model.
function getBlocksToChange( model ) {
const selection = model.document.selection;
const schema = model.schema;
const blocksInSelection = Array.from( selection.getSelectedBlocks() );
return blocksInSelection.filter( block => schema.checkAttribute( block, 'blockIndent' ) );
}
/**
* Provides indentation behavior to {@link module:indent/indentblockcommand~IndentBlockCommand}.
*
* @interface module:indent/indentblockcommand~IndentBehavior
*/
/**
* Checks if the command should be enabled.
*
* @method #checkEnabled
* @param {String} indentAttributeValue The current indent attribute value.
* @returns {Boolean}
*/
/**
* Returns a new indent attribute value based on the current indent. This method returns `undefined` when the indentation should be removed.
*
* @method #getNextIndent
* @param {String} indentAttributeValue The current indent attribute value.
* @returns {String|undefined}
*/