@ckeditor/ckeditor5-code-block 35.4.0 → 36.0.1

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/src/utils.js CHANGED
@@ -1,14 +1,8 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
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/utils
8
- */
9
-
10
5
  import { first } from 'ckeditor5/src/utils';
11
-
12
6
  /**
13
7
  * Returns code block languages as defined in `config.codeBlock.languages` but processed:
14
8
  *
@@ -17,220 +11,197 @@ import { first } from 'ckeditor5/src/utils';
17
11
  * configuration is defined because the editor does not exist yet.
18
12
  * * To make sure each definition has a CSS class associated with it even if not specified
19
13
  * in the original configuration.
20
- *
21
- * @param {module:core/editor/editor~Editor} editor
22
- * @returns {Array.<module:code-block/codeblock~CodeBlockLanguageDefinition>}.
23
14
  */
24
- export function getNormalizedAndLocalizedLanguageDefinitions( editor ) {
25
- const t = editor.t;
26
- const languageDefs = editor.config.get( 'codeBlock.languages' );
27
-
28
- for ( const def of languageDefs ) {
29
- if ( def.label === 'Plain text' ) {
30
- def.label = t( 'Plain text' );
31
- }
32
-
33
- if ( def.class === undefined ) {
34
- def.class = `language-${ def.language }`;
35
- }
36
- }
37
-
38
- return languageDefs;
15
+ export function getNormalizedAndLocalizedLanguageDefinitions(editor) {
16
+ const t = editor.t;
17
+ const languageDefs = editor.config.get('codeBlock.languages');
18
+ for (const def of languageDefs) {
19
+ if (def.label === 'Plain text') {
20
+ def.label = t('Plain text');
21
+ }
22
+ if (def.class === undefined) {
23
+ def.class = `language-${def.language}`;
24
+ }
25
+ }
26
+ return languageDefs;
39
27
  }
40
-
41
28
  /**
42
29
  * Returns an object associating certain language definition properties with others. For instance:
43
30
  *
44
31
  * For:
45
32
  *
46
- * const definitions = {
47
- * { language: 'php', class: 'language-php', label: 'PHP' },
48
- * { language: 'javascript', class: 'js', label: 'JavaScript' },
49
- * };
33
+ * const definitions = {
34
+ * { language: 'php', class: 'language-php', label: 'PHP' },
35
+ * { language: 'javascript', class: 'js', label: 'JavaScript' },
36
+ * };
50
37
  *
51
- * getPropertyAssociation( definitions, 'class', 'language' );
38
+ * getPropertyAssociation( definitions, 'class', 'language' );
52
39
  *
53
40
  * returns:
54
41
  *
55
- * {
56
- * 'language-php': 'php'
57
- * 'js': 'javascript'
58
- * }
42
+ * ```ts
43
+ * {
44
+ * 'language-php': 'php',
45
+ * 'js': 'javascript'
46
+ * }
47
+ * ```
59
48
  *
60
49
  * and
61
50
  *
62
- * getPropertyAssociation( definitions, 'language', 'label' );
51
+ * ```ts
52
+ * getPropertyAssociation( definitions, 'language', 'label' );
53
+ * ```
63
54
  *
64
55
  * returns:
65
56
  *
66
- * {
67
- * 'php': 'PHP'
68
- * 'javascript': 'JavaScript'
69
- * }
70
- *
71
- * @param {Array.<module:code-block/codeblock~CodeBlockLanguageDefinition>}
72
- * @param {String} key
73
- * @param {String} value
74
- * @param {Object.<String,String>}
57
+ * ```ts
58
+ * {
59
+ * 'php': 'PHP',
60
+ * 'javascript': 'JavaScript'
61
+ * }
62
+ * ```
75
63
  */
76
- export function getPropertyAssociation( languageDefs, key, value ) {
77
- const association = {};
78
-
79
- for ( const def of languageDefs ) {
80
- if ( key === 'class' ) {
81
- // Only the first class is considered.
82
- association[ def[ key ].split( ' ' ).shift() ] = def[ value ];
83
- } else {
84
- association[ def[ key ] ] = def[ value ];
85
- }
86
- }
87
-
88
- return association;
64
+ export function getPropertyAssociation(languageDefs, key, value) {
65
+ const association = {};
66
+ for (const def of languageDefs) {
67
+ if (key === 'class') {
68
+ // Only the first class is considered.
69
+ const newKey = (def[key]).split(' ').shift();
70
+ association[newKey] = def[value];
71
+ }
72
+ else {
73
+ association[def[key]] = def[value];
74
+ }
75
+ }
76
+ return association;
89
77
  }
90
-
91
78
  /**
92
79
  * For a given model text node, it returns white spaces that precede other characters in that node.
93
80
  * This corresponds to the indentation part of the code block line.
94
- *
95
- * @param {module:engine/model/text~Text} codeLineNodes
96
- * @returns {String}
97
81
  */
98
- export function getLeadingWhiteSpaces( textNode ) {
99
- return textNode.data.match( /^(\s*)/ )[ 0 ];
82
+ export function getLeadingWhiteSpaces(textNode) {
83
+ return textNode.data.match(/^(\s*)/)[0];
100
84
  }
101
-
102
85
  /**
103
86
  * For plain text containing the code (a snippet), it returns a document fragment containing
104
87
  * view text nodes separated by `<br>` elements (in place of new line characters "\n"), for instance:
105
88
  *
106
89
  * Input:
107
90
  *
108
- * "foo()\n
109
- * bar()"
91
+ * ```ts
92
+ * "foo()\n
93
+ * bar()"
94
+ * ```
110
95
  *
111
96
  * Output:
112
97
  *
113
- * <DocumentFragment>
114
- * "foo()"
115
- * <br/>
116
- * "bar()"
117
- * </DocumentFragment>
98
+ * ```html
99
+ * <DocumentFragment>
100
+ * "foo()"
101
+ * <br/>
102
+ * "bar()"
103
+ * </DocumentFragment>
104
+ * ```
118
105
  *
119
- * @param {module:engine/view/upcastwriter~UpcastWriter} writer
120
- * @param {String} text The raw code text to be converted.
121
- * @returns {module:engine/view/documentfragment~DocumentFragment}
106
+ * @param text The raw code text to be converted.
122
107
  */
123
- export function rawSnippetTextToViewDocumentFragment( writer, text ) {
124
- const fragment = writer.createDocumentFragment();
125
- const textLines = text.split( '\n' );
126
-
127
- const nodes = textLines.reduce( ( nodes, line, lineIndex ) => {
128
- nodes.push( line );
129
-
130
- if ( lineIndex < textLines.length - 1 ) {
131
- nodes.push( writer.createElement( 'br' ) );
132
- }
133
-
134
- return nodes;
135
- }, [] );
136
-
137
- writer.appendChild( nodes, fragment );
138
-
139
- return fragment;
108
+ export function rawSnippetTextToViewDocumentFragment(writer, text) {
109
+ const fragment = writer.createDocumentFragment();
110
+ const textLines = text.split('\n');
111
+ const items = textLines.reduce((nodes, line, lineIndex) => {
112
+ nodes.push(line);
113
+ if (lineIndex < textLines.length - 1) {
114
+ nodes.push(writer.createElement('br'));
115
+ }
116
+ return nodes;
117
+ }, []);
118
+ writer.appendChild(items, fragment);
119
+ return fragment;
140
120
  }
141
-
142
121
  /**
143
122
  * Returns an array of all model positions within the selection that represent code block lines.
144
123
  *
145
124
  * If the selection is collapsed, it returns the exact selection anchor position:
146
125
  *
147
- * <codeBlock>[]foo</codeBlock> -> <codeBlock>^foo</codeBlock>
148
- * <codeBlock>foo[]bar</codeBlock> -> <codeBlock>foo^bar</codeBlock>
126
+ * ```html
127
+ * <codeBlock>[]foo</codeBlock> -> <codeBlock>^foo</codeBlock>
128
+ * <codeBlock>foo[]bar</codeBlock> -> <codeBlock>foo^bar</codeBlock>
129
+ * ```
149
130
  *
150
131
  * Otherwise, it returns positions **before** each text node belonging to all code blocks contained by the selection:
151
132
  *
152
- * <codeBlock> <codeBlock>
153
- * foo[bar ^foobar
154
- * <softBreak></softBreak> -> <softBreak></softBreak>
155
- * baz]qux ^bazqux
156
- * </codeBlock> </codeBlock>
133
+ * ```html
134
+ * <codeBlock> <codeBlock>
135
+ * foo[bar ^foobar
136
+ * <softBreak></softBreak> -> <softBreak></softBreak>
137
+ * baz]qux ^bazqux
138
+ * </codeBlock> </codeBlock>
139
+ * ```
157
140
  *
158
141
  * It also works across other non–code blocks:
159
142
  *
160
- * <codeBlock> <codeBlock>
161
- * foo[bar ^foobar
162
- * </codeBlock> </codeBlock>
163
- * <paragraph>text</paragraph> -> <paragraph>text</paragraph>
164
- * <codeBlock> <codeBlock>
165
- * baz]qux ^bazqux
166
- * </codeBlock> </codeBlock>
143
+ * ```html
144
+ * <codeBlock> <codeBlock>
145
+ * foo[bar ^foobar
146
+ * </codeBlock> </codeBlock>
147
+ * <paragraph>text</paragraph> -> <paragraph>text</paragraph>
148
+ * <codeBlock> <codeBlock>
149
+ * baz]qux ^bazqux
150
+ * </codeBlock> </codeBlock>
151
+ * ```
167
152
  *
168
153
  * **Note:** The positions are in reverse order so they do not get outdated when iterating over them and
169
154
  * the writer inserts or removes elements at the same time.
170
155
  *
171
156
  * **Note:** The position is located after the leading white spaces in the text node.
172
- *
173
- * @param {module:engine/model/model~Model} model
174
- * @returns {Array.<module:engine/model/position~Position>}
175
157
  */
176
- export function getIndentOutdentPositions( model ) {
177
- const selection = model.document.selection;
178
- const positions = [];
179
-
180
- // When the selection is collapsed, there's only one position we can indent or outdent.
181
- if ( selection.isCollapsed ) {
182
- positions.push( selection.anchor );
183
- }
184
-
185
- // When the selection is NOT collapsed, collect all positions starting before text nodes
186
- // (code lines) in any <codeBlock> within the selection.
187
- else {
188
- // Walk backward so positions we are about to collect here do not get outdated when
189
- // inserting or deleting using the writer.
190
- const walker = selection.getFirstRange().getWalker( {
191
- ignoreElementEnd: true,
192
- direction: 'backward'
193
- } );
194
-
195
- for ( const { item } of walker ) {
196
- if ( item.is( '$textProxy' ) && item.parent.is( 'element', 'codeBlock' ) ) {
197
- const leadingWhiteSpaces = getLeadingWhiteSpaces( item.textNode );
198
- const { parent, startOffset } = item.textNode;
199
-
200
- // Make sure the position is after all leading whitespaces in the text node.
201
- const position = model.createPositionAt( parent, startOffset + leadingWhiteSpaces.length );
202
-
203
- positions.push( position );
204
- }
205
- }
206
- }
207
-
208
- return positions;
158
+ export function getIndentOutdentPositions(model) {
159
+ const selection = model.document.selection;
160
+ const positions = [];
161
+ // When the selection is collapsed, there's only one position we can indent or outdent.
162
+ if (selection.isCollapsed) {
163
+ return [selection.anchor];
164
+ }
165
+ // When the selection is NOT collapsed, collect all positions starting before text nodes
166
+ // (code lines) in any <codeBlock> within the selection.
167
+ // Walk backward so positions we are about to collect here do not get outdated when
168
+ // inserting or deleting using the writer.
169
+ const walker = selection.getFirstRange().getWalker({
170
+ ignoreElementEnd: true,
171
+ direction: 'backward'
172
+ });
173
+ for (const { item } of walker) {
174
+ if (!item.is('$textProxy')) {
175
+ continue;
176
+ }
177
+ const { parent, startOffset } = item.textNode;
178
+ if (!parent.is('element', 'codeBlock')) {
179
+ continue;
180
+ }
181
+ const leadingWhiteSpaces = getLeadingWhiteSpaces(item.textNode);
182
+ // Make sure the position is after all leading whitespaces in the text node.
183
+ const position = model.createPositionAt(parent, startOffset + leadingWhiteSpaces.length);
184
+ positions.push(position);
185
+ }
186
+ return positions;
209
187
  }
210
-
211
188
  /**
212
189
  * Checks if any of the blocks within the model selection is a code block.
213
- *
214
- * @param {module:engine/model/selection~Selection} selection
215
- * @returns {Boolean}
216
190
  */
217
- export function isModelSelectionInCodeBlock( selection ) {
218
- const firstBlock = first( selection.getSelectedBlocks() );
219
-
220
- return firstBlock && firstBlock.is( 'element', 'codeBlock' );
191
+ export function isModelSelectionInCodeBlock(selection) {
192
+ const firstBlock = first(selection.getSelectedBlocks());
193
+ return !!firstBlock && firstBlock.is('element', 'codeBlock');
221
194
  }
222
-
223
195
  /**
224
196
  * Checks if an {@link module:engine/model/element~Element Element} can become a code block.
225
197
  *
226
- * @param {module:engine/model/schema~Schema} schema Model's schema.
227
- * @param {module:engine/model/element~Element} element The element to be checked.
228
- * @returns {Boolean} Check result.
198
+ * @param schema Model's schema.
199
+ * @param element The element to be checked.
200
+ * @returns Check result.
229
201
  */
230
- export function canBeCodeBlock( schema, element ) {
231
- if ( element.is( 'rootElement' ) || schema.isLimit( element ) ) {
232
- return false;
233
- }
234
-
235
- return schema.checkChild( element.parent, 'codeBlock' );
202
+ export function canBeCodeBlock(schema, element) {
203
+ if (element.is('rootElement') || schema.isLimit(element)) {
204
+ return false;
205
+ }
206
+ return schema.checkChild(element.parent, 'codeBlock');
236
207
  }
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
2
+ * 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
5