@ckeditor/ckeditor5-paste-from-office 47.5.0 → 47.6.0-alpha.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-paste-from-office",
3
- "version": "47.5.0",
3
+ "version": "47.6.0-alpha.0",
4
4
  "description": "Paste from Office feature for CKEditor 5.",
5
5
  "keywords": [
6
6
  "ckeditor",
@@ -13,10 +13,10 @@
13
13
  "type": "module",
14
14
  "main": "src/index.js",
15
15
  "dependencies": {
16
- "@ckeditor/ckeditor5-clipboard": "47.5.0",
17
- "@ckeditor/ckeditor5-core": "47.5.0",
18
- "@ckeditor/ckeditor5-engine": "47.5.0",
19
- "ckeditor5": "47.5.0"
16
+ "@ckeditor/ckeditor5-clipboard": "47.6.0-alpha.0",
17
+ "@ckeditor/ckeditor5-core": "47.6.0-alpha.0",
18
+ "@ckeditor/ckeditor5-engine": "47.6.0-alpha.0",
19
+ "ckeditor5": "47.6.0-alpha.0"
20
20
  },
21
21
  "author": "CKSource (http://cksource.com/)",
22
22
  "license": "SEE LICENSE IN LICENSE.md",
@@ -6,7 +6,7 @@
6
6
  * @module paste-from-office/filters/list
7
7
  */
8
8
  import { Matcher, ViewUpcastWriter } from 'ckeditor5/src/engine.js';
9
- import { convertCssLengthToPx, isPx, toPx } from './utils.js';
9
+ import { convertCssLengthToPx, toPx } from './utils.js';
10
10
  /**
11
11
  * Transforms Word specific list-like elements to the semantic HTML lists.
12
12
  *
@@ -32,9 +32,12 @@ export function transformListItemLikeElementsIntoLists(documentFragment, stylesS
32
32
  }
33
33
  const encounteredLists = {};
34
34
  const stack = [];
35
+ let topLevelListInfo = createTopLevelListInfo();
35
36
  for (const itemLikeElement of itemLikeElements) {
36
37
  if (itemLikeElement.indent !== undefined) {
37
38
  if (!isListContinuation(itemLikeElement)) {
39
+ applyIndentationToTopLevelList(writer, stack, topLevelListInfo);
40
+ topLevelListInfo = createTopLevelListInfo();
38
41
  stack.length = 0;
39
42
  }
40
43
  // Combined list ID for addressing encounter lists counters.
@@ -61,16 +64,6 @@ export function transformListItemLikeElementsIntoLists(documentFragment, stylesS
61
64
  listStyle.startIndex = encounteredLists[originalListId];
62
65
  }
63
66
  const listElement = createNewEmptyList(listStyle, writer, hasMultiLevelListPlugin);
64
- // Apply list padding only if we have margins for the item and the parent item.
65
- if (isPx(itemLikeElement.marginLeft) &&
66
- (indent == 0 || isPx(stack[indent - 1].marginLeft))) {
67
- let marginLeft = itemLikeElement.marginLeft;
68
- if (indent > 0) {
69
- // Convert the padding from absolute to relative.
70
- marginLeft = toPx(parseFloat(marginLeft) - parseFloat(stack[indent - 1].marginLeft));
71
- }
72
- writer.setStyle('padding-left', marginLeft, listElement);
73
- }
74
67
  // Insert the new OL/UL.
75
68
  if (stack.length == 0) {
76
69
  const parent = itemLikeElement.element.parent;
@@ -96,6 +89,7 @@ export function transformListItemLikeElementsIntoLists(documentFragment, stylesS
96
89
  // Use LI if it is already it or create a new LI element.
97
90
  // https://github.com/ckeditor/ckeditor5/issues/15964
98
91
  const listItem = itemLikeElement.element.name == 'li' ? itemLikeElement.element : writer.createElement('li');
92
+ applyListItemMarginLeftAndUpdateTopLevelInfo(writer, stack, topLevelListInfo, itemLikeElement, listItem, indent);
99
93
  // Append the LI to OL/UL.
100
94
  writer.appendChild(listItem, stack[indent].listElement);
101
95
  stack[indent].listItemElements.push(listItem);
@@ -127,6 +121,70 @@ export function transformListItemLikeElementsIntoLists(documentFragment, stylesS
127
121
  }
128
122
  }
129
123
  }
124
+ applyIndentationToTopLevelList(writer, stack, topLevelListInfo);
125
+ }
126
+ function applyListItemMarginLeftAndUpdateTopLevelInfo(writer, stack, topLevelListInfo, itemLikeElement, listItem, indent) {
127
+ if (itemLikeElement.marginLeft === undefined) {
128
+ // If at least one of the list items at indent = 0 does not have margin-left style, we cannot set margin-left on the list.
129
+ if (indent == 0) {
130
+ topLevelListInfo.canApplyMarginOnList = false;
131
+ }
132
+ return;
133
+ }
134
+ const listItemBlockMarginLeft = parseFloat(itemLikeElement.marginLeft);
135
+ let currentListBlockIndent = 0;
136
+ if (stack.length > 1) {
137
+ const prevStackLevelItems = stack[stack.length - 2].listItemElements;
138
+ if (prevStackLevelItems.length > 0) {
139
+ // The margin-left style of the previous indent level last item is already a relative value applied in the previous iteration.
140
+ const lastItemMargin = prevStackLevelItems[prevStackLevelItems.length - 1].getStyle('margin-left');
141
+ if (lastItemMargin !== undefined) {
142
+ currentListBlockIndent += parseFloat(lastItemMargin);
143
+ }
144
+ }
145
+ }
146
+ // Add 40px for each indent level because by default HTML lists have 40px indentation (padding-inline-start: 40px).
147
+ // So every nested list is indented by another 40px.
148
+ // Additionally, the nested list itself may be placed in a list item with margin-left style.
149
+ currentListBlockIndent += stack.length * 40;
150
+ // Calculate relative list item indentation to the list it is in.
151
+ const adjustedListItemIndent = listItemBlockMarginLeft - currentListBlockIndent;
152
+ const listItemBlockMarginLeftPx = adjustedListItemIndent !== 0 ? toPx(adjustedListItemIndent) : undefined;
153
+ if (listItemBlockMarginLeftPx) {
154
+ writer.setStyle('margin-left', listItemBlockMarginLeftPx, listItem);
155
+ if (indent == 0 && topLevelListInfo.canApplyMarginOnList) {
156
+ if (topLevelListInfo.marginLeft === undefined) {
157
+ topLevelListInfo.marginLeft = listItemBlockMarginLeftPx;
158
+ }
159
+ if (listItemBlockMarginLeftPx !== topLevelListInfo.marginLeft) {
160
+ topLevelListInfo.canApplyMarginOnList = false;
161
+ }
162
+ topLevelListInfo.topLevelListItemElements.push(listItem);
163
+ }
164
+ }
165
+ }
166
+ function createTopLevelListInfo() {
167
+ return {
168
+ marginLeft: undefined,
169
+ canApplyMarginOnList: true,
170
+ topLevelListItemElements: []
171
+ };
172
+ }
173
+ /**
174
+ * Sets margin-left style to the top-level list if all its items have the same margin-left.
175
+ * If margin-left is set on the list, it is removed from all its items to avoid doubling of margins.
176
+ */
177
+ function applyIndentationToTopLevelList(writer, stack, topLevelListInfo) {
178
+ if (topLevelListInfo.canApplyMarginOnList &&
179
+ topLevelListInfo.marginLeft &&
180
+ topLevelListInfo.topLevelListItemElements.length > 0) {
181
+ // Apply margin-left to the top-level list if all its items have the same margin-left.
182
+ writer.setStyle('margin-left', topLevelListInfo.marginLeft, stack[0].listElement);
183
+ // Remove margin-left from all top-level list items.
184
+ for (const topLevelListItem of topLevelListInfo.topLevelListItemElements) {
185
+ writer.removeStyle('margin-left', topLevelListItem);
186
+ }
187
+ }
130
188
  }
131
189
  /**
132
190
  * Removes paragraph wrapping content inside a list item.