@ckeditor/ckeditor5-paste-from-office 47.2.0 → 47.3.0-alpha.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-paste-from-office",
3
- "version": "47.2.0",
3
+ "version": "47.3.0-alpha.1",
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.2.0",
17
- "@ckeditor/ckeditor5-core": "47.2.0",
18
- "@ckeditor/ckeditor5-engine": "47.2.0",
19
- "ckeditor5": "47.2.0"
16
+ "@ckeditor/ckeditor5-clipboard": "47.3.0-alpha.1",
17
+ "@ckeditor/ckeditor5-core": "47.3.0-alpha.1",
18
+ "@ckeditor/ckeditor5-engine": "47.3.0-alpha.1",
19
+ "ckeditor5": "47.3.0-alpha.1"
20
20
  },
21
21
  "author": "CKSource (http://cksource.com/)",
22
22
  "license": "SEE LICENSE IN LICENSE.md",
@@ -9,7 +9,8 @@ import { type ViewUpcastWriter, type ViewDocumentFragment } from 'ckeditor5/src/
9
9
  /**
10
10
  * Applies border none for table and cells without a border specified.
11
11
  * Normalizes style length units to px.
12
+ * Handles left block table alignment.
12
13
  *
13
14
  * @internal
14
15
  */
15
- export declare function transformTables(documentFragment: ViewDocumentFragment, writer: ViewUpcastWriter): void;
16
+ export declare function transformTables(documentFragment: ViewDocumentFragment, writer: ViewUpcastWriter, hasTablePropertiesPlugin?: boolean, hasExtendedTableBlockAlignment?: boolean): void;
@@ -6,16 +6,47 @@ import { convertCssLengthToPx } from './utils.js';
6
6
  /**
7
7
  * Applies border none for table and cells without a border specified.
8
8
  * Normalizes style length units to px.
9
+ * Handles left block table alignment.
9
10
  *
10
11
  * @internal
11
12
  */
12
- export function transformTables(documentFragment, writer) {
13
+ export function transformTables(documentFragment, writer, hasTablePropertiesPlugin = false, hasExtendedTableBlockAlignment = false) {
13
14
  for (const item of writer.createRangeIn(documentFragment).getItems()) {
14
15
  if (!item.is('element', 'table') &&
15
16
  !item.is('element', 'td') &&
16
17
  !item.is('element', 'th')) {
17
18
  continue;
18
19
  }
20
+ // In MS Word, left-aligned tables (default) have no align attribute on the `<table>` and are not wrapped in a `<div>`.
21
+ // In such cases, we need to set `margin-left: 0` and `margin-right: auto` to indicate to the editor that
22
+ // the table is block-aligned to the left.
23
+ //
24
+ // Center- and right-aligned tables in MS Word are wrapped in a `<div>` with the `align` attribute set to
25
+ // `center` or `right`, respectively with no align attribute on the `<table>` itself.
26
+ //
27
+ // Additionally, the structure may change when pasting content from MS Word.
28
+ // Some browsers (e.g., Safari) may insert extra elements around the table (e.g., a <span>),
29
+ // so the surrounding `<div>` with the `align` attribute may end up being the table's grandparent.
30
+ if (hasTablePropertiesPlugin && hasExtendedTableBlockAlignment && item.is('element', 'table')) {
31
+ const directParent = item.parent?.is('element', 'div') ? item.parent : null;
32
+ const grandParent = item.parent?.parent?.is('element', 'div') ? item.parent.parent : null;
33
+ const divParent = directParent ?? grandParent;
34
+ // Center block table alignment.
35
+ if (divParent && divParent.getAttribute('align') === 'center' && !item.getAttribute('align')) {
36
+ writer.setStyle('margin-left', 'auto', item);
37
+ writer.setStyle('margin-right', 'auto', item);
38
+ }
39
+ // Right block table alignment.
40
+ else if (divParent && divParent.getAttribute('align') === 'right' && !item.getAttribute('align')) {
41
+ writer.setStyle('margin-left', 'auto', item);
42
+ writer.setStyle('margin-right', '0', item);
43
+ }
44
+ // Left block table alignment.
45
+ else if (!divParent && !item.getAttribute('align')) {
46
+ writer.setStyle('margin-left', '0', item);
47
+ writer.setStyle('margin-right', 'auto', item);
48
+ }
49
+ }
19
50
  const sides = ['left', 'top', 'right', 'bottom'];
20
51
  // As this is a pasted table, we do not want default table styles to apply here
21
52
  // so we set border node for sides that does not have any border style.
@@ -10,12 +10,14 @@ import type { PasteFromOfficeNormalizer, PasteFromOfficeNormalizerData } from '.
10
10
  export declare class PasteFromOfficeMSWordNormalizer implements PasteFromOfficeNormalizer {
11
11
  readonly document: ViewDocument;
12
12
  readonly hasMultiLevelListPlugin: boolean;
13
+ readonly hasTablePropertiesPlugin: boolean;
14
+ readonly hasExtendedTableBlockAlignment: boolean;
13
15
  /**
14
16
  * Creates a new `PasteFromOfficeMSWordNormalizer` instance.
15
17
  *
16
18
  * @param document View document.
17
19
  */
18
- constructor(document: ViewDocument, hasMultiLevelListPlugin?: boolean);
20
+ constructor(document: ViewDocument, hasMultiLevelListPlugin?: boolean, hasTablePropertiesPlugin?: boolean, hasExtendedTableBlockAlignment?: boolean);
19
21
  /**
20
22
  * @inheritDoc
21
23
  */
@@ -21,14 +21,18 @@ const msWordMatch2 = /xmlns:o="urn:schemas-microsoft-com/i;
21
21
  export class PasteFromOfficeMSWordNormalizer {
22
22
  document;
23
23
  hasMultiLevelListPlugin;
24
+ hasTablePropertiesPlugin;
25
+ hasExtendedTableBlockAlignment;
24
26
  /**
25
27
  * Creates a new `PasteFromOfficeMSWordNormalizer` instance.
26
28
  *
27
29
  * @param document View document.
28
30
  */
29
- constructor(document, hasMultiLevelListPlugin = false) {
31
+ constructor(document, hasMultiLevelListPlugin = false, hasTablePropertiesPlugin = false, hasExtendedTableBlockAlignment = false) {
30
32
  this.document = document;
31
33
  this.hasMultiLevelListPlugin = hasMultiLevelListPlugin;
34
+ this.hasTablePropertiesPlugin = hasTablePropertiesPlugin;
35
+ this.hasExtendedTableBlockAlignment = hasExtendedTableBlockAlignment;
32
36
  }
33
37
  /**
34
38
  * @inheritDoc
@@ -45,7 +49,7 @@ export class PasteFromOfficeMSWordNormalizer {
45
49
  transformBookmarks(documentFragment, writer);
46
50
  transformListItemLikeElementsIntoLists(documentFragment, stylesString, this.hasMultiLevelListPlugin);
47
51
  replaceImagesSourceWithBase64(documentFragment, data.dataTransfer.getData('text/rtf'));
48
- transformTables(documentFragment, writer);
52
+ transformTables(documentFragment, writer, this.hasTablePropertiesPlugin, this.hasExtendedTableBlockAlignment);
49
53
  removeInvalidTableWidth(documentFragment, writer);
50
54
  replaceMSFootnotes(documentFragment, writer);
51
55
  removeMSAttributes(documentFragment);
@@ -65,7 +65,9 @@ export class PasteFromOffice extends Plugin {
65
65
  const viewDocument = editor.editing.view.document;
66
66
  const normalizers = [];
67
67
  const hasMultiLevelListPlugin = this.editor.plugins.has('MultiLevelList');
68
- normalizers.push(new PasteFromOfficeMSWordNormalizer(viewDocument, hasMultiLevelListPlugin));
68
+ const hasTablePropertiesPlugin = this.editor.plugins.has('TableProperties');
69
+ const hasExtendedTableBlockAlignment = !!this.editor.config.get('experimentalFlags.useExtendedTableBlockAlignment');
70
+ normalizers.push(new PasteFromOfficeMSWordNormalizer(viewDocument, hasMultiLevelListPlugin, hasTablePropertiesPlugin, hasExtendedTableBlockAlignment));
69
71
  normalizers.push(new GoogleDocsNormalizer(viewDocument));
70
72
  normalizers.push(new GoogleSheetsNormalizer(viewDocument));
71
73
  clipboardPipeline.on('inputTransformation', (evt, data) => {