@ckeditor/ckeditor5-list 31.1.0 → 34.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.
Files changed (166) hide show
  1. package/LICENSE.md +2 -2
  2. package/README.md +2 -1
  3. package/build/list.js +3 -3
  4. package/build/list.js.map +1 -0
  5. package/build/translations/ar.js +1 -1
  6. package/build/translations/ast.js +1 -1
  7. package/build/translations/az.js +1 -1
  8. package/build/translations/bg.js +1 -1
  9. package/build/translations/cs.js +1 -1
  10. package/build/translations/da.js +1 -1
  11. package/build/translations/de-ch.js +1 -1
  12. package/build/translations/de.js +1 -1
  13. package/build/translations/el.js +1 -1
  14. package/build/translations/en-au.js +1 -1
  15. package/build/translations/en-gb.js +1 -1
  16. package/build/translations/eo.js +1 -1
  17. package/build/translations/es.js +1 -1
  18. package/build/translations/et.js +1 -1
  19. package/build/translations/eu.js +1 -1
  20. package/build/translations/fa.js +1 -1
  21. package/build/translations/fi.js +1 -1
  22. package/build/translations/fr.js +1 -1
  23. package/build/translations/gl.js +1 -1
  24. package/build/translations/he.js +1 -1
  25. package/build/translations/hi.js +1 -1
  26. package/build/translations/hr.js +1 -1
  27. package/build/translations/hu.js +1 -1
  28. package/build/translations/id.js +1 -1
  29. package/build/translations/it.js +1 -1
  30. package/build/translations/ja.js +1 -1
  31. package/build/translations/jv.js +1 -0
  32. package/build/translations/km.js +1 -1
  33. package/build/translations/kn.js +1 -1
  34. package/build/translations/ko.js +1 -1
  35. package/build/translations/ku.js +1 -1
  36. package/build/translations/lt.js +1 -1
  37. package/build/translations/lv.js +1 -1
  38. package/build/translations/nb.js +1 -1
  39. package/build/translations/ne.js +1 -1
  40. package/build/translations/nl.js +1 -1
  41. package/build/translations/no.js +1 -1
  42. package/build/translations/pl.js +1 -1
  43. package/build/translations/pt-br.js +1 -1
  44. package/build/translations/pt.js +1 -1
  45. package/build/translations/ro.js +1 -1
  46. package/build/translations/ru.js +1 -1
  47. package/build/translations/si.js +1 -1
  48. package/build/translations/sk.js +1 -1
  49. package/build/translations/sq.js +1 -1
  50. package/build/translations/sr-latn.js +1 -1
  51. package/build/translations/sr.js +1 -1
  52. package/build/translations/sv.js +1 -1
  53. package/build/translations/tk.js +1 -1
  54. package/build/translations/tr.js +1 -1
  55. package/build/translations/ug.js +1 -1
  56. package/build/translations/uk.js +1 -1
  57. package/build/translations/uz.js +1 -1
  58. package/build/translations/vi.js +1 -1
  59. package/build/translations/zh-cn.js +1 -1
  60. package/build/translations/zh.js +1 -1
  61. package/ckeditor5-metadata.json +8 -4
  62. package/lang/contexts.json +5 -1
  63. package/lang/translations/ar.po +17 -1
  64. package/lang/translations/ast.po +17 -1
  65. package/lang/translations/az.po +17 -1
  66. package/lang/translations/bg.po +17 -1
  67. package/lang/translations/cs.po +17 -1
  68. package/lang/translations/da.po +17 -1
  69. package/lang/translations/de-ch.po +17 -1
  70. package/lang/translations/de.po +17 -1
  71. package/lang/translations/el.po +40 -24
  72. package/lang/translations/en-au.po +17 -1
  73. package/lang/translations/en-gb.po +17 -1
  74. package/lang/translations/en.po +17 -1
  75. package/lang/translations/eo.po +17 -1
  76. package/lang/translations/es.po +35 -19
  77. package/lang/translations/et.po +17 -1
  78. package/lang/translations/eu.po +17 -1
  79. package/lang/translations/fa.po +17 -1
  80. package/lang/translations/fi.po +17 -1
  81. package/lang/translations/fr.po +17 -1
  82. package/lang/translations/gl.po +17 -1
  83. package/lang/translations/he.po +17 -1
  84. package/lang/translations/hi.po +17 -1
  85. package/lang/translations/hr.po +17 -1
  86. package/lang/translations/hu.po +17 -1
  87. package/lang/translations/id.po +17 -1
  88. package/lang/translations/it.po +17 -1
  89. package/lang/translations/ja.po +17 -1
  90. package/lang/translations/jv.po +125 -0
  91. package/lang/translations/km.po +17 -1
  92. package/lang/translations/kn.po +17 -1
  93. package/lang/translations/ko.po +17 -1
  94. package/lang/translations/ku.po +17 -1
  95. package/lang/translations/lt.po +17 -1
  96. package/lang/translations/lv.po +17 -1
  97. package/lang/translations/nb.po +17 -1
  98. package/lang/translations/ne.po +17 -1
  99. package/lang/translations/nl.po +17 -1
  100. package/lang/translations/no.po +17 -1
  101. package/lang/translations/pl.po +17 -1
  102. package/lang/translations/pt-br.po +17 -1
  103. package/lang/translations/pt.po +17 -1
  104. package/lang/translations/ro.po +17 -1
  105. package/lang/translations/ru.po +17 -1
  106. package/lang/translations/si.po +17 -1
  107. package/lang/translations/sk.po +17 -1
  108. package/lang/translations/sq.po +17 -1
  109. package/lang/translations/sr-latn.po +17 -1
  110. package/lang/translations/sr.po +17 -1
  111. package/lang/translations/sv.po +17 -1
  112. package/lang/translations/tk.po +17 -1
  113. package/lang/translations/tr.po +17 -1
  114. package/lang/translations/ug.po +17 -1
  115. package/lang/translations/uk.po +17 -1
  116. package/lang/translations/uz.po +17 -1
  117. package/lang/translations/vi.po +17 -1
  118. package/lang/translations/zh-cn.po +17 -1
  119. package/lang/translations/zh.po +17 -1
  120. package/package.json +39 -27
  121. package/src/documentlist/converters.js +470 -0
  122. package/src/documentlist/documentlistcommand.js +216 -0
  123. package/src/documentlist/documentlistediting.js +676 -0
  124. package/src/documentlist/documentlistindentcommand.js +182 -0
  125. package/src/documentlist/documentlistmergecommand.js +235 -0
  126. package/src/documentlist/documentlistsplitcommand.js +114 -0
  127. package/src/documentlist/utils/listwalker.js +260 -0
  128. package/src/documentlist/utils/model.js +534 -0
  129. package/src/documentlist/utils/postfixers.js +138 -0
  130. package/src/documentlist/utils/view.js +148 -0
  131. package/src/documentlist.js +36 -0
  132. package/src/documentlistproperties/converters.js +57 -0
  133. package/src/documentlistproperties/documentlistpropertiesediting.js +338 -0
  134. package/src/documentlistproperties/documentlistreversedcommand.js +76 -0
  135. package/src/documentlistproperties/documentliststartcommand.js +76 -0
  136. package/src/documentlistproperties/documentliststylecommand.js +140 -0
  137. package/src/documentlistproperties/utils/style.js +41 -0
  138. package/src/documentlistproperties.js +37 -0
  139. package/src/index.js +8 -8
  140. package/src/{converters.js → list/converters.js} +24 -11
  141. package/src/{indentcommand.js → list/indentcommand.js} +2 -2
  142. package/src/{listcommand.js → list/listcommand.js} +3 -3
  143. package/src/{listediting.js → list/listediting.js} +12 -13
  144. package/src/{listui.js → list/listui.js} +4 -4
  145. package/src/{utils.js → list/utils.js} +81 -5
  146. package/src/list.js +29 -5
  147. package/src/{liststyleediting.js → listproperties/listpropertiesediting.js} +303 -125
  148. package/src/listproperties/listpropertiesui.js +313 -0
  149. package/src/listproperties/listreversedcommand.js +64 -0
  150. package/src/listproperties/liststartcommand.js +63 -0
  151. package/src/{liststylecommand.js → listproperties/liststylecommand.js} +40 -25
  152. package/src/listproperties/ui/collapsibleview.js +152 -0
  153. package/src/listproperties/ui/listpropertiesview.js +405 -0
  154. package/src/listproperties.js +101 -0
  155. package/src/liststyle.js +12 -6
  156. package/src/{checktodolistcommand.js → todolist/checktodolistcommand.js} +3 -3
  157. package/src/{todolistconverters.js → todolist/todolistconverters.js} +9 -5
  158. package/src/{todolistediting.js → todolist/todolistediting.js} +5 -5
  159. package/src/{todolistui.js → todolist/todolistui.js} +4 -4
  160. package/src/todolist.js +5 -5
  161. package/theme/collapsible.css +10 -0
  162. package/theme/documentlist.css +8 -0
  163. package/theme/listproperties.css +10 -0
  164. package/theme/liststyles.css +2 -6
  165. package/theme/todolist.css +1 -1
  166. package/src/liststyleui.js +0 -225
@@ -0,0 +1,76 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+
6
+ /**
7
+ * @module list/documentlistproperties/documentliststartcommand
8
+ */
9
+
10
+ import { Command } from 'ckeditor5/src/core';
11
+ import { first } from 'ckeditor5/src/utils';
12
+ import {
13
+ expandListBlocksToCompleteList,
14
+ isListItemBlock
15
+ } from '../documentlist/utils/model';
16
+
17
+ /**
18
+ * The list start index command. It changes the `listStart` attribute of the selected list items,
19
+ * letting the user to choose the starting point of an ordered list.
20
+ * It is used by the {@link module:list/documentlistproperties~DocumentListProperties list properties feature}.
21
+ *
22
+ * @extends module:core/command~Command
23
+ */
24
+ export default class DocumentListStartCommand extends Command {
25
+ /**
26
+ * @inheritDoc
27
+ */
28
+ refresh() {
29
+ const value = this._getValue();
30
+
31
+ this.value = value;
32
+ this.isEnabled = value != null;
33
+ }
34
+
35
+ /**
36
+ * Executes the command.
37
+ *
38
+ * @fires execute
39
+ * @param {Object} [options]
40
+ * @param {Number} [options.startIndex=1] The list start index.
41
+ */
42
+ execute( options = {} ) {
43
+ const model = this.editor.model;
44
+ const document = model.document;
45
+
46
+ let blocks = Array.from( document.selection.getSelectedBlocks() )
47
+ .filter( block => isListItemBlock( block ) && block.getAttribute( 'listType' ) == 'numbered' );
48
+
49
+ blocks = expandListBlocksToCompleteList( blocks );
50
+
51
+ model.change( writer => {
52
+ for ( const block of blocks ) {
53
+ writer.setAttribute( 'listStart', options.startIndex || 1, block );
54
+ }
55
+ } );
56
+ }
57
+
58
+ /**
59
+ * Checks the command's {@link #value}.
60
+ *
61
+ * @private
62
+ * @returns {Number|null} The current value.
63
+ */
64
+ _getValue() {
65
+ const model = this.editor.model;
66
+ const document = model.document;
67
+
68
+ const block = first( document.selection.getSelectedBlocks() );
69
+
70
+ if ( block && isListItemBlock( block ) && block.getAttribute( 'listType' ) == 'numbered' ) {
71
+ return block.getAttribute( 'listStart' );
72
+ }
73
+
74
+ return null;
75
+ }
76
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+
6
+ /**
7
+ * @module list/documentlistproperties/documentliststylecommand
8
+ */
9
+
10
+ import { Command } from 'ckeditor5/src/core';
11
+ import { first } from 'ckeditor5/src/utils';
12
+ import {
13
+ expandListBlocksToCompleteList,
14
+ isListItemBlock
15
+ } from '../documentlist/utils/model';
16
+ import { getListTypeFromListStyleType } from './utils/style';
17
+
18
+ /**
19
+ * The list style command. It changes `listStyle` attribute of the selected list items,
20
+ * letting the user choose styles for the list item markers.
21
+ * It is used by the {@link module:list/documentlistproperties~DocumentListProperties list properties feature}.
22
+ *
23
+ * @extends module:core/command~Command
24
+ */
25
+ export default class DocumentListStyleCommand extends Command {
26
+ /**
27
+ * Creates an instance of the command.
28
+ *
29
+ * @param {module:core/editor/editor~Editor} editor The editor instance.
30
+ * @param {String} defaultType The list type that will be used by default if the value was not specified during
31
+ * the command execution.
32
+ */
33
+ constructor( editor, defaultType ) {
34
+ super( editor );
35
+
36
+ /**
37
+ * The default type of the list style.
38
+ *
39
+ * @protected
40
+ * @member {String}
41
+ */
42
+ this._defaultType = defaultType;
43
+ }
44
+
45
+ /**
46
+ * @inheritDoc
47
+ */
48
+ refresh() {
49
+ this.value = this._getValue();
50
+ this.isEnabled = this._checkEnabled();
51
+ }
52
+
53
+ /**
54
+ * Executes the command.
55
+ *
56
+ * @fires execute
57
+ * @param {Object} options
58
+ * @param {String|null} [options.type] The type of the list style, e.g. `'disc'` or `'square'`. If `null` is specified, the default
59
+ * style will be applied.
60
+ */
61
+ execute( options = {} ) {
62
+ const model = this.editor.model;
63
+ const document = model.document;
64
+
65
+ model.change( writer => {
66
+ this._tryToConvertItemsToList( options );
67
+
68
+ let blocks = Array.from( document.selection.getSelectedBlocks() )
69
+ .filter( block => block.hasAttribute( 'listType' ) );
70
+
71
+ if ( !blocks.length ) {
72
+ return;
73
+ }
74
+
75
+ blocks = expandListBlocksToCompleteList( blocks );
76
+
77
+ for ( const block of blocks ) {
78
+ writer.setAttribute( 'listStyle', options.type || this._defaultType, block );
79
+ }
80
+ } );
81
+ }
82
+
83
+ /**
84
+ * Checks the command's {@link #value}.
85
+ *
86
+ * @private
87
+ * @returns {String|null} The current value.
88
+ */
89
+ _getValue() {
90
+ const listItem = first( this.editor.model.document.selection.getSelectedBlocks() );
91
+
92
+ if ( isListItemBlock( listItem ) ) {
93
+ return listItem.getAttribute( 'listStyle' );
94
+ }
95
+
96
+ return null;
97
+ }
98
+
99
+ /**
100
+ * Checks whether the command can be enabled in the current context.
101
+ *
102
+ * @private
103
+ * @returns {Boolean} Whether the command should be enabled.
104
+ */
105
+ _checkEnabled() {
106
+ const editor = this.editor;
107
+
108
+ const numberedList = editor.commands.get( 'numberedList' );
109
+ const bulletedList = editor.commands.get( 'bulletedList' );
110
+
111
+ return numberedList.isEnabled || bulletedList.isEnabled;
112
+ }
113
+
114
+ /**
115
+ * Check if the provided list style is valid. Also change the selection to a list if it's not set yet.
116
+ *
117
+ * @private
118
+ * @param {Object} options
119
+ * @param {String|null} [options.type] The type of the list style. If `null` is specified, the function does nothing.
120
+ */
121
+ _tryToConvertItemsToList( options ) {
122
+ if ( !options.type ) {
123
+ return;
124
+ }
125
+
126
+ const listType = getListTypeFromListStyleType( options.type );
127
+
128
+ if ( !listType ) {
129
+ return;
130
+ }
131
+
132
+ const editor = this.editor;
133
+ const commandName = listType + 'List';
134
+ const command = editor.commands.get( commandName );
135
+
136
+ if ( !command.value ) {
137
+ editor.execute( commandName );
138
+ }
139
+ }
140
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+
6
+ /**
7
+ * @module list/documentlistproperties/utils/style
8
+ */
9
+
10
+ const BULLETED_LIST_STYLE_TYPES = [ 'disc', 'circle', 'square' ];
11
+
12
+ // There's a lot of them (https://www.w3.org/TR/css-counter-styles-3/#typedef-counter-style).
13
+ // Let's support only those that can be selected by ListPropertiesUI.
14
+ const NUMBERED_LIST_STYLE_TYPES = [
15
+ 'decimal',
16
+ 'decimal-leading-zero',
17
+ 'lower-roman',
18
+ 'upper-roman',
19
+ 'lower-latin',
20
+ 'upper-latin',
21
+ 'lower-alpha',
22
+ 'upper-alpha'
23
+ ];
24
+
25
+ /**
26
+ * Checks whether the given list-style-type is supported by numbered or bulleted list.
27
+ *
28
+ * @param {String} listStyleType
29
+ * @returns {'bulleted'|'numbered'|null}
30
+ */
31
+ export function getListTypeFromListStyleType( listStyleType ) {
32
+ if ( BULLETED_LIST_STYLE_TYPES.includes( listStyleType ) ) {
33
+ return 'bulleted';
34
+ }
35
+
36
+ if ( NUMBERED_LIST_STYLE_TYPES.includes( listStyleType ) ) {
37
+ return 'numbered';
38
+ }
39
+
40
+ return null;
41
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+
6
+ /**
7
+ * @module list/documentlistproperties
8
+ */
9
+
10
+ import { Plugin } from 'ckeditor5/src/core';
11
+ import DocumentListPropertiesEditing from './documentlistproperties/documentlistpropertiesediting';
12
+ import ListPropertiesUI from './listproperties/listpropertiesui';
13
+
14
+ /**
15
+ * The document list properties feature.
16
+ *
17
+ * This is a "glue" plugin that loads the
18
+ * {@link module:list/documentlistproperties/documentlistpropertiesediting~DocumentListPropertiesEditing document list properties
19
+ * editing feature} and the {@link module:list/listproperties/listpropertiesui~ListPropertiesUI list properties UI feature}.
20
+ *
21
+ * @extends module:core/plugin~Plugin
22
+ */
23
+ export default class DocumentListProperties extends Plugin {
24
+ /**
25
+ * @inheritDoc
26
+ */
27
+ static get requires() {
28
+ return [ DocumentListPropertiesEditing, ListPropertiesUI ];
29
+ }
30
+
31
+ /**
32
+ * @inheritDoc
33
+ */
34
+ static get pluginName() {
35
+ return 'DocumentListProperties';
36
+ }
37
+ }
package/src/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
2
+ * @license Copyright (c) 2003-2022, 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
 
@@ -8,11 +8,11 @@
8
8
  */
9
9
 
10
10
  export { default as List } from './list';
11
- export { default as ListEditing } from './listediting';
12
- export { default as ListUI } from './listui';
13
- export { default as ListStyle } from './liststyle';
14
- export { default as ListStyleEditing } from './liststyleediting';
15
- export { default as ListStyleUI } from './liststyleui';
11
+ export { default as ListEditing } from './list/listediting';
12
+ export { default as ListUI } from './list/listui';
13
+ export { default as ListProperties } from './listproperties';
14
+ export { default as ListPropertiesEditing } from './listproperties/listpropertiesediting';
15
+ export { default as ListPropertiesUI } from './listproperties/listpropertiesui';
16
16
  export { default as TodoList } from './todolist';
17
- export { default as TodoListEditing } from './todolistediting';
18
- export { default as TodoListUI } from './todolistui';
17
+ export { default as TodoListEditing } from './todolist/todolistediting';
18
+ export { default as TodoListUI } from './todolist/todolistui';
@@ -1,10 +1,10 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
2
+ * @license Copyright (c) 2003-2022, 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
 
6
6
  /**
7
- * @module list/converters
7
+ * @module list/list/converters
8
8
  */
9
9
 
10
10
  import { TreeWalker } from 'ckeditor5/src/engine';
@@ -97,11 +97,11 @@ export function modelViewRemove( model ) {
97
97
  * A model-to-view converter for the `type` attribute change on the `listItem` model element.
98
98
  *
99
99
  * This change means that the `<li>` element parent changes from `<ul>` to `<ol>` (or vice versa). This is accomplished
100
- * by breaking view elements and changing their name. The next {@link module:list/converters~modelViewMergeAfterChangeType}
100
+ * by breaking view elements and changing their name. The next {@link module:list/list/converters~modelViewMergeAfterChangeType}
101
101
  * converter will attempt to merge split nodes.
102
102
  *
103
103
  * Splitting this conversion into 2 steps makes it possible to add an additional conversion in the middle.
104
- * Check {@link module:list/todolistconverters~modelViewChangeType} to see an example of it.
104
+ * Check {@link module:list/todolist/todolistconverters~modelViewChangeType} to see an example of it.
105
105
  *
106
106
  * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute
107
107
  * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.
@@ -109,7 +109,7 @@ export function modelViewRemove( model ) {
109
109
  * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface.
110
110
  */
111
111
  export function modelViewChangeType( evt, data, conversionApi ) {
112
- if ( !conversionApi.consumable.consume( data.item, 'attribute:listType' ) ) {
112
+ if ( !conversionApi.consumable.test( data.item, evt.name ) ) {
113
113
  return;
114
114
  }
115
115
 
@@ -130,7 +130,7 @@ export function modelViewChangeType( evt, data, conversionApi ) {
130
130
  }
131
131
 
132
132
  /**
133
- * A model-to-view converter that attempts to merge nodes split by {@link module:list/converters~modelViewChangeType}.
133
+ * A model-to-view converter that attempts to merge nodes split by {@link module:list/list/converters~modelViewChangeType}.
134
134
  *
135
135
  * @see module:engine/conversion/downcastdispatcher~DowncastDispatcher#event:attribute
136
136
  * @param {module:utils/eventinfo~EventInfo} evt An object containing information about the fired event.
@@ -138,6 +138,8 @@ export function modelViewChangeType( evt, data, conversionApi ) {
138
138
  * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface.
139
139
  */
140
140
  export function modelViewMergeAfterChangeType( evt, data, conversionApi ) {
141
+ conversionApi.consumable.consume( data.item, evt.name );
142
+
141
143
  const viewItem = conversionApi.mapper.toViewElement( data.item );
142
144
  const viewList = viewItem.parent;
143
145
  const viewWriter = conversionApi.writer;
@@ -145,11 +147,6 @@ export function modelViewMergeAfterChangeType( evt, data, conversionApi ) {
145
147
  // Merge the changed view list with other lists, if possible.
146
148
  mergeViewLists( viewWriter, viewList, viewList.nextSibling );
147
149
  mergeViewLists( viewWriter, viewList.previousSibling, viewList );
148
-
149
- // Consumable insertion of children inside the item. They are already handled by re-building the item in view.
150
- for ( const child of data.item.getChildren() ) {
151
- conversionApi.consumable.consume( child, 'insert' );
152
- }
153
150
  }
154
151
 
155
152
  /**
@@ -221,6 +218,10 @@ export function modelViewChangeIndent( model ) {
221
218
  * @param {module:engine/conversion/downcastdispatcher~DowncastConversionApi} conversionApi Conversion interface.
222
219
  */
223
220
  export function modelViewSplitOnInsert( evt, data, conversionApi ) {
221
+ if ( !conversionApi.consumable.test( data.item, evt.name ) ) {
222
+ return;
223
+ }
224
+
224
225
  if ( data.item.name != 'listItem' ) {
225
226
  let viewPosition = conversionApi.mapper.toViewPosition( data.range.start );
226
227
 
@@ -605,6 +606,18 @@ export function modelChangePostFixer( model, writer ) {
605
606
  applied = true;
606
607
  }
607
608
 
609
+ if ( item.hasAttribute( 'listReversed' ) ) {
610
+ writer.removeAttribute( 'listReversed', item );
611
+
612
+ applied = true;
613
+ }
614
+
615
+ if ( item.hasAttribute( 'listStart' ) ) {
616
+ writer.removeAttribute( 'listStart', item );
617
+
618
+ applied = true;
619
+ }
620
+
608
621
  for ( const innerItem of Array.from( model.createRangeIn( item ) ).filter( e => e.item.is( 'element', 'listItem' ) ) ) {
609
622
  _addListToFix( innerItem.previousPosition );
610
623
  }
@@ -1,10 +1,10 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
2
+ * @license Copyright (c) 2003-2022, 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
 
6
6
  /**
7
- * @module list/indentcommand
7
+ * @module list/list/indentcommand
8
8
  */
9
9
 
10
10
  import { Command } from 'ckeditor5/src/core';
@@ -1,10 +1,10 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
2
+ * @license Copyright (c) 2003-2022, 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
 
6
6
  /**
7
- * @module list/listcommand
7
+ * @module list/list/listcommand
8
8
  */
9
9
 
10
10
  import { Command } from 'ckeditor5/src/core';
@@ -56,7 +56,7 @@ export default class ListCommand extends Command {
56
56
  * @fires execute
57
57
  * @param {Object} [options] Command options.
58
58
  * @param {Boolean} [options.forceValue] If set, it will force the command behavior. If `true`, the command will try to convert the
59
- * selected items and potentially the neighbor elements to the proper list items. If set to `false` it will convert selected elements
59
+ * selected items and potentially the neighbor elements to the proper list items. If set to `false`, it will convert selected elements
60
60
  * to paragraphs. If not set, the command will toggle selected elements to list items or paragraphs, depending on the selection.
61
61
  */
62
62
  execute( options = {} ) {
@@ -1,10 +1,10 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
2
+ * @license Copyright (c) 2003-2022, 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
 
6
6
  /**
7
- * @module list/listediting
7
+ * @module list/list/listediting
8
8
  */
9
9
 
10
10
  import ListCommand from './listcommand';
@@ -171,19 +171,18 @@ export default class ListEditing extends Plugin {
171
171
  evt.stop();
172
172
  }, { context: 'li' } );
173
173
 
174
- const getCommandExecuter = commandName => {
175
- return ( data, cancel ) => {
176
- const command = this.editor.commands.get( commandName );
174
+ this.listenTo( editor.editing.view.document, 'tab', ( evt, data ) => {
175
+ const commandName = data.shiftKey ? 'outdentList' : 'indentList';
176
+ const command = this.editor.commands.get( commandName );
177
177
 
178
- if ( command.isEnabled ) {
179
- this.editor.execute( commandName );
180
- cancel();
181
- }
182
- };
183
- };
178
+ if ( command.isEnabled ) {
179
+ editor.execute( commandName );
184
180
 
185
- editor.keystrokes.set( 'Tab', getCommandExecuter( 'indentList' ) );
186
- editor.keystrokes.set( 'Shift+Tab', getCommandExecuter( 'outdentList' ) );
181
+ data.stopPropagation();
182
+ data.preventDefault();
183
+ evt.stop();
184
+ }
185
+ }, { context: 'li' } );
187
186
  }
188
187
 
189
188
  /**
@@ -1,16 +1,16 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
2
+ * @license Copyright (c) 2003-2022, 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
 
6
6
  /**
7
- * @module list/listui
7
+ * @module list/list/listui
8
8
  */
9
9
 
10
10
  import { createUIComponent } from './utils';
11
11
 
12
- import numberedListIcon from '../theme/icons/numberedlist.svg';
13
- import bulletedListIcon from '../theme/icons/bulletedlist.svg';
12
+ import numberedListIcon from '../../theme/icons/numberedlist.svg';
13
+ import bulletedListIcon from '../../theme/icons/bulletedlist.svg';
14
14
 
15
15
  import { Plugin } from 'ckeditor5/src/core';
16
16
 
@@ -1,10 +1,10 @@
1
1
  /**
2
- * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.
2
+ * @license Copyright (c) 2003-2022, 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
 
6
6
  /**
7
- * @module list/utils
7
+ * @module list/list/utils
8
8
  */
9
9
 
10
10
  import { TreeWalker, getFillerOffset } from 'ckeditor5/src/engine';
@@ -285,9 +285,9 @@ export function findNestedList( viewElement ) {
285
285
  }
286
286
 
287
287
  /**
288
- * Returns an array with all `listItem` elements that represents the same list.
288
+ * Returns an array with all `listItem` elements that represent the same list.
289
289
  *
290
- * It means that values for `listIndent`, `listType`, and `listStyle` for all items are equal.
290
+ * It means that values of `listIndent`, `listType`, `listStyle`, `listReversed` and `listStart` for all items are equal.
291
291
  *
292
292
  * @param {module:engine/model/position~Position} position Starting position.
293
293
  * @param {'forward'|'backward'} direction Walking direction.
@@ -350,11 +350,21 @@ export function getSiblingNodes( position, direction ) {
350
350
  // ○ List item 3. [listType=bulleted]
351
351
  // ○ List item 4. [listType=bulleted]
352
352
  //
353
- // Abort searching when found a different list style.
353
+ // Abort searching when found a different list style,
354
354
  if ( element.getAttribute( 'listStyle' ) !== listItem.getAttribute( 'listStyle' ) ) {
355
355
  break;
356
356
  }
357
357
 
358
+ // ... different direction
359
+ if ( element.getAttribute( 'listReversed' ) !== listItem.getAttribute( 'listReversed' ) ) {
360
+ break;
361
+ }
362
+
363
+ // ... and different start index
364
+ if ( element.getAttribute( 'listStart' ) !== listItem.getAttribute( 'listStart' ) ) {
365
+ break;
366
+ }
367
+
358
368
  if ( direction === 'backward' ) {
359
369
  items.unshift( element );
360
370
  } else {
@@ -365,6 +375,72 @@ export function getSiblingNodes( position, direction ) {
365
375
  return items;
366
376
  }
367
377
 
378
+ /**
379
+ * Returns an array with all `listItem` elements in the model selection.
380
+ *
381
+ * It returns all the items even if only a part of the list is selected, including items that belong to nested lists.
382
+ * If no list is selected, it returns an empty array.
383
+ * The order of the elements is not specified.
384
+ *
385
+ * @protected
386
+ * @param {module:engine/model/model~Model} model
387
+ * @returns {Array.<module:engine/model/element~Element>}
388
+ */
389
+ export function getSelectedListItems( model ) {
390
+ const document = model.document;
391
+
392
+ // For all selected blocks find all list items that are being selected
393
+ // and update the `listStyle` attribute in those lists.
394
+ let listItems = [ ...document.selection.getSelectedBlocks() ]
395
+ .filter( element => element.is( 'element', 'listItem' ) )
396
+ .map( element => {
397
+ const position = model.change( writer => writer.createPositionAt( element, 0 ) );
398
+
399
+ return [
400
+ ...getSiblingNodes( position, 'backward' ),
401
+ ...getSiblingNodes( position, 'forward' )
402
+ ];
403
+ } )
404
+ .flat();
405
+
406
+ // Since `getSelectedBlocks()` can return items that belong to the same list, and
407
+ // `getSiblingNodes()` returns the entire list, we need to remove duplicated items.
408
+ listItems = [ ...new Set( listItems ) ];
409
+
410
+ return listItems;
411
+ }
412
+
413
+ const BULLETED_LIST_STYLE_TYPES = [ 'disc', 'circle', 'square' ];
414
+
415
+ // There's a lot of them (https://www.w3.org/TR/css-counter-styles-3/#typedef-counter-style).
416
+ // Let's support only those that can be selected by ListPropertiesUI.
417
+ const NUMBERED_LIST_STYLE_TYPES = [
418
+ 'decimal',
419
+ 'decimal-leading-zero',
420
+ 'lower-roman',
421
+ 'upper-roman',
422
+ 'lower-latin',
423
+ 'upper-latin'
424
+ ];
425
+
426
+ /**
427
+ * Checks whether the given list-style-type is supported by numbered or bulleted list.
428
+ *
429
+ * @param {String} listStyleType
430
+ * @returns {'bulleted'|'numbered'|null}
431
+ */
432
+ export function getListTypeFromListStyleType( listStyleType ) {
433
+ if ( BULLETED_LIST_STYLE_TYPES.includes( listStyleType ) ) {
434
+ return 'bulleted';
435
+ }
436
+
437
+ if ( NUMBERED_LIST_STYLE_TYPES.includes( listStyleType ) ) {
438
+ return 'numbered';
439
+ }
440
+
441
+ return null;
442
+ }
443
+
368
444
  // Implementation of getFillerOffset for view list item element.
369
445
  //
370
446
  // @returns {Number|null} Block filler offset or `null` if block filler is not needed.