@ckeditor/ckeditor5-code-block 35.3.2 → 36.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +1 -1
- package/build/code-block.js +2 -2
- package/build/translations/ug.js +1 -1
- package/lang/translations/ug.po +1 -1
- package/package.json +26 -22
- package/src/codeblock.js +13 -151
- package/src/codeblockcommand.js +126 -191
- package/src/codeblockediting.js +358 -445
- package/src/codeblockui.js +69 -96
- package/src/converters.js +206 -240
- package/src/indentcodeblockcommand.js +66 -93
- package/src/index.js +1 -3
- package/src/outdentcodeblockcommand.js +121 -165
- package/src/utils.js +132 -161
- package/theme/codeblock.css +1 -1
- package/build/code-block.js.map +0 -1
|
@@ -1,105 +1,78 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
5
|
/**
|
|
7
6
|
* @module code-block/indentcodeblockcommand
|
|
8
7
|
*/
|
|
9
|
-
|
|
10
8
|
import { Command } from 'ckeditor5/src/core';
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
getIndentOutdentPositions,
|
|
14
|
-
isModelSelectionInCodeBlock
|
|
15
|
-
} from './utils';
|
|
16
|
-
|
|
9
|
+
import { getIndentOutdentPositions, isModelSelectionInCodeBlock } from './utils';
|
|
17
10
|
/**
|
|
18
11
|
* The code block indentation increase command plugin.
|
|
19
|
-
*
|
|
20
|
-
* @extends module:core/command~Command
|
|
21
12
|
*/
|
|
22
13
|
export default class IndentCodeBlockCommand extends Command {
|
|
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
|
-
* Checks whether the command can be enabled in the current context.
|
|
92
|
-
*
|
|
93
|
-
* @private
|
|
94
|
-
* @returns {Boolean} Whether the command should be enabled.
|
|
95
|
-
*/
|
|
96
|
-
_checkEnabled() {
|
|
97
|
-
if ( !this._indentSequence ) {
|
|
98
|
-
return false;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Indent (forward) command is always enabled when there's any code block in the selection
|
|
102
|
-
// because you can always indent code lines.
|
|
103
|
-
return isModelSelectionInCodeBlock( this.editor.model.document.selection );
|
|
104
|
-
}
|
|
14
|
+
constructor(editor) {
|
|
15
|
+
super(editor);
|
|
16
|
+
this._indentSequence = editor.config.get('codeBlock.indentSequence');
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* @inheritDoc
|
|
20
|
+
*/
|
|
21
|
+
refresh() {
|
|
22
|
+
this.isEnabled = this._checkEnabled();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Executes the command. When the command {@link #isEnabled is enabled}, the indentation of the
|
|
26
|
+
* code lines in the selection will be increased.
|
|
27
|
+
*
|
|
28
|
+
* @fires execute
|
|
29
|
+
*/
|
|
30
|
+
execute() {
|
|
31
|
+
const editor = this.editor;
|
|
32
|
+
const model = editor.model;
|
|
33
|
+
model.change(writer => {
|
|
34
|
+
const positions = getIndentOutdentPositions(model);
|
|
35
|
+
// Indent all positions, for instance assuming the indent sequence is 4x space (" "):
|
|
36
|
+
//
|
|
37
|
+
// <codeBlock>^foo</codeBlock> -> <codeBlock> foo</codeBlock>
|
|
38
|
+
//
|
|
39
|
+
// <codeBlock>foo^bar</codeBlock> -> <codeBlock>foo bar</codeBlock>
|
|
40
|
+
//
|
|
41
|
+
// Also, when there is more than one position:
|
|
42
|
+
//
|
|
43
|
+
// <codeBlock>
|
|
44
|
+
// ^foobar
|
|
45
|
+
// <softBreak></softBreak>
|
|
46
|
+
// ^bazqux
|
|
47
|
+
// </codeBlock>
|
|
48
|
+
//
|
|
49
|
+
// ->
|
|
50
|
+
//
|
|
51
|
+
// <codeBlock>
|
|
52
|
+
// foobar
|
|
53
|
+
// <softBreak></softBreak>
|
|
54
|
+
// bazqux
|
|
55
|
+
// </codeBlock>
|
|
56
|
+
//
|
|
57
|
+
for (const position of positions) {
|
|
58
|
+
const indentSequenceTextElement = writer.createText(this._indentSequence);
|
|
59
|
+
// Previously insertion was done by writer.insertText(). It was changed to insertContent() to enable
|
|
60
|
+
// integration of code block with track changes. It's the easiest way of integration because insertContent()
|
|
61
|
+
// is already integrated with track changes, but if it ever cause any troubles it can be reverted, however
|
|
62
|
+
// some additional work will be required in track changes integration of code block.
|
|
63
|
+
model.insertContent(indentSequenceTextElement, position);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Checks whether the command can be enabled in the current context.
|
|
69
|
+
*/
|
|
70
|
+
_checkEnabled() {
|
|
71
|
+
if (!this._indentSequence) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
// Indent (forward) command is always enabled when there's any code block in the selection
|
|
75
|
+
// because you can always indent code lines.
|
|
76
|
+
return isModelSelectionInCodeBlock(this.editor.model.document.selection);
|
|
77
|
+
}
|
|
105
78
|
}
|
package/src/index.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
5
|
/**
|
|
7
6
|
* @module code-block
|
|
8
7
|
*/
|
|
9
|
-
|
|
10
8
|
export { default as CodeBlock } from './codeblock';
|
|
11
9
|
export { default as CodeBlockEditing } from './codeblockediting';
|
|
12
10
|
export { default as CodeBlockUI } from './codeblockui';
|
|
@@ -1,119 +1,88 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* @module code-block/outdentcodeblockcommand
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
5
|
import { Command } from 'ckeditor5/src/core';
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
getLeadingWhiteSpaces,
|
|
14
|
-
getIndentOutdentPositions,
|
|
15
|
-
isModelSelectionInCodeBlock
|
|
16
|
-
} from './utils';
|
|
17
|
-
|
|
6
|
+
import { getLeadingWhiteSpaces, getIndentOutdentPositions, isModelSelectionInCodeBlock } from './utils';
|
|
18
7
|
/**
|
|
19
8
|
* The code block indentation decrease command plugin.
|
|
20
|
-
*
|
|
21
|
-
* @extends module:core/command~Command
|
|
22
9
|
*/
|
|
23
10
|
export default class OutdentCodeBlockCommand extends Command {
|
|
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
|
-
_checkEnabled() {
|
|
99
|
-
if ( !this._indentSequence ) {
|
|
100
|
-
return false;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const model = this.editor.model;
|
|
104
|
-
|
|
105
|
-
if ( !isModelSelectionInCodeBlock( model.document.selection ) ) {
|
|
106
|
-
return false;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Outdent command can execute only when there is an indent character sequence
|
|
110
|
-
// in some of the lines.
|
|
111
|
-
return getIndentOutdentPositions( model ).some( position => {
|
|
112
|
-
return getLastOutdentableSequenceRange( model, position, this._indentSequence );
|
|
113
|
-
} );
|
|
114
|
-
}
|
|
11
|
+
constructor(editor) {
|
|
12
|
+
super(editor);
|
|
13
|
+
this._indentSequence = editor.config.get('codeBlock.indentSequence');
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* @inheritDoc
|
|
17
|
+
*/
|
|
18
|
+
refresh() {
|
|
19
|
+
this.isEnabled = this._checkEnabled();
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Executes the command. When the command {@link #isEnabled is enabled}, the indentation of the
|
|
23
|
+
* code lines in the selection will be decreased.
|
|
24
|
+
*
|
|
25
|
+
* @fires execute
|
|
26
|
+
*/
|
|
27
|
+
execute() {
|
|
28
|
+
const editor = this.editor;
|
|
29
|
+
const model = editor.model;
|
|
30
|
+
model.change(() => {
|
|
31
|
+
const positions = getIndentOutdentPositions(model);
|
|
32
|
+
// Outdent all positions, for instance assuming the indent sequence is 4x space (" "):
|
|
33
|
+
//
|
|
34
|
+
// <codeBlock>^foo</codeBlock> -> <codeBlock>foo</codeBlock>
|
|
35
|
+
//
|
|
36
|
+
// <codeBlock> ^bar</codeBlock> -> <codeBlock>bar</codeBlock>
|
|
37
|
+
//
|
|
38
|
+
// Also, when there is more than one position:
|
|
39
|
+
//
|
|
40
|
+
// <codeBlock>
|
|
41
|
+
// ^foobar
|
|
42
|
+
// <softBreak></softBreak>
|
|
43
|
+
// ^bazqux
|
|
44
|
+
// </codeBlock>
|
|
45
|
+
//
|
|
46
|
+
// ->
|
|
47
|
+
//
|
|
48
|
+
// <codeBlock>
|
|
49
|
+
// foobar
|
|
50
|
+
// <softBreak></softBreak>
|
|
51
|
+
// bazqux
|
|
52
|
+
// </codeBlock>
|
|
53
|
+
for (const position of positions) {
|
|
54
|
+
const range = getLastOutdentableSequenceRange(model, position, this._indentSequence);
|
|
55
|
+
if (range) {
|
|
56
|
+
// Previously deletion was done by writer.remove(). It was changed to deleteContent() to enable
|
|
57
|
+
// integration of code block with track changes. It's the easiest way of integration because deleteContent()
|
|
58
|
+
// is already integrated with track changes, but if it ever cause any troubles it can be reverted, however
|
|
59
|
+
// some additional work will be required in track changes integration of code block.
|
|
60
|
+
model.deleteContent(model.createSelection(range));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Checks whether the command can be enabled in the current context.
|
|
67
|
+
*
|
|
68
|
+
* @private
|
|
69
|
+
* @returns {Boolean} Whether the command should be enabled.
|
|
70
|
+
*/
|
|
71
|
+
_checkEnabled() {
|
|
72
|
+
if (!this._indentSequence) {
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
const model = this.editor.model;
|
|
76
|
+
if (!isModelSelectionInCodeBlock(model.document.selection)) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
// Outdent command can execute only when there is an indent character sequence
|
|
80
|
+
// in some of the lines.
|
|
81
|
+
return getIndentOutdentPositions(model).some(position => {
|
|
82
|
+
return getLastOutdentableSequenceRange(model, position, this._indentSequence);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
115
85
|
}
|
|
116
|
-
|
|
117
86
|
// For a position coming from `getIndentOutdentPositions()`, it returns the range representing
|
|
118
87
|
// the last occurrence of the indent sequence among the leading whitespaces of the code line the
|
|
119
88
|
// position represents.
|
|
@@ -130,63 +99,50 @@ export default class OutdentCodeBlockCommand extends Command {
|
|
|
130
99
|
// @param {<module:engine/model/position~Position>} position
|
|
131
100
|
// @param {String} sequence
|
|
132
101
|
// @returns {<module:engine/model/range~Range>|null}
|
|
133
|
-
function getLastOutdentableSequenceRange(
|
|
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
|
-
// For instance, assuming the indent sequence is 4x space (" "):
|
|
166
|
-
//
|
|
167
|
-
// <codeBlock> ^foo</codeBlock> -> <codeBlock> [ ]foo</codeBlock>
|
|
168
|
-
//
|
|
169
|
-
return model.createRange(
|
|
170
|
-
model.createPositionAt( parent, startOffset + lastIndexOfSequence ),
|
|
171
|
-
model.createPositionAt( parent, startOffset + lastIndexOfSequence + sequence.length )
|
|
172
|
-
);
|
|
102
|
+
function getLastOutdentableSequenceRange(model, position, sequence) {
|
|
103
|
+
// Positions start before each text node (code line). Get the node corresponding to the position.
|
|
104
|
+
const nodeAtPosition = getCodeLineTextNodeAtPosition(position);
|
|
105
|
+
if (!nodeAtPosition) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
const leadingWhiteSpaces = getLeadingWhiteSpaces(nodeAtPosition);
|
|
109
|
+
const lastIndexOfSequence = leadingWhiteSpaces.lastIndexOf(sequence);
|
|
110
|
+
// For instance, assuming the indent sequence is 4x space (" "):
|
|
111
|
+
//
|
|
112
|
+
// <codeBlock> ^foo</codeBlock> -> null
|
|
113
|
+
//
|
|
114
|
+
if (lastIndexOfSequence + sequence.length !== leadingWhiteSpaces.length) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
// For instance, assuming the indent sequence is 4x space (" "):
|
|
118
|
+
//
|
|
119
|
+
// <codeBlock> ^foo</codeBlock> -> null
|
|
120
|
+
//
|
|
121
|
+
if (lastIndexOfSequence === -1) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
const { parent, startOffset } = nodeAtPosition;
|
|
125
|
+
// Create a range that contains the **last** indent sequence among the leading whitespaces
|
|
126
|
+
// of the line.
|
|
127
|
+
//
|
|
128
|
+
// For instance, assuming the indent sequence is 4x space (" "):
|
|
129
|
+
//
|
|
130
|
+
// <codeBlock> ^foo</codeBlock> -> <codeBlock> [ ]foo</codeBlock>
|
|
131
|
+
//
|
|
132
|
+
return model.createRange(model.createPositionAt(parent, startOffset + lastIndexOfSequence), model.createPositionAt(parent, startOffset + lastIndexOfSequence + sequence.length));
|
|
173
133
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
return null;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return nodeAtPosition;
|
|
134
|
+
function getCodeLineTextNodeAtPosition(position) {
|
|
135
|
+
// Positions start before each text node (code line). Get the node corresponding to the position.
|
|
136
|
+
let nodeAtPosition = position.parent.getChild(position.index);
|
|
137
|
+
// <codeBlock>foo^</codeBlock>
|
|
138
|
+
// <codeBlock>foo^<softBreak></softBreak>bar</codeBlock>
|
|
139
|
+
if (!nodeAtPosition || nodeAtPosition.is('element', 'softBreak')) {
|
|
140
|
+
nodeAtPosition = position.nodeBefore;
|
|
141
|
+
}
|
|
142
|
+
// <codeBlock>^</codeBlock>
|
|
143
|
+
// <codeBlock>foo^<softBreak></softBreak>bar</codeBlock>
|
|
144
|
+
if (!nodeAtPosition || nodeAtPosition.is('element', 'softBreak')) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
return nodeAtPosition;
|
|
192
148
|
}
|