Sfoglia il codice sorgente

Merge branch 'master' into t/29

Krzysztof Krztoń 7 anni fa
parent
commit
09939704b1
83 ha cambiato i file con 3776 aggiunte e 1203 eliminazioni
  1. 2 2
      packages/ckeditor5-paste-from-office/src/filters/parse.js
  2. 18 2
      packages/ckeditor5-paste-from-office/src/filters/space.js
  3. 2 1
      packages/ckeditor5-paste-from-office/src/pastefromoffice.js
  4. 202 0
      packages/ckeditor5-paste-from-office/tests/README.md
  5. 4 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/bold-within-text/input.safari.word2016.html
  6. 1 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/bold-within-text/model.word2016.html
  7. 1 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/bold-within-text/normalized.safari.word2016.html
  8. 97 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/index.js
  9. 4 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/italic-starting-text/input.safari.word2016.html
  10. 1 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/italic-starting-text/model.word2016.html
  11. 1 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/italic-starting-text/normalized.safari.word2016.html
  12. 4 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/multiple-styles-multiline/input.safari.word2016.html
  13. 9 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/multiple-styles-multiline/model.word2016.html
  14. 3 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/multiple-styles-multiline/normalized.safari.word2016.html
  15. 4 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/multiple-styles-single-line/input.safari.word2016.html
  16. 6 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/multiple-styles-single-line/model.word2016.html
  17. 1 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/multiple-styles-single-line/normalized.safari.word2016.html
  18. 4 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/strikethrough-ending-text/input.safari.word2016.html
  19. 1 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/strikethrough-ending-text/model.word2016.html
  20. 1 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/strikethrough-ending-text/normalized.safari.word2016.html
  21. 4 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/underlined-text/input.safari.word2016.html
  22. 1 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/underlined-text/model.word2016.html
  23. 1 0
      packages/ckeditor5-paste-from-office/tests/_data/basic-styles/underlined-text/normalized.safari.word2016.html
  24. 4 0
      packages/ckeditor5-paste-from-office/tests/_data/link/combined/input.safari.word2016.html
  25. 1 0
      packages/ckeditor5-paste-from-office/tests/_data/link/combined/model.word2016.html
  26. 3 0
      packages/ckeditor5-paste-from-office/tests/_data/link/combined/normalized.safari.word2016.html
  27. 64 0
      packages/ckeditor5-paste-from-office/tests/_data/link/index.js
  28. 4 0
      packages/ckeditor5-paste-from-office/tests/_data/link/two-line/input.safari.word2016.html
  29. 1 0
      packages/ckeditor5-paste-from-office/tests/_data/link/two-line/model.word2016.html
  30. 8 0
      packages/ckeditor5-paste-from-office/tests/_data/link/two-line/normalized.safari.word2016.html
  31. 4 0
      packages/ckeditor5-paste-from-office/tests/_data/link/within-text/input.safari.word2016.html
  32. 1 0
      packages/ckeditor5-paste-from-office/tests/_data/link/within-text/model.word2016.html
  33. 3 0
      packages/ckeditor5-paste-from-office/tests/_data/link/within-text/normalized.safari.word2016.html
  34. 163 0
      packages/ckeditor5-paste-from-office/tests/_data/list/heading1/input.safari.word2016.html
  35. 2 0
      packages/ckeditor5-paste-from-office/tests/_data/list/heading1/model.word2016.html
  36. 15 0
      packages/ckeditor5-paste-from-office/tests/_data/list/heading1/normalized.safari.word2016.html
  37. 180 0
      packages/ckeditor5-paste-from-office/tests/_data/list/heading3-styled/input.safari.word2016.html
  38. 5 0
      packages/ckeditor5-paste-from-office/tests/_data/list/heading3-styled/model.word2016.html
  39. 13 0
      packages/ckeditor5-paste-from-office/tests/_data/list/heading3-styled/normalized.safari.word2016.html
  40. 170 0
      packages/ckeditor5-paste-from-office/tests/_data/list/heading7/input.safari.word2016.html
  41. 1 0
      packages/ckeditor5-paste-from-office/tests/_data/list/heading7/model.word2016.html
  42. 9 0
      packages/ckeditor5-paste-from-office/tests/_data/list/heading7/normalized.safari.word2016.html
  43. 121 0
      packages/ckeditor5-paste-from-office/tests/_data/list/index.js
  44. 847 0
      packages/ckeditor5-paste-from-office/tests/_data/list/many-one-item/input.safari.word2016.html
  45. 21 0
      packages/ckeditor5-paste-from-office/tests/_data/list/many-one-item/model.word2016.html
  46. 113 0
      packages/ckeditor5-paste-from-office/tests/_data/list/many-one-item/normalized.safari.word2016.html
  47. 258 0
      packages/ckeditor5-paste-from-office/tests/_data/list/multiple-combined/input.safari.word2016.html
  48. 4 0
      packages/ckeditor5-paste-from-office/tests/_data/list/multiple-combined/model.word2016.html
  49. 31 0
      packages/ckeditor5-paste-from-office/tests/_data/list/multiple-combined/normalized.safari.word2016.html
  50. 280 0
      packages/ckeditor5-paste-from-office/tests/_data/list/multiple/input.safari.word2016.html
  51. 6 0
      packages/ckeditor5-paste-from-office/tests/_data/list/multiple/model.word2016.html
  52. 25 0
      packages/ckeditor5-paste-from-office/tests/_data/list/multiple/normalized.safari.word2016.html
  53. 208 0
      packages/ckeditor5-paste-from-office/tests/_data/list/simple/input.safari.word2016.html
  54. 2 0
      packages/ckeditor5-paste-from-office/tests/_data/list/simple/model.word2016.html
  55. 15 0
      packages/ckeditor5-paste-from-office/tests/_data/list/simple/normalized.safari.word2016.html
  56. 245 0
      packages/ckeditor5-paste-from-office/tests/_data/list/styled/input.safari.word2016.html
  57. 9 0
      packages/ckeditor5-paste-from-office/tests/_data/list/styled/model.safari.word2016.html
  58. 9 0
      packages/ckeditor5-paste-from-office/tests/_data/list/styled/model.word2016.html
  59. 23 0
      packages/ckeditor5-paste-from-office/tests/_data/list/styled/normalized.safari.word2016.html
  60. 64 0
      packages/ckeditor5-paste-from-office/tests/_data/spacing/index.js
  61. 4 0
      packages/ckeditor5-paste-from-office/tests/_data/spacing/multi-line/input.safari.word2016.html
  62. 3 0
      packages/ckeditor5-paste-from-office/tests/_data/spacing/multi-line/model.word2016.html
  63. 11 0
      packages/ckeditor5-paste-from-office/tests/_data/spacing/multi-line/normalized.safari.word2016.html
  64. 4 0
      packages/ckeditor5-paste-from-office/tests/_data/spacing/simple/input.safari.word2016.html
  65. 1 0
      packages/ckeditor5-paste-from-office/tests/_data/spacing/simple/model.word2016.html
  66. 3 0
      packages/ckeditor5-paste-from-office/tests/_data/spacing/simple/normalized.safari.word2016.html
  67. 4 0
      packages/ckeditor5-paste-from-office/tests/_data/spacing/single-line/input.safari.word2016.html
  68. 1 0
      packages/ckeditor5-paste-from-office/tests/_data/spacing/single-line/model.word2016.html
  69. 3 0
      packages/ckeditor5-paste-from-office/tests/_data/spacing/single-line/normalized.safari.word2016.html
  70. 26 0
      packages/ckeditor5-paste-from-office/tests/_utils/fixtures.js
  71. 245 59
      packages/ckeditor5-paste-from-office/tests/_utils/utils.js
  72. 65 0
      packages/ckeditor5-paste-from-office/tests/data/integration.js
  73. 0 286
      packages/ckeditor5-paste-from-office/tests/data/integration/basic-styles.js
  74. 0 166
      packages/ckeditor5-paste-from-office/tests/data/integration/link.js
  75. 0 287
      packages/ckeditor5-paste-from-office/tests/data/integration/list.js
  76. 0 119
      packages/ckeditor5-paste-from-office/tests/data/integration/spacing.js
  77. 43 0
      packages/ckeditor5-paste-from-office/tests/data/normalization.js
  78. 0 70
      packages/ckeditor5-paste-from-office/tests/data/normalization/basic-styles.js
  79. 0 46
      packages/ckeditor5-paste-from-office/tests/data/normalization/link.js
  80. 0 76
      packages/ckeditor5-paste-from-office/tests/data/normalization/list.js
  81. 0 46
      packages/ckeditor5-paste-from-office/tests/data/normalization/spacing.js
  82. 41 39
      packages/ckeditor5-paste-from-office/tests/filters/list.js
  83. 18 4
      packages/ckeditor5-paste-from-office/tests/filters/space.js

+ 2 - 2
packages/ckeditor5-paste-from-office/src/filters/parse.js

@@ -12,7 +12,7 @@
 import DomConverter from '@ckeditor/ckeditor5-engine/src/view/domconverter';
 import { NBSP_FILLER } from '@ckeditor/ckeditor5-engine/src/view/filler';
 
-import { normalizeEndTagsPrecedingSpace, normalizeSpacerunSpans } from './space';
+import { normalizeSpacing, normalizeSpacerunSpans } from './space';
 
 /**
  * Parses provided HTML extracting contents of `<body>` and `<style>` tags.
@@ -30,7 +30,7 @@ export function parseHtml( htmlString ) {
 	const domParser = new DOMParser();
 
 	// Parse htmlString as native Document object.
-	const htmlDocument = domParser.parseFromString( normalizeEndTagsPrecedingSpace( htmlString ), 'text/html' );
+	const htmlDocument = domParser.parseFromString( normalizeSpacing( htmlString ), 'text/html' );
 
 	normalizeSpacerunSpans( htmlDocument );
 

+ 18 - 2
packages/ckeditor5-paste-from-office/src/filters/space.js

@@ -15,8 +15,8 @@
  * @param {String} htmlString HTML string in which spacing should be normalized.
  * @returns {String} Input HTML with spaces normalized.
  */
-export function normalizeEndTagsPrecedingSpace( htmlString ) {
-	return htmlString
+export function normalizeSpacing( htmlString ) {
+	return normalizeSafariSpaceSpans( normalizeSafariSpaceSpans( htmlString ) ) // Run normalization two times to cover nested spans.
 		.replace( / <\//g, '\u00A0</' )
 		.replace( / <o:p><\/o:p>/g, '\u00A0<o:p></o:p>' );
 }
@@ -37,3 +37,19 @@ export function normalizeSpacerunSpans( htmlDocument ) {
 		el.innerHTML = Array( innerTextLength + 1 ).join( '\u00A0 ' ).substr( 0, innerTextLength );
 	} );
 }
+
+// Normalizes specific spacing generated by Safari when content pasted from Word (`<span class="Apple-converted-space"> </span>`)
+// by replacing all spaces sequences longer than 1 space with `&nbsp; ` pairs. This prevents spaces from being removed during
+// further DOM/View processing (see especially {@link module:engine/view/domconverter~DomConverter#_processDataFromDomText}).
+//
+// This function is similar to {@link module:clipboard/utils/normalizeclipboarddata normalizeClipboardData util} but uses
+// regular spaces / &nbsp; sequence for replacement.
+//
+// @param {String} htmlString HTML string in which spacing should be normalized
+// @returns {String} Input HTML with spaces normalized.
+function normalizeSafariSpaceSpans( htmlString ) {
+	return htmlString.replace( /<span(?: class="Apple-converted-space"|)>(\s+)<\/span>/g, ( fullMatch, spaces ) => {
+		return spaces.length === 1 ? ' ' : Array( spaces.length + 1 ).join( '\u00A0 ' ).substr( 0, spaces.length );
+	} );
+}
+

+ 2 - 1
packages/ckeditor5-paste-from-office/src/pastefromoffice.js

@@ -68,5 +68,6 @@ export default class PasteFromOffice extends Plugin {
 // @param {String} html HTML string to test.
 // @returns {Boolean} True if given HTML string is a Word HTML.
 function isWordInput( html ) {
-	return !!( html && html.match( /<meta\s*name="?generator"?\s*content="?microsoft\s*word\s*\d+"?\/?>/gi ) );
+	return !!( html && ( html.match( /<meta\s*name="?generator"?\s*content="?microsoft\s*word\s*\d+"?\/?>/gi ) ||
+		html.match( /xmlns:o="urn:schemas-microsoft-com/gi ) ) );
 }

+ 202 - 0
packages/ckeditor5-paste-from-office/tests/README.md

@@ -0,0 +1,202 @@
+# Testing
+
+In order to test if a content pasted from any external application is transformed correctly by the editor the test itself needs to use data which is put into the native clipboard by that application. For test purposes, such data is stored in a single file called a fixture file.
+
+The fixture file is usually an HTML file containing HTML content which was fetched from the native browser `dataTransfer` object (`dataTransfer.getData( 'html/text' )`). This ensures that the fixture file provides exactly same data as a real use scenario.
+
+## Fixture files
+
+_For example files see `_data/basic-style/bold-within-text/`_.
+
+Fixture files are grouped per feature (which usually corresponds to editor plugins, for example `basic-styles`, `list`, etc). All fixtures are stored in `_data/feature-name/` directory (for example `_data/basic-style/`). Each feature (which will be called a *group*) has a separate folder per fixture. Each fixture is used to create one normalization and one integration test.
+
+Each fixture folder contains:
+
+- original input file - `bold-with-text.docx`
+- input fixture - `input.word2016.html`
+- normalized output fixture - `normalized.word2016.html`
+- model output fixture - `model.word2016.html`
+
+In some cases, different browsers produces different input data. For such situations, additional fixtures are stored. For example if input data is different for Safari, additional `input.safari.word2016.html` file will be present in the fixture directory.
+
+## Tests group index
+
+_For example file see `_data/basic-style/index.js`_.
+
+Each group of fixtures contains an index file (`index.js` in a group folder – e.g. `_data/basic-styles/index.js`). Its purpose is to import all fixture files from the group and expose them for further use. An index file has the following structure:
+
+```js
+// Import default/generic fixtures.
+// Input fixtures.
+import boldWithinText from './bold-within-text/input.word2016.html';
+
+// Expected normalized fixtures.
+import boldWithinTextNormalized from './bold-within-text/normalized.word2016.html';
+
+// Expected model fixtures.
+import boldWithinTextModel from './bold-within-text/model.word2016.html';
+
+// Export imported generic fixtures for future use.
+export const fixtures = {
+	input: {
+		boldWithinText
+	},
+	normalized: {
+		boldWithinText: boldWithinTextNormalized
+	},
+	model: {
+		boldWithinText: boldWithinTextModel
+	}
+};
+```
+
+Such a structure exports generic fixtures (the ones which are the same for more than one browser and will be used if no browser specific fixtures are present).
+
+Index files must also export browser specific fixtures. In the simplest case if there are none, it exports an empty object:
+
+```js
+export browserFixtures = {};
+```
+
+If there are any browser specific fixtures, they are exported in a similar manner to generic ones (apart from being grouped by a browser):
+
+```js
+// Export imported browser-specific fixtures for future use.
+export const browserFixtures = {
+	safari: {
+		input: {
+			boldWithinText: boldWithinTextSafari
+		},
+		normalized: {
+			boldWithinText: boldWithinTextNormalizedSafari
+		},
+		model: {
+			boldWithinText: boldWithinTextModelSafari
+		}
+	}
+};
+```
+
+### What if only input or one of the expected output fixtures are different for specific browser? Could fixtures be mixed?
+
+There are cases when only some fixtures differ for a given browser. In such cases browser fixtures export reuses generic fixtures:
+
+```js
+// Export imported browser-specific fixtures for future use.
+export const browserFixtures = {
+	safari: {
+		input: {
+			boldWithinText: boldWithinText // generic
+		},
+		normalized: {
+			boldWithinText: boldWithinTextNormalizedSafari // Safari specific
+		},
+		model: {
+			boldWithinText: boldWithinTextModel // generic
+		}
+	}
+};
+```
+
+## Fixtures aggregation
+
+_See `_utils/fixtures.js`_.
+
+All group index files are aggregated in the `fixtures` util (`_utils/fixtures.js`) and exposed for tests in a single `fixtures` and `browserFixtures` objects:
+
+```js
+// Import fixtures.
+import { fixtures as basicStyles, browserFixtures as basicStylesBrowser } from '../_data/basic-styles/index.js';
+
+// Generic fixtures.
+export const fixtures = {
+	'basic-styles': basicStyles
+};
+
+// Browser specific fixtures.
+export const browserFixtures = {
+	'basic-styles': basicStylesBrowser
+};
+```
+
+## Tests generation
+
+_See `data/normalization.js` and `data/integration.js`_.
+
+Tests based on fixture files are generated by the special util function `generateTests()` (see `_utils/utils.js`). This function is specifically designed to generate `normalization` (see `data/normalization.js`) or `integration` (see `data/integration.js`) tests using provided fixtures group, for example:
+
+```js
+generateTests( {
+	input: 'basic-styles', // Group name.
+	type: 'integration', // Tests type (integration or normalization).
+	browsers: [ 'chrome', 'firefox', 'safari', 'edge' ], // For which browsers generate tests.
+	editorConfig: { // Editor config which will be used during editor creation which is used in tests.
+		plugins: [ Clipboard, Paragraph, Heading, Bold, Italic, Underline, Strikethrough, PasteFromOffice ]
+	},
+	skip: { // Names of fixtures which tests should be skipped (object `key` is the name of the browser for which to skip tests).
+		safari: [ 'italicStartingText', 'multipleStylesSingleLine', 'multipleStylesMultiline' ] // Skip due to spacing issue (#13).
+	}
+} );
+```
+
+## Adding new tests
+
+### To an existing group
+
+1. Create new fixtures directory in a group to which you plan to add tests (e.g. `_data/link/new-use-case/`).
+2. Add all necessary fixture files to the above directory:
+	* original input file - `new-use-case.docx`
+	* input fixture - `input.word2016.html` (to acquire clipboard data you may use `integration.html` manual test which prints `text/html` on paste)
+	* normalized output fixture - `normalized.word2016.html`
+	* model output fixture - `model.word2016.html`
+	* any browser specific fixtures
+3. Add new fixtures to group `index.js` file.
+
+That's all, added fixtures will be now used to generate normalization and integration test.
+
+### To a new group
+
+1. Create new group directory, for example `_data/new-group/`.
+2. Create new fixtures directories (one per input fixture file) in `_data/new-group/`, each containing:
+	* original input file - `new-use-case.docx`
+	* input fixture - `input.word2016.html` (to acquire clipboard data you may use `integration.html` manual test which prints `text/html` on paste)
+	* normalized output fixture - `normalized.word2016.html`
+	* model output fixture - `model.word2016.html`
+	* any browser specific fixtures
+3. Create group `index.js` file (`_data/new-group/index.js`) importing all necessary fixtures.
+4. Add new group to fixtures util `_utils/fixtures.js`:
+
+	```js
+	// Import fixtures.
+	import { fixtures as newGroup, browserFixtures as newGroupBrowser } from '../_data/new-group/index.js';
+
+	// Generic fixtures.
+	export const fixtures = {
+		'new-group': newGroup
+	};
+
+	// Browser specific fixtures.
+	export const browserFixtures = {
+		'new-group': newGroupBrowser
+	};
+	```
+
+5. Add `generateTests()` function call in `data/normalization.js` to generate normalization and in `data/integration.js` to generate integration tests:
+
+	```js
+	// normalization.js
+	generateTests( {
+		input: 'new-group',
+		type: 'normalization',
+		browsers: [ 'chrome', 'firefox', 'safari', 'edge' ]
+		editorConfig: { ... }
+	} );
+
+	// integration.js
+	generateTests( {
+		input: 'new-group',
+		type: 'integration',
+		browsers: [ 'chrome', 'firefox', 'safari', 'edge' ]
+		editorConfig: { ... }
+	} );
+	```

File diff suppressed because it is too large
+ 4 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/bold-within-text/input.safari.word2016.html


+ 1 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/bold-within-text/model.word2016.html

@@ -0,0 +1 @@
+<paragraph>Some text <$text bold="true">with bold</$text>.</paragraph>

File diff suppressed because it is too large
+ 1 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/bold-within-text/normalized.safari.word2016.html


+ 97 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/index.js

@@ -0,0 +1,97 @@
+/**
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+// Default.
+import boldWithinText from './bold-within-text/input.word2016.html';
+import italicStartingText from './italic-starting-text/input.word2016.html';
+import underlinedText from './underlined-text/input.word2016.html';
+import strikethroughEndingText from './strikethrough-ending-text/input.word2016.html';
+import multipleStylesSingleLine from './multiple-styles-single-line/input.word2016.html';
+import multipleStylesMultiline from './multiple-styles-multiline/input.word2016.html';
+
+import boldWithinTextNormalized from './bold-within-text/normalized.word2016.html';
+import italicStartingTextNormalized from './italic-starting-text/normalized.word2016.html';
+import underlinedTextNormalized from './underlined-text/normalized.word2016.html';
+import strikethroughEndingTextNormalized from './strikethrough-ending-text/normalized.word2016.html';
+import multipleStylesSingleLineNormalized from './multiple-styles-single-line/normalized.word2016.html';
+import multipleStylesMultilineNormalized from './multiple-styles-multiline/normalized.word2016.html';
+
+import boldWithinTextModel from './bold-within-text/model.word2016.html';
+import italicStartingTextModel from './italic-starting-text/model.word2016.html';
+import underlinedTextModel from './underlined-text/model.word2016.html';
+import strikethroughEndingTextModel from './strikethrough-ending-text/model.word2016.html';
+import multipleStylesSingleLineModel from './multiple-styles-single-line/model.word2016.html';
+import multipleStylesMultilineModel from './multiple-styles-multiline/model.word2016.html';
+
+export const fixtures = {
+	input: {
+		boldWithinText,
+		italicStartingText,
+		underlinedText,
+		strikethroughEndingText,
+		multipleStylesSingleLine,
+		multipleStylesMultiline
+	},
+	normalized: {
+		boldWithinText: boldWithinTextNormalized,
+		italicStartingText: italicStartingTextNormalized,
+		underlinedText: underlinedTextNormalized,
+		strikethroughEndingText: strikethroughEndingTextNormalized,
+		multipleStylesSingleLine: multipleStylesSingleLineNormalized,
+		multipleStylesMultiline: multipleStylesMultilineNormalized
+	},
+	model: {
+		boldWithinText: boldWithinTextModel,
+		italicStartingText: italicStartingTextModel,
+		underlinedText: underlinedTextModel,
+		strikethroughEndingText: strikethroughEndingTextModel,
+		multipleStylesSingleLine: multipleStylesSingleLineModel,
+		multipleStylesMultiline: multipleStylesMultilineModel
+	}
+};
+
+// Safari.
+import boldWithinTextSafari from './bold-within-text/input.safari.word2016.html';
+import italicStartingTextSafari from './italic-starting-text/input.safari.word2016.html';
+import underlinedTextSafari from './underlined-text/input.safari.word2016.html';
+import strikethroughEndingTextSafari from './strikethrough-ending-text/input.safari.word2016.html';
+import multipleStylesSingleLineSafari from './multiple-styles-single-line/input.safari.word2016.html';
+import multipleStylesMultilineSafari from './multiple-styles-multiline/input.safari.word2016.html';
+
+import boldWithinTextNormalizedSafari from './bold-within-text/normalized.safari.word2016.html';
+import italicStartingTextNormalizedSafari from './italic-starting-text/normalized.safari.word2016.html';
+import underlinedTextNormalizedSafari from './underlined-text/normalized.safari.word2016.html';
+import strikethroughEndingTextNormalizedSafari from './strikethrough-ending-text/normalized.safari.word2016.html';
+import multipleStylesSingleLineNormalizedSafari from './multiple-styles-single-line/normalized.safari.word2016.html';
+import multipleStylesMultilineNormalizedSafari from './multiple-styles-multiline/normalized.safari.word2016.html';
+
+export const browserFixtures = {
+	safari: {
+		input: {
+			boldWithinText: boldWithinTextSafari,
+			italicStartingText: italicStartingTextSafari,
+			underlinedText: underlinedTextSafari,
+			strikethroughEndingText: strikethroughEndingTextSafari,
+			multipleStylesSingleLine: multipleStylesSingleLineSafari,
+			multipleStylesMultiline: multipleStylesMultilineSafari
+		},
+		normalized: {
+			boldWithinText: boldWithinTextNormalizedSafari,
+			italicStartingText: italicStartingTextNormalizedSafari,
+			underlinedText: underlinedTextNormalizedSafari,
+			strikethroughEndingText: strikethroughEndingTextNormalizedSafari,
+			multipleStylesSingleLine: multipleStylesSingleLineNormalizedSafari,
+			multipleStylesMultiline: multipleStylesMultilineNormalizedSafari
+		},
+		model: {
+			boldWithinText: boldWithinTextModel,
+			italicStartingText: italicStartingTextModel,
+			underlinedText: underlinedTextModel,
+			strikethroughEndingText: strikethroughEndingTextModel,
+			multipleStylesSingleLine: multipleStylesSingleLineModel,
+			multipleStylesMultiline: multipleStylesMultilineModel
+		}
+	}
+};

File diff suppressed because it is too large
+ 4 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/italic-starting-text/input.safari.word2016.html


+ 1 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/italic-starting-text/model.word2016.html

@@ -0,0 +1 @@
+<paragraph><$text italic="true">Italic</$text> text.</paragraph>

File diff suppressed because it is too large
+ 1 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/italic-starting-text/normalized.safari.word2016.html


File diff suppressed because it is too large
+ 4 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/multiple-styles-multiline/input.safari.word2016.html


+ 9 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/multiple-styles-multiline/model.word2016.html

@@ -0,0 +1,9 @@
+<paragraph>Line <$text bold="true">bold</$text> and <$text italic="true">italics</$text></paragraph>
+
+<paragraph>Line <$text bold="true" underline="true">foo</$text><$text underline="true"> bar</$text></paragraph>
+
+<paragraph>
+	<$text strikethrough="true">Third</$text> line <$text bold="true">styling, </$text>
+	<$text bold="true" italic="true">space on e</$text>
+	<$text bold="true">nd </$text>
+</paragraph>

File diff suppressed because it is too large
+ 3 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/multiple-styles-multiline/normalized.safari.word2016.html


File diff suppressed because it is too large
+ 4 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/multiple-styles-single-line/input.safari.word2016.html


+ 6 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/multiple-styles-single-line/model.word2016.html

@@ -0,0 +1,6 @@
+<paragraph>Text <$text bold="true" underline="true">containi</$text>
+	<$text bold="true" strikethrough="true" underline="true">ng</$text>
+	<$text strikethrough="true" underline="true"> multi</$text>
+	<$text strikethrough="true">ple </$text>
+	<$text italic="true">styling</$text>.
+</paragraph>

File diff suppressed because it is too large
+ 1 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/multiple-styles-single-line/normalized.safari.word2016.html


File diff suppressed because it is too large
+ 4 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/strikethrough-ending-text/input.safari.word2016.html


+ 1 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/strikethrough-ending-text/model.word2016.html

@@ -0,0 +1 @@
+<paragraph>Text <$text strikethrough="true">incorrect</$text></paragraph>

File diff suppressed because it is too large
+ 1 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/strikethrough-ending-text/normalized.safari.word2016.html


File diff suppressed because it is too large
+ 4 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/underlined-text/input.safari.word2016.html


+ 1 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/underlined-text/model.word2016.html

@@ -0,0 +1 @@
+<paragraph><$text underline="true">Whole text underlined</$text></paragraph>

File diff suppressed because it is too large
+ 1 - 0
packages/ckeditor5-paste-from-office/tests/_data/basic-styles/underlined-text/normalized.safari.word2016.html


File diff suppressed because it is too large
+ 4 - 0
packages/ckeditor5-paste-from-office/tests/_data/link/combined/input.safari.word2016.html


+ 1 - 0
packages/ckeditor5-paste-from-office/tests/_data/link/combined/model.word2016.html

@@ -0,0 +1 @@
+<paragraph><$text linkHref="https://ckeditor.com/">CKEditor</$text><$text linkHref="https://cksource.com/">CKSource</$text> 2</paragraph>

+ 3 - 0
packages/ckeditor5-paste-from-office/tests/_data/link/combined/normalized.safari.word2016.html

@@ -0,0 +1,3 @@
+<p class="MsoNormal" style="margin: 0cm 0cm 8pt; line-height: 15.693333625793457px; font-size: 11pt; font-family: Calibri, sans-serif; caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;">
+	<span><a href="https://ckeditor.com/" style="color: rgb(149, 79, 114); text-decoration: underline;">CKEditor</a><span class="MsoHyperlink" style="color: rgb(5, 99, 193); text-decoration: underline;"><a href="https://cksource.com/" style="color: rgb(149, 79, 114); text-decoration: underline;">CKSource</a></span>2<o:p></o:p></span>
+</p>

+ 64 - 0
packages/ckeditor5-paste-from-office/tests/_data/link/index.js

@@ -0,0 +1,64 @@
+/**
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+// Default.
+import withinText from './within-text/input.word2016.html';
+import combined from './combined/input.word2016.html';
+import twoLine from './two-line/input.word2016.html';
+
+import withinTextNormalized from './within-text/normalized.word2016.html';
+import combinedNormalized from './combined/normalized.word2016.html';
+import twoLineNormalized from './two-line/normalized.word2016.html';
+
+import withinTextModel from './within-text/model.word2016.html';
+import combinedModel from './combined/model.word2016.html';
+import twoLineModel from './two-line/model.word2016.html';
+
+export const fixtures = {
+	input: {
+		withinText,
+		combined,
+		twoLine
+	},
+	normalized: {
+		withinText: withinTextNormalized,
+		combined: combinedNormalized,
+		twoLine: twoLineNormalized
+	},
+	model: {
+		withinText: withinTextModel,
+		combined: combinedModel,
+		twoLine: twoLineModel
+	}
+};
+
+// Safari.
+import withinTextSafari from './within-text/input.safari.word2016.html';
+import combinedSafari from './combined/input.safari.word2016.html';
+import twoLineSafari from './two-line/input.safari.word2016.html';
+
+import withinTextNormalizedSafari from './within-text/normalized.safari.word2016.html';
+import combinedNormalizedSafari from './combined/normalized.safari.word2016.html';
+import twoLineNormalizedSafari from './two-line/normalized.safari.word2016.html';
+
+export const browserFixtures = {
+	safari: {
+		input: {
+			withinText: withinTextSafari,
+			combined: combinedSafari,
+			twoLine: twoLineSafari
+		},
+		normalized: {
+			withinText: withinTextNormalizedSafari,
+			combined: combinedNormalizedSafari,
+			twoLine: twoLineNormalizedSafari
+		},
+		model: {
+			withinText: withinTextModel,
+			combined: combinedModel,
+			twoLine: twoLineModel
+		}
+	}
+};

File diff suppressed because it is too large
+ 4 - 0
packages/ckeditor5-paste-from-office/tests/_data/link/two-line/input.safari.word2016.html


+ 1 - 0
packages/ckeditor5-paste-from-office/tests/_data/link/two-line/model.word2016.html

@@ -0,0 +1 @@
+<paragraph><$text linkHref="https://cksource.com/">Long link </$text><softBreak></softBreak><$text linkHref="https://cksource.com/">WITH spaces</$text></paragraph>

+ 8 - 0
packages/ckeditor5-paste-from-office/tests/_data/link/two-line/normalized.safari.word2016.html

@@ -0,0 +1,8 @@
+<p class="MsoNormal" style="margin: 0cm 0cm 8pt; line-height: 15.693333625793457px; font-size: 11pt; font-family: Calibri, sans-serif; caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;">
+	<span class="MsoHyperlink" style="color: rgb(5, 99, 193); text-decoration: underline;">
+		<span>
+			<a href="https://cksource.com/" style="color: rgb(149, 79, 114); text-decoration: underline;">Long link <br>WITH spaces</a>
+		</span>
+	</span>
+	<span><o:p></o:p></span>
+</p>

File diff suppressed because it is too large
+ 4 - 0
packages/ckeditor5-paste-from-office/tests/_data/link/within-text/input.safari.word2016.html


+ 1 - 0
packages/ckeditor5-paste-from-office/tests/_data/link/within-text/model.word2016.html

@@ -0,0 +1 @@
+<paragraph>Regular <$text linkHref="https://ckeditor.com/">link</$text>1</paragraph>

+ 3 - 0
packages/ckeditor5-paste-from-office/tests/_data/link/within-text/normalized.safari.word2016.html

@@ -0,0 +1,3 @@
+<p class="MsoNormal" style="margin: 0cm 0cm 8pt; line-height: 15.693333625793457px; font-size: 11pt; font-family: Calibri, sans-serif; caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;">
+	<span>Regular <span class="MsoHyperlink" style="color: rgb(5, 99, 193); text-decoration: underline;"><a href="https://ckeditor.com/" style="color: rgb(149, 79, 114); text-decoration: underline;">link</a></span>1<o:p></o:p></span>
+</p>

+ 163 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/heading1/input.safari.word2016.html

@@ -0,0 +1,163 @@
+<html xmlns:o="urn:schemas-microsoft-com:office:office"
+	  xmlns:w="urn:schemas-microsoft-com:office:word"
+	  xmlns:m="http://schemas.microsoft.com/office/2004/12/omml"
+	  xmlns="http://www.w3.org/TR/REC-html40"><head><style class="WebKit-mso-list-quirks-style">
+	<!--
+	/* Style Definitions */
+	p.MsoNormal, li.MsoNormal, div.MsoNormal
+	{mso-style-unhide:no;
+		mso-style-qformat:yes;
+		mso-style-parent:"";
+		margin-top:0cm;
+		margin-right:0cm;
+		margin-bottom:8.0pt;
+		margin-left:0cm;
+		line-height:107%;
+		mso-pagination:widow-orphan;
+		font-size:11.0pt;
+		font-family:"Calibri",sans-serif;
+		mso-ascii-font-family:Calibri;
+		mso-ascii-theme-font:minor-latin;
+		mso-fareast-font-family:"Yu Mincho";
+		mso-fareast-theme-font:minor-fareast;
+		mso-hansi-font-family:Calibri;
+		mso-hansi-theme-font:minor-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:minor-bidi;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;}
+	h1
+	{mso-style-priority:9;
+		mso-style-unhide:no;
+		mso-style-qformat:yes;
+		mso-style-link:"Heading 1 Char";
+		mso-style-next:Normal;
+		margin-top:12.0pt;
+		margin-right:0cm;
+		margin-bottom:0cm;
+		margin-left:0cm;
+		margin-bottom:.0001pt;
+		line-height:107%;
+		mso-pagination:widow-orphan lines-together;
+		page-break-after:avoid;
+		mso-outline-level:1;
+		font-size:16.0pt;
+		font-family:"Calibri Light",sans-serif;
+		mso-ascii-font-family:"Calibri Light";
+		mso-ascii-theme-font:major-latin;
+		mso-fareast-font-family:"Yu Gothic Light";
+		mso-fareast-theme-font:major-fareast;
+		mso-hansi-font-family:"Calibri Light";
+		mso-hansi-theme-font:major-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:major-bidi;
+		color:#2F5496;
+		mso-themecolor:accent1;
+		mso-themeshade:191;
+		mso-font-kerning:0pt;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;
+		font-weight:normal;}
+	span.Heading1Char
+	{mso-style-name:"Heading 1 Char";
+		mso-style-priority:9;
+		mso-style-unhide:no;
+		mso-style-locked:yes;
+		mso-style-link:"Heading 1";
+		mso-ansi-font-size:16.0pt;
+		mso-bidi-font-size:16.0pt;
+		font-family:"Calibri Light",sans-serif;
+		mso-ascii-font-family:"Calibri Light";
+		mso-ascii-theme-font:major-latin;
+		mso-fareast-font-family:"Yu Gothic Light";
+		mso-fareast-theme-font:major-fareast;
+		mso-hansi-font-family:"Calibri Light";
+		mso-hansi-theme-font:major-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:major-bidi;
+		color:#2F5496;
+		mso-themecolor:accent1;
+		mso-themeshade:191;}
+	.MsoChpDefault
+	{mso-style-type:export-only;
+		mso-default-props:yes;
+		font-size:11.0pt;
+		mso-ansi-font-size:11.0pt;
+		mso-bidi-font-size:11.0pt;
+		font-family:"Calibri",sans-serif;
+		mso-ascii-font-family:Calibri;
+		mso-ascii-theme-font:minor-latin;
+		mso-fareast-font-family:"Yu Mincho";
+		mso-fareast-theme-font:minor-fareast;
+		mso-hansi-font-family:Calibri;
+		mso-hansi-theme-font:minor-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:minor-bidi;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;}
+	.MsoPapDefault
+	{mso-style-type:export-only;
+		margin-bottom:8.0pt;
+		line-height:107%;}
+	@page WordSection1
+	{size:612.0pt 792.0pt;
+		margin:72.0pt 72.0pt 72.0pt 72.0pt;
+		mso-header-margin:36.0pt;
+		mso-footer-margin:36.0pt;
+		mso-paper-source:0;}
+	div.WordSection1
+	{page:WordSection1;}
+	/* List Definitions */
+	@list l0
+	{mso-list-id:805243082;
+		mso-list-type:hybrid;
+		mso-list-template-ids:-1568012680 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;}
+	@list l0:level1
+	{mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l0:level2
+	{mso-level-number-format:alpha-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l0:level3
+	{mso-level-number-format:roman-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:right;
+		text-indent:-9.0pt;}
+	@list l0:level4
+	{mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l0:level5
+	{mso-level-number-format:alpha-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l0:level6
+	{mso-level-number-format:roman-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:right;
+		text-indent:-9.0pt;}
+	@list l0:level7
+	{mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l0:level8
+	{mso-level-number-format:alpha-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l0:level9
+	{mso-level-number-format:roman-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:right;
+		text-indent:-9.0pt;}
+
+	-->
+</style></head><h1 style="margin-left:36.0pt;text-indent:-18.0pt;mso-list:l0 level1 lfo1"><!--[if !supportLists]--><span style="mso-fareast-font-family:&quot;Calibri Light&quot;;mso-fareast-theme-font:major-latin;
+mso-bidi-font-family:&quot;Calibri Light&quot;;mso-bidi-theme-font:major-latin;
+mso-ansi-language:PL"><span style="mso-list:Ignore">1.<span style="font:7.0pt &quot;Times New Roman&quot;">  </span></span></span><!--[endif]--><span>H1 1<o:p></o:p></span></h1><h1 style="margin-left:36.0pt;text-indent:-18.0pt;mso-list:l0 level1 lfo1"><!--[if !supportLists]--><span style="mso-fareast-font-family:&quot;Calibri Light&quot;;mso-fareast-theme-font:major-latin;
+mso-bidi-font-family:&quot;Calibri Light&quot;;mso-bidi-theme-font:major-latin;
+mso-ansi-language:PL"><span style="mso-list:Ignore">2.<span style="font:7.0pt &quot;Times New Roman&quot;">  </span></span></span><!--[endif]--><span>H1 2<o:p></o:p></span></h1></html>

+ 2 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/heading1/model.word2016.html

@@ -0,0 +1,2 @@
+<listItem listIndent="0" listType="numbered">H1 1</listItem>
+<listItem listIndent="0" listType="numbered">H1 2</listItem>

+ 15 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/heading1/normalized.safari.word2016.html

@@ -0,0 +1,15 @@
+<ol>
+	<li style="margin-left:36.0pt;text-indent:-18.0pt;mso-list:l0 level1 lfo1">
+		<!--[if !supportLists]--><span style="mso-fareast-font-family:&quot;Calibri Light&quot;;mso-fareast-theme-font:major-latin;
+	mso-bidi-font-family:&quot;Calibri Light&quot;;mso-bidi-theme-font:major-latin;
+	mso-ansi-language:PL"></span><!--[endif]-->
+		<span>H1 1<o:p></o:p></span>
+	</li>
+
+	<li style="margin-left:36.0pt;text-indent:-18.0pt;mso-list:l0 level1 lfo1">
+		<!--[if !supportLists]--><span style="mso-fareast-font-family:&quot;Calibri Light&quot;;mso-fareast-theme-font:major-latin;
+	mso-bidi-font-family:&quot;Calibri Light&quot;;mso-bidi-theme-font:major-latin;
+	mso-ansi-language:PL"></span><!--[endif]-->
+		<span>H1 2<o:p></o:p></span>
+	</li>
+</ol>

+ 180 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/heading3-styled/input.safari.word2016.html

@@ -0,0 +1,180 @@
+<html xmlns:o="urn:schemas-microsoft-com:office:office"
+	  xmlns:w="urn:schemas-microsoft-com:office:word"
+	  xmlns:m="http://schemas.microsoft.com/office/2004/12/omml"
+	  xmlns="http://www.w3.org/TR/REC-html40"><head><style class="WebKit-mso-list-quirks-style">
+	<!--
+	/* Style Definitions */
+	p.MsoNormal, li.MsoNormal, div.MsoNormal
+	{mso-style-unhide:no;
+		mso-style-qformat:yes;
+		mso-style-parent:"";
+		margin-top:0cm;
+		margin-right:0cm;
+		margin-bottom:8.0pt;
+		margin-left:0cm;
+		line-height:107%;
+		mso-pagination:widow-orphan;
+		font-size:11.0pt;
+		font-family:"Calibri",sans-serif;
+		mso-ascii-font-family:Calibri;
+		mso-ascii-theme-font:minor-latin;
+		mso-fareast-font-family:"Yu Mincho";
+		mso-fareast-theme-font:minor-fareast;
+		mso-hansi-font-family:Calibri;
+		mso-hansi-theme-font:minor-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:minor-bidi;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;}
+	h3
+	{mso-style-priority:9;
+		mso-style-qformat:yes;
+		mso-style-link:"Heading 3 Char";
+		mso-style-next:Normal;
+		margin-top:2.0pt;
+		margin-right:0cm;
+		margin-bottom:0cm;
+		margin-left:0cm;
+		margin-bottom:.0001pt;
+		line-height:107%;
+		mso-pagination:widow-orphan lines-together;
+		page-break-after:avoid;
+		mso-outline-level:3;
+		font-size:12.0pt;
+		font-family:"Calibri Light",sans-serif;
+		mso-ascii-font-family:"Calibri Light";
+		mso-ascii-theme-font:major-latin;
+		mso-fareast-font-family:"Yu Gothic Light";
+		mso-fareast-theme-font:major-fareast;
+		mso-hansi-font-family:"Calibri Light";
+		mso-hansi-theme-font:major-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:major-bidi;
+		color:#1F3763;
+		mso-themecolor:accent1;
+		mso-themeshade:127;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;
+		font-weight:normal;}
+	span.Heading3Char
+	{mso-style-name:"Heading 3 Char";
+		mso-style-priority:9;
+		mso-style-unhide:no;
+		mso-style-locked:yes;
+		mso-style-link:"Heading 3";
+		mso-ansi-font-size:12.0pt;
+		mso-bidi-font-size:12.0pt;
+		font-family:"Calibri Light",sans-serif;
+		mso-ascii-font-family:"Calibri Light";
+		mso-ascii-theme-font:major-latin;
+		mso-fareast-font-family:"Yu Gothic Light";
+		mso-fareast-theme-font:major-fareast;
+		mso-hansi-font-family:"Calibri Light";
+		mso-hansi-theme-font:major-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:major-bidi;
+		color:#1F3763;
+		mso-themecolor:accent1;
+		mso-themeshade:127;}
+	.MsoChpDefault
+	{mso-style-type:export-only;
+		mso-default-props:yes;
+		font-size:11.0pt;
+		mso-ansi-font-size:11.0pt;
+		mso-bidi-font-size:11.0pt;
+		font-family:"Calibri",sans-serif;
+		mso-ascii-font-family:Calibri;
+		mso-ascii-theme-font:minor-latin;
+		mso-fareast-font-family:"Yu Mincho";
+		mso-fareast-theme-font:minor-fareast;
+		mso-hansi-font-family:Calibri;
+		mso-hansi-theme-font:minor-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:minor-bidi;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;}
+	.MsoPapDefault
+	{mso-style-type:export-only;
+		margin-bottom:8.0pt;
+		line-height:107%;}
+	@page WordSection1
+	{size:612.0pt 792.0pt;
+		margin:72.0pt 72.0pt 72.0pt 72.0pt;
+		mso-header-margin:36.0pt;
+		mso-footer-margin:36.0pt;
+		mso-paper-source:0;}
+	div.WordSection1
+	{page:WordSection1;}
+	/* List Definitions */
+	@list l0
+	{mso-list-id:479226091;
+		mso-list-type:hybrid;
+		mso-list-template-ids:-1827736892 67698689 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
+	@list l0:level1
+	{mso-level-number-format:bullet;
+		mso-level-text:;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;
+		font-family:Symbol;}
+	@list l0:level2
+	{mso-level-number-format:bullet;
+		mso-level-text:o;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;
+		font-family:"Courier New";}
+	@list l0:level3
+	{mso-level-number-format:bullet;
+		mso-level-text:;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;
+		font-family:Wingdings;}
+	@list l0:level4
+	{mso-level-number-format:bullet;
+		mso-level-text:;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;
+		font-family:Symbol;}
+	@list l0:level5
+	{mso-level-number-format:bullet;
+		mso-level-text:o;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;
+		font-family:"Courier New";}
+	@list l0:level6
+	{mso-level-number-format:bullet;
+		mso-level-text:;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;
+		font-family:Wingdings;}
+	@list l0:level7
+	{mso-level-number-format:bullet;
+		mso-level-text:;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;
+		font-family:Symbol;}
+	@list l0:level8
+	{mso-level-number-format:bullet;
+		mso-level-text:o;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;
+		font-family:"Courier New";}
+	@list l0:level9
+	{mso-level-number-format:bullet;
+		mso-level-text:;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;
+		font-family:Wingdings;}
+
+	-->
+</style></head><h3 style="margin-left:36.0pt;text-indent:-18.0pt;mso-list:l0 level1 lfo1"><!--[if !supportLists]--><span style="font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family:
+Symbol;mso-ansi-language:PL"><span style="mso-list:Ignore">·<span style="font:7.0pt &quot;Times New Roman&quot;">     <span class="Apple-converted-space"> </span></span></span></span><!--[endif]--><span>H<b>2 1</b><o:p></o:p></span></h3><h3 style="margin-left:36.0pt;text-indent:-18.0pt;mso-list:l0 level1 lfo1"><!--[if !supportLists]--><span style="font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family:
+Symbol;mso-ansi-language:PL"><span style="mso-list:Ignore">·<span style="font:7.0pt &quot;Times New Roman&quot;">     <span class="Apple-converted-space"> </span></span></span></span><!--[endif]--><i><u><span>H</span></u></i><u><span>2</span></u><span>2<o:p></o:p></span></h3></html>

+ 5 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/heading3-styled/model.word2016.html

@@ -0,0 +1,5 @@
+<listItem listIndent="0" listType="bulleted">H<$text bold="true">2 1</$text></listItem>
+<listItem listIndent="0" listType="bulleted">
+	<$text italic="true" underline="true">H</$text>
+	<$text underline="true">2</$text> 2
+</listItem>

+ 13 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/heading3-styled/normalized.safari.word2016.html

@@ -0,0 +1,13 @@
+<ul>
+	<li style="margin-left:36.0pt;text-indent:-18.0pt;mso-list:l0 level1 lfo1">
+		<!--[if !supportLists]--><span style="font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family:
+	Symbol;mso-ansi-language:PL"></span><!--[endif]-->
+		<span>H<b>2 1</b><o:p></o:p></span>
+	</li>
+
+	<li style="margin-left:36.0pt;text-indent:-18.0pt;mso-list:l0 level1 lfo1">
+		<!--[if !supportLists]--><span style="font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family:
+	Symbol;mso-ansi-language:PL"></span><!--[endif]-->
+		<i><u><span>H</span></u></i><u><span>2</span></u><span>2<o:p></o:p></span>
+	</li>
+</ul>

+ 170 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/heading7/input.safari.word2016.html

@@ -0,0 +1,170 @@
+<html xmlns:o="urn:schemas-microsoft-com:office:office"
+	  xmlns:w="urn:schemas-microsoft-com:office:word"
+	  xmlns:m="http://schemas.microsoft.com/office/2004/12/omml"
+	  xmlns="http://www.w3.org/TR/REC-html40"><head><style class="WebKit-mso-list-quirks-style">
+	<!--
+	/* Style Definitions */
+	p.MsoNormal, li.MsoNormal, div.MsoNormal
+	{mso-style-unhide:no;
+		mso-style-qformat:yes;
+		mso-style-parent:"";
+		margin-top:0cm;
+		margin-right:0cm;
+		margin-bottom:8.0pt;
+		margin-left:0cm;
+		line-height:107%;
+		mso-pagination:widow-orphan;
+		font-size:11.0pt;
+		font-family:"Calibri",sans-serif;
+		mso-ascii-font-family:Calibri;
+		mso-ascii-theme-font:minor-latin;
+		mso-fareast-font-family:"Yu Mincho";
+		mso-fareast-theme-font:minor-fareast;
+		mso-hansi-font-family:Calibri;
+		mso-hansi-theme-font:minor-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:minor-bidi;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;}
+	p.MsoHeading7, li.MsoHeading7, div.MsoHeading7
+	{mso-style-priority:9;
+		mso-style-qformat:yes;
+		mso-style-link:"Heading 7 Char";
+		mso-style-next:Normal;
+		margin-top:2.0pt;
+		margin-right:0cm;
+		margin-bottom:0cm;
+		margin-left:0cm;
+		margin-bottom:.0001pt;
+		line-height:107%;
+		mso-pagination:widow-orphan lines-together;
+		page-break-after:avoid;
+		mso-outline-level:7;
+		font-size:11.0pt;
+		font-family:"Calibri Light",sans-serif;
+		mso-ascii-font-family:"Calibri Light";
+		mso-ascii-theme-font:major-latin;
+		mso-fareast-font-family:"Yu Gothic Light";
+		mso-fareast-theme-font:major-fareast;
+		mso-hansi-font-family:"Calibri Light";
+		mso-hansi-theme-font:major-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:major-bidi;
+		color:#1F3763;
+		mso-themecolor:accent1;
+		mso-themeshade:127;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;
+		font-style:italic;}
+	span.Heading7Char
+	{mso-style-name:"Heading 7 Char";
+		mso-style-priority:9;
+		mso-style-unhide:no;
+		mso-style-locked:yes;
+		mso-style-link:"Heading 7";
+		font-family:"Calibri Light",sans-serif;
+		mso-ascii-font-family:"Calibri Light";
+		mso-ascii-theme-font:major-latin;
+		mso-fareast-font-family:"Yu Gothic Light";
+		mso-fareast-theme-font:major-fareast;
+		mso-hansi-font-family:"Calibri Light";
+		mso-hansi-theme-font:major-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:major-bidi;
+		color:#1F3763;
+		mso-themecolor:accent1;
+		mso-themeshade:127;
+		font-style:italic;}
+	.MsoChpDefault
+	{mso-style-type:export-only;
+		mso-default-props:yes;
+		font-size:11.0pt;
+		mso-ansi-font-size:11.0pt;
+		mso-bidi-font-size:11.0pt;
+		font-family:"Calibri",sans-serif;
+		mso-ascii-font-family:Calibri;
+		mso-ascii-theme-font:minor-latin;
+		mso-fareast-font-family:"Yu Mincho";
+		mso-fareast-theme-font:minor-fareast;
+		mso-hansi-font-family:Calibri;
+		mso-hansi-theme-font:minor-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:minor-bidi;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;}
+	.MsoPapDefault
+	{mso-style-type:export-only;
+		margin-bottom:8.0pt;
+		line-height:107%;}
+	@page WordSection1
+	{size:612.0pt 792.0pt;
+		margin:72.0pt 72.0pt 72.0pt 72.0pt;
+		mso-header-margin:36.0pt;
+		mso-footer-margin:36.0pt;
+		mso-paper-source:0;}
+	div.WordSection1
+	{page:WordSection1;}
+	/* List Definitions */
+	@list l0
+	{mso-list-id:1763799148;
+		mso-list-template-ids:67698719;}
+	@list l0:level1
+	{mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		margin-left:18.0pt;
+		text-indent:-18.0pt;}
+	@list l0:level2
+	{mso-level-text:"%1\.%2\.";
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		margin-left:39.6pt;
+		text-indent:-21.6pt;}
+	@list l0:level3
+	{mso-level-text:"%1\.%2\.%3\.";
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		margin-left:61.2pt;
+		text-indent:-25.2pt;}
+	@list l0:level4
+	{mso-level-text:"%1\.%2\.%3\.%4\.";
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		margin-left:86.4pt;
+		text-indent:-32.4pt;}
+	@list l0:level5
+	{mso-level-text:"%1\.%2\.%3\.%4\.%5\.";
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		margin-left:111.6pt;
+		text-indent:-39.6pt;}
+	@list l0:level6
+	{mso-level-text:"%1\.%2\.%3\.%4\.%5\.%6\.";
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		margin-left:136.8pt;
+		text-indent:-46.8pt;}
+	@list l0:level7
+	{mso-level-text:"%1\.%2\.%3\.%4\.%5\.%6\.%7\.";
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		margin-left:162.0pt;
+		text-indent:-54.0pt;}
+	@list l0:level8
+	{mso-level-text:"%1\.%2\.%3\.%4\.%5\.%6\.%7\.%8\.";
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		margin-left:187.2pt;
+		text-indent:-61.2pt;}
+	@list l0:level9
+	{mso-level-text:"%1\.%2\.%3\.%4\.%5\.%6\.%7\.%8\.%9\.";
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		margin-left:216.0pt;
+		text-indent:-72.0pt;}
+
+	-->
+</style></head><p class="MsoHeading7" style="margin-left:18.0pt;text-indent:-18.0pt;mso-list:
+l0 level1 lfo1"><!--[if !supportLists]--><span style="mso-fareast-font-family:&quot;Calibri Light&quot;;
+mso-fareast-theme-font:major-latin;mso-bidi-font-family:&quot;Calibri Light&quot;;
+mso-bidi-theme-font:major-latin;mso-ansi-language:PL"><span style="mso-list:
+Ignore">1.<span style="font:7.0pt &quot;Times New Roman&quot;">    <span class="Apple-converted-space"> </span></span></span></span><!--[endif]--><span>H 7<o:p></o:p></span></p></html>

+ 1 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/heading7/model.word2016.html

@@ -0,0 +1 @@
+<listItem listIndent="0" listType="numbered">H 7</listItem>

+ 9 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/heading7/normalized.safari.word2016.html

@@ -0,0 +1,9 @@
+<ol>
+	<li class="MsoHeading7" style="margin-left:18.0pt;text-indent:-18.0pt;mso-list:
+	l0 level1 lfo1">
+		<!--[if !supportLists]--><span style="mso-fareast-font-family:&quot;Calibri Light&quot;;
+	mso-fareast-theme-font:major-latin;mso-bidi-font-family:&quot;Calibri Light&quot;;
+	mso-bidi-theme-font:major-latin;mso-ansi-language:PL"></span><!--[endif]-->
+		<span>H 7<o:p></o:p></span>
+	</li>
+</ol>

+ 121 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/index.js

@@ -0,0 +1,121 @@
+/**
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+// Default.
+import simple from './simple/input.word2016.html';
+import styled from './styled/input.word2016.html';
+import multiple from './multiple/input.word2016.html';
+import multipleCombined from './multiple-combined/input.word2016.html';
+import manyOneItem from './many-one-item/input.word2016.html';
+import heading1 from './heading1/input.word2016.html';
+import heading3Styled from './heading3-styled/input.word2016.html';
+import heading7 from './heading7/input.word2016.html';
+
+import simpleNormalized from './simple/normalized.word2016.html';
+import styledNormalized from './styled/normalized.word2016.html';
+import multipleNormalized from './multiple/normalized.word2016.html';
+import multipleCombinedNormalized from './multiple-combined/normalized.word2016.html';
+import manyOneItemNormalized from './many-one-item/normalized.word2016.html';
+import heading1Normalized from './heading1/normalized.word2016.html';
+import heading3StyledNormalized from './heading3-styled/normalized.word2016.html';
+import heading7Normalized from './heading7/normalized.word2016.html';
+
+import simpleModel from './simple/model.word2016.html';
+import styledModel from './styled/model.word2016.html';
+import multipleModel from './multiple/model.word2016.html';
+import multipleCombinedModel from './multiple-combined/model.word2016.html';
+import manyOneItemModel from './many-one-item/model.word2016.html';
+import heading1Model from './heading1/model.word2016.html';
+import heading3StyledModel from './heading3-styled/model.word2016.html';
+import heading7Model from './heading7/model.word2016.html';
+
+export const fixtures = {
+	input: {
+		simple,
+		styled,
+		multiple,
+		multipleCombined,
+		manyOneItem,
+		heading1,
+		heading3Styled,
+		heading7
+	},
+	normalized: {
+		simple: simpleNormalized,
+		styled: styledNormalized,
+		multiple: multipleNormalized,
+		multipleCombined: multipleCombinedNormalized,
+		manyOneItem: manyOneItemNormalized,
+		heading1: heading1Normalized,
+		heading3Styled: heading3StyledNormalized,
+		heading7: heading7Normalized
+	},
+	model: {
+		simple: simpleModel,
+		styled: styledModel,
+		multiple: multipleModel,
+		multipleCombined: multipleCombinedModel,
+		manyOneItem: manyOneItemModel,
+		heading1: heading1Model,
+		heading3Styled: heading3StyledModel,
+		heading7: heading7Model
+	}
+};
+
+// Safari.
+import simpleSafari from './simple/input.safari.word2016.html';
+import styledSafari from './styled/input.safari.word2016.html';
+import multipleSafari from './multiple/input.safari.word2016.html';
+import multipleCombinedSafari from './multiple-combined/input.safari.word2016.html';
+import manyOneItemSafari from './many-one-item/input.safari.word2016.html';
+import heading1Safari from './heading1/input.safari.word2016.html';
+import heading3StyledSafari from './heading3-styled/input.safari.word2016.html';
+import heading7Safari from './heading7/input.safari.word2016.html';
+
+import simpleNormalizedSafari from './simple/normalized.safari.word2016.html';
+import styledNormalizedSafari from './styled/normalized.safari.word2016.html';
+import multipleNormalizedSafari from './multiple/normalized.safari.word2016.html';
+import multipleCombinedNormalizedSafari from './multiple-combined/normalized.safari.word2016.html';
+import manyOneItemNormalizedSafari from './many-one-item/normalized.safari.word2016.html';
+import heading1NormalizedSafari from './heading1/normalized.safari.word2016.html';
+import heading3StyledNormalizedSafari from './heading3-styled/normalized.safari.word2016.html';
+import heading7NormalizedSafari from './heading7/normalized.safari.word2016.html';
+
+import styledSafariModel from './styled/model.safari.word2016.html';
+
+export const browserFixtures = {
+	safari: {
+		input: {
+			simple: simpleSafari,
+			styled: styledSafari,
+			multiple: multipleSafari,
+			multipleCombined: multipleCombinedSafari,
+			manyOneItem: manyOneItemSafari,
+			heading1: heading1Safari,
+			heading3Styled: heading3StyledSafari,
+			heading7: heading7Safari
+		},
+		normalized: {
+			simple: simpleNormalizedSafari,
+			styled: styledNormalizedSafari,
+			multiple: multipleNormalizedSafari,
+			multipleCombined: multipleCombinedNormalizedSafari,
+			manyOneItem: manyOneItemNormalizedSafari,
+			heading1: heading1NormalizedSafari,
+			heading3Styled: heading3StyledNormalizedSafari,
+			heading7: heading7NormalizedSafari
+		},
+		model: {
+			simple: simpleModel,
+			styled: styledSafariModel,
+			multiple: multipleModel,
+			multipleCombined: multipleCombinedModel,
+			manyOneItem: manyOneItemModel,
+			heading1: heading1Model,
+			heading3Styled: heading3StyledModel,
+			heading7: heading7Model
+		}
+	}
+};

File diff suppressed because it is too large
+ 847 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/many-one-item/input.safari.word2016.html


+ 21 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/many-one-item/model.word2016.html

@@ -0,0 +1,21 @@
+<listItem listIndent="0" listType="numbered">A</listItem>
+<listItem listIndent="0" listType="numbered">B</listItem>
+<listItem listIndent="0" listType="numbered">C</listItem>
+<listItem listIndent="0" listType="numbered">D</listItem>
+<listItem listIndent="0" listType="numbered">E</listItem>
+<listItem listIndent="0" listType="numbered">F</listItem>
+<listItem listIndent="0" listType="numbered">G</listItem>
+
+<paragraph></paragraph>
+
+<listItem listIndent="0" listType="bulleted">H</listItem>
+<listItem listIndent="0" listType="bulleted">I</listItem>
+
+<paragraph></paragraph>
+
+<listItem listIndent="0" listType="bulleted">J</listItem>
+<listItem listIndent="0" listType="bulleted">k</listItem>
+
+<paragraph></paragraph>
+
+<listItem listIndent="0" listType="numbered">h1</listItem>

File diff suppressed because it is too large
+ 113 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/many-one-item/normalized.safari.word2016.html


+ 258 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/multiple-combined/input.safari.word2016.html

@@ -0,0 +1,258 @@
+<html xmlns:o="urn:schemas-microsoft-com:office:office"
+	  xmlns:w="urn:schemas-microsoft-com:office:word"
+	  xmlns:m="http://schemas.microsoft.com/office/2004/12/omml"
+	  xmlns="http://www.w3.org/TR/REC-html40"><head><style class="WebKit-mso-list-quirks-style">
+	<!--
+	/* Style Definitions */
+	p.MsoNormal, li.MsoNormal, div.MsoNormal
+	{mso-style-unhide:no;
+		mso-style-qformat:yes;
+		mso-style-parent:"";
+		margin-top:0cm;
+		margin-right:0cm;
+		margin-bottom:8.0pt;
+		margin-left:0cm;
+		line-height:107%;
+		mso-pagination:widow-orphan;
+		font-size:11.0pt;
+		font-family:"Calibri",sans-serif;
+		mso-ascii-font-family:Calibri;
+		mso-ascii-theme-font:minor-latin;
+		mso-fareast-font-family:"Yu Mincho";
+		mso-fareast-theme-font:minor-fareast;
+		mso-hansi-font-family:Calibri;
+		mso-hansi-theme-font:minor-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:minor-bidi;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;}
+	p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
+	{mso-style-priority:34;
+		mso-style-unhide:no;
+		mso-style-qformat:yes;
+		margin-top:0cm;
+		margin-right:0cm;
+		margin-bottom:8.0pt;
+		margin-left:36.0pt;
+		mso-add-space:auto;
+		line-height:107%;
+		mso-pagination:widow-orphan;
+		font-size:11.0pt;
+		font-family:"Calibri",sans-serif;
+		mso-ascii-font-family:Calibri;
+		mso-ascii-theme-font:minor-latin;
+		mso-fareast-font-family:"Yu Mincho";
+		mso-fareast-theme-font:minor-fareast;
+		mso-hansi-font-family:Calibri;
+		mso-hansi-theme-font:minor-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:minor-bidi;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;}
+	p.MsoListParagraphCxSpFirst, li.MsoListParagraphCxSpFirst, div.MsoListParagraphCxSpFirst
+	{mso-style-priority:34;
+		mso-style-unhide:no;
+		mso-style-qformat:yes;
+		mso-style-type:export-only;
+		margin-top:0cm;
+		margin-right:0cm;
+		margin-bottom:0cm;
+		margin-left:36.0pt;
+		margin-bottom:.0001pt;
+		mso-add-space:auto;
+		line-height:107%;
+		mso-pagination:widow-orphan;
+		font-size:11.0pt;
+		font-family:"Calibri",sans-serif;
+		mso-ascii-font-family:Calibri;
+		mso-ascii-theme-font:minor-latin;
+		mso-fareast-font-family:"Yu Mincho";
+		mso-fareast-theme-font:minor-fareast;
+		mso-hansi-font-family:Calibri;
+		mso-hansi-theme-font:minor-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:minor-bidi;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;}
+	p.MsoListParagraphCxSpMiddle, li.MsoListParagraphCxSpMiddle, div.MsoListParagraphCxSpMiddle
+	{mso-style-priority:34;
+		mso-style-unhide:no;
+		mso-style-qformat:yes;
+		mso-style-type:export-only;
+		margin-top:0cm;
+		margin-right:0cm;
+		margin-bottom:0cm;
+		margin-left:36.0pt;
+		margin-bottom:.0001pt;
+		mso-add-space:auto;
+		line-height:107%;
+		mso-pagination:widow-orphan;
+		font-size:11.0pt;
+		font-family:"Calibri",sans-serif;
+		mso-ascii-font-family:Calibri;
+		mso-ascii-theme-font:minor-latin;
+		mso-fareast-font-family:"Yu Mincho";
+		mso-fareast-theme-font:minor-fareast;
+		mso-hansi-font-family:Calibri;
+		mso-hansi-theme-font:minor-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:minor-bidi;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;}
+	p.MsoListParagraphCxSpLast, li.MsoListParagraphCxSpLast, div.MsoListParagraphCxSpLast
+	{mso-style-priority:34;
+		mso-style-unhide:no;
+		mso-style-qformat:yes;
+		mso-style-type:export-only;
+		margin-top:0cm;
+		margin-right:0cm;
+		margin-bottom:8.0pt;
+		margin-left:36.0pt;
+		mso-add-space:auto;
+		line-height:107%;
+		mso-pagination:widow-orphan;
+		font-size:11.0pt;
+		font-family:"Calibri",sans-serif;
+		mso-ascii-font-family:Calibri;
+		mso-ascii-theme-font:minor-latin;
+		mso-fareast-font-family:"Yu Mincho";
+		mso-fareast-theme-font:minor-fareast;
+		mso-hansi-font-family:Calibri;
+		mso-hansi-theme-font:minor-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:minor-bidi;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;}
+	.MsoChpDefault
+	{mso-style-type:export-only;
+		mso-default-props:yes;
+		font-size:11.0pt;
+		mso-ansi-font-size:11.0pt;
+		mso-bidi-font-size:11.0pt;
+		font-family:"Calibri",sans-serif;
+		mso-ascii-font-family:Calibri;
+		mso-ascii-theme-font:minor-latin;
+		mso-fareast-font-family:"Yu Mincho";
+		mso-fareast-theme-font:minor-fareast;
+		mso-hansi-font-family:Calibri;
+		mso-hansi-theme-font:minor-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:minor-bidi;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;}
+	.MsoPapDefault
+	{mso-style-type:export-only;
+		margin-bottom:8.0pt;
+		line-height:107%;}
+	@page WordSection1
+	{size:612.0pt 792.0pt;
+		margin:72.0pt 72.0pt 72.0pt 72.0pt;
+		mso-header-margin:36.0pt;
+		mso-footer-margin:36.0pt;
+		mso-paper-source:0;}
+	div.WordSection1
+	{page:WordSection1;}
+	/* List Definitions */
+	@list l0
+	{mso-list-id:164786957;
+		mso-list-type:hybrid;
+		mso-list-template-ids:-1315690950 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;}
+	@list l0:level1
+	{mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l0:level2
+	{mso-level-number-format:alpha-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l0:level3
+	{mso-level-number-format:roman-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:right;
+		text-indent:-9.0pt;}
+	@list l0:level4
+	{mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l0:level5
+	{mso-level-number-format:alpha-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l0:level6
+	{mso-level-number-format:roman-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:right;
+		text-indent:-9.0pt;}
+	@list l0:level7
+	{mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l0:level8
+	{mso-level-number-format:alpha-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l0:level9
+	{mso-level-number-format:roman-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:right;
+		text-indent:-9.0pt;}
+	@list l1
+	{mso-list-id:984899113;
+		mso-list-type:hybrid;
+		mso-list-template-ids:-846005604 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;}
+	@list l1:level1
+	{mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l1:level2
+	{mso-level-number-format:alpha-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l1:level3
+	{mso-level-number-format:roman-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:right;
+		text-indent:-9.0pt;}
+	@list l1:level4
+	{mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l1:level5
+	{mso-level-number-format:alpha-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l1:level6
+	{mso-level-number-format:roman-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:right;
+		text-indent:-9.0pt;}
+	@list l1:level7
+	{mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l1:level8
+	{mso-level-number-format:alpha-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l1:level9
+	{mso-level-number-format:roman-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:right;
+		text-indent:-9.0pt;}
+
+	-->
+</style></head><p class="MsoListParagraphCxSpFirst" style="text-indent:-18.0pt;mso-list:l1 level1 lfo1"><!--[if !supportLists]--><span style="mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;
+mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin;mso-ansi-language:
+PL"><span style="mso-list:Ignore">1.<span style="font:7.0pt &quot;Times New Roman&quot;">    </span></span></span><!--[endif]--><span>Item1<o:p></o:p></span></p><p class="MsoListParagraphCxSpMiddle" style="text-indent:-18.0pt;mso-list:l1 level1 lfo1"><!--[if !supportLists]--><span style="mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;
+mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin;mso-ansi-language:
+PL"><span style="mso-list:Ignore">2.<span style="font:7.0pt &quot;Times New Roman&quot;">    </span></span></span><!--[endif]--><span>Item 2<o:p></o:p></span></p><p class="MsoListParagraphCxSpMiddle" style="text-indent:-18.0pt;mso-list:l0 level1 lfo2"><!--[if !supportLists]--><span style="mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;
+mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin;mso-ansi-language:
+PL"><span style="mso-list:Ignore">1.<span style="font:7.0pt &quot;Times New Roman&quot;">    </span></span></span><!--[endif]--><span>Item 1<o:p></o:p></span></p><p class="MsoListParagraphCxSpLast" style="text-indent:-18.0pt;mso-list:l0 level1 lfo2"><!--[if !supportLists]--><span style="mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;
+mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin;mso-ansi-language:
+PL"><span style="mso-list:Ignore">2.<span style="font:7.0pt &quot;Times New Roman&quot;">    </span></span></span><!--[endif]--><span>Item2<o:p></o:p></span></p></html>

+ 4 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/multiple-combined/model.word2016.html

@@ -0,0 +1,4 @@
+<listItem listIndent="0" listType="numbered">Item1</listItem>
+<listItem listIndent="0" listType="numbered">Item 2</listItem>
+<listItem listIndent="0" listType="numbered">Item 1</listItem>
+<listItem listIndent="0" listType="numbered">Item2</listItem>

+ 31 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/multiple-combined/normalized.safari.word2016.html

@@ -0,0 +1,31 @@
+<ol>
+	<li class="MsoListParagraphCxSpFirst" style="text-indent:-18.0pt;mso-list:l1 level1 lfo1">
+		<!--[if !supportLists]--><span style="mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;
+	mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin;mso-ansi-language:
+	PL"></span><!--[endif]-->
+		<span>Item1<o:p></o:p></span>
+	</li>
+
+	<li class="MsoListParagraphCxSpMiddle" style="text-indent:-18.0pt;mso-list:l1 level1 lfo1">
+		<!--[if !supportLists]--><span style="mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;
+	mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin;mso-ansi-language:
+	PL"></span><!--[endif]-->
+		<span>Item 2<o:p></o:p></span>
+	</li>
+</ol>
+
+<ol>
+	<li class="MsoListParagraphCxSpMiddle" style="text-indent:-18.0pt;mso-list:l0 level1 lfo2">
+		<!--[if !supportLists]--><span style="mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;
+	mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin;mso-ansi-language:
+	PL"></span><!--[endif]-->
+		<span>Item 1<o:p></o:p></span>
+	</li>
+
+	<li class="MsoListParagraphCxSpLast" style="text-indent:-18.0pt;mso-list:l0 level1 lfo2">
+		<!--[if !supportLists]--><span style="mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;
+	mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin;mso-ansi-language:
+	PL"></span><!--[endif]-->
+		<span>Item2<o:p></o:p></span>
+	</li>
+</ol>

File diff suppressed because it is too large
+ 280 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/multiple/input.safari.word2016.html


+ 6 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/multiple/model.word2016.html

@@ -0,0 +1,6 @@
+<listItem listIndent="0" listType="numbered">Item1</listItem>
+<listItem listIndent="0" listType="numbered">Item 2</listItem>
+
+<paragraph>Some text</paragraph>
+
+<listItem listIndent="0" listType="bulleted">Bullet 1</listItem>

File diff suppressed because it is too large
+ 25 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/multiple/normalized.safari.word2016.html


+ 208 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/simple/input.safari.word2016.html

@@ -0,0 +1,208 @@
+<html xmlns:o="urn:schemas-microsoft-com:office:office"
+	  xmlns:w="urn:schemas-microsoft-com:office:word"
+	  xmlns:m="http://schemas.microsoft.com/office/2004/12/omml"
+	  xmlns="http://www.w3.org/TR/REC-html40"><head><style class="WebKit-mso-list-quirks-style">
+	<!--
+	/* Style Definitions */
+	p.MsoNormal, li.MsoNormal, div.MsoNormal
+	{mso-style-unhide:no;
+		mso-style-qformat:yes;
+		mso-style-parent:"";
+		margin-top:0cm;
+		margin-right:0cm;
+		margin-bottom:8.0pt;
+		margin-left:0cm;
+		line-height:107%;
+		mso-pagination:widow-orphan;
+		font-size:11.0pt;
+		font-family:"Calibri",sans-serif;
+		mso-ascii-font-family:Calibri;
+		mso-ascii-theme-font:minor-latin;
+		mso-fareast-font-family:"Yu Mincho";
+		mso-fareast-theme-font:minor-fareast;
+		mso-hansi-font-family:Calibri;
+		mso-hansi-theme-font:minor-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:minor-bidi;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;}
+	p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
+	{mso-style-priority:34;
+		mso-style-unhide:no;
+		mso-style-qformat:yes;
+		margin-top:0cm;
+		margin-right:0cm;
+		margin-bottom:8.0pt;
+		margin-left:36.0pt;
+		mso-add-space:auto;
+		line-height:107%;
+		mso-pagination:widow-orphan;
+		font-size:11.0pt;
+		font-family:"Calibri",sans-serif;
+		mso-ascii-font-family:Calibri;
+		mso-ascii-theme-font:minor-latin;
+		mso-fareast-font-family:"Yu Mincho";
+		mso-fareast-theme-font:minor-fareast;
+		mso-hansi-font-family:Calibri;
+		mso-hansi-theme-font:minor-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:minor-bidi;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;}
+	p.MsoListParagraphCxSpFirst, li.MsoListParagraphCxSpFirst, div.MsoListParagraphCxSpFirst
+	{mso-style-priority:34;
+		mso-style-unhide:no;
+		mso-style-qformat:yes;
+		mso-style-type:export-only;
+		margin-top:0cm;
+		margin-right:0cm;
+		margin-bottom:0cm;
+		margin-left:36.0pt;
+		margin-bottom:.0001pt;
+		mso-add-space:auto;
+		line-height:107%;
+		mso-pagination:widow-orphan;
+		font-size:11.0pt;
+		font-family:"Calibri",sans-serif;
+		mso-ascii-font-family:Calibri;
+		mso-ascii-theme-font:minor-latin;
+		mso-fareast-font-family:"Yu Mincho";
+		mso-fareast-theme-font:minor-fareast;
+		mso-hansi-font-family:Calibri;
+		mso-hansi-theme-font:minor-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:minor-bidi;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;}
+	p.MsoListParagraphCxSpMiddle, li.MsoListParagraphCxSpMiddle, div.MsoListParagraphCxSpMiddle
+	{mso-style-priority:34;
+		mso-style-unhide:no;
+		mso-style-qformat:yes;
+		mso-style-type:export-only;
+		margin-top:0cm;
+		margin-right:0cm;
+		margin-bottom:0cm;
+		margin-left:36.0pt;
+		margin-bottom:.0001pt;
+		mso-add-space:auto;
+		line-height:107%;
+		mso-pagination:widow-orphan;
+		font-size:11.0pt;
+		font-family:"Calibri",sans-serif;
+		mso-ascii-font-family:Calibri;
+		mso-ascii-theme-font:minor-latin;
+		mso-fareast-font-family:"Yu Mincho";
+		mso-fareast-theme-font:minor-fareast;
+		mso-hansi-font-family:Calibri;
+		mso-hansi-theme-font:minor-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:minor-bidi;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;}
+	p.MsoListParagraphCxSpLast, li.MsoListParagraphCxSpLast, div.MsoListParagraphCxSpLast
+	{mso-style-priority:34;
+		mso-style-unhide:no;
+		mso-style-qformat:yes;
+		mso-style-type:export-only;
+		margin-top:0cm;
+		margin-right:0cm;
+		margin-bottom:8.0pt;
+		margin-left:36.0pt;
+		mso-add-space:auto;
+		line-height:107%;
+		mso-pagination:widow-orphan;
+		font-size:11.0pt;
+		font-family:"Calibri",sans-serif;
+		mso-ascii-font-family:Calibri;
+		mso-ascii-theme-font:minor-latin;
+		mso-fareast-font-family:"Yu Mincho";
+		mso-fareast-theme-font:minor-fareast;
+		mso-hansi-font-family:Calibri;
+		mso-hansi-theme-font:minor-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:minor-bidi;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;}
+	.MsoChpDefault
+	{mso-style-type:export-only;
+		mso-default-props:yes;
+		font-size:11.0pt;
+		mso-ansi-font-size:11.0pt;
+		mso-bidi-font-size:11.0pt;
+		font-family:"Calibri",sans-serif;
+		mso-ascii-font-family:Calibri;
+		mso-ascii-theme-font:minor-latin;
+		mso-fareast-font-family:"Yu Mincho";
+		mso-fareast-theme-font:minor-fareast;
+		mso-hansi-font-family:Calibri;
+		mso-hansi-theme-font:minor-latin;
+		mso-bidi-font-family:"Times New Roman";
+		mso-bidi-theme-font:minor-bidi;
+		mso-ansi-language:EN-US;
+		mso-fareast-language:JA;}
+	.MsoPapDefault
+	{mso-style-type:export-only;
+		margin-bottom:8.0pt;
+		line-height:107%;}
+	@page WordSection1
+	{size:612.0pt 792.0pt;
+		margin:72.0pt 72.0pt 72.0pt 72.0pt;
+		mso-header-margin:36.0pt;
+		mso-footer-margin:36.0pt;
+		mso-paper-source:0;}
+	div.WordSection1
+	{page:WordSection1;}
+	/* List Definitions */
+	@list l0
+	{mso-list-id:984899113;
+		mso-list-type:hybrid;
+		mso-list-template-ids:-846005604 67698703 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;}
+	@list l0:level1
+	{mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l0:level2
+	{mso-level-number-format:alpha-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l0:level3
+	{mso-level-number-format:roman-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:right;
+		text-indent:-9.0pt;}
+	@list l0:level4
+	{mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l0:level5
+	{mso-level-number-format:alpha-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l0:level6
+	{mso-level-number-format:roman-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:right;
+		text-indent:-9.0pt;}
+	@list l0:level7
+	{mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l0:level8
+	{mso-level-number-format:alpha-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:left;
+		text-indent:-18.0pt;}
+	@list l0:level9
+	{mso-level-number-format:roman-lower;
+		mso-level-tab-stop:none;
+		mso-level-number-position:right;
+		text-indent:-9.0pt;}
+
+	-->
+</style></head><p class="MsoListParagraphCxSpFirst" style="text-indent:-18.0pt;mso-list:l0 level1 lfo1"><!--[if !supportLists]--><span style="mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;
+mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin;mso-ansi-language:
+PL"><span style="mso-list:Ignore">1.<span style="font:7.0pt &quot;Times New Roman&quot;">    </span></span></span><!--[endif]--><span>Item1<o:p></o:p></span></p><p class="MsoListParagraphCxSpLast" style="text-indent:-18.0pt;mso-list:l0 level1 lfo1"><!--[if !supportLists]--><span style="mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;
+mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin;mso-ansi-language:
+PL"><span style="mso-list:Ignore">2.<span style="font:7.0pt &quot;Times New Roman&quot;">    </span></span></span><!--[endif]--><span>Item 2<o:p></o:p></span></p></html>

+ 2 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/simple/model.word2016.html

@@ -0,0 +1,2 @@
+<listItem listIndent="0" listType="numbered">Item1</listItem>
+<listItem listIndent="0" listType="numbered">Item 2</listItem>

+ 15 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/simple/normalized.safari.word2016.html

@@ -0,0 +1,15 @@
+<ol>
+	<li class="MsoListParagraphCxSpFirst" style="text-indent:-18.0pt;mso-list:l0 level1 lfo1">
+		<!--[if !supportLists]--><span style="mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;
+	mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin;mso-ansi-language:
+	PL"></span><!--[endif]-->
+		<span>Item1<o:p></o:p></span>
+	</li>
+
+	<li class="MsoListParagraphCxSpLast" style="text-indent:-18.0pt;mso-list:l0 level1 lfo1">
+		<!--[if !supportLists]--><span style="mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;
+	mso-bidi-font-family:Calibri;mso-bidi-theme-font:minor-latin;mso-ansi-language:
+	PL"></span><!--[endif]-->
+		<span>Item 2<o:p></o:p></span>
+	</li>
+</ol>

File diff suppressed because it is too large
+ 245 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/styled/input.safari.word2016.html


+ 9 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/styled/model.safari.word2016.html

@@ -0,0 +1,9 @@
+<paragraph>List:</paragraph>
+
+<listItem listIndent="0" listType="bulleted">B<$text bold="true">old</$text></listItem>
+<listItem listIndent="0" listType="bulleted"><$text linkHref="https://cksource.com/" underline="true">Lin</$text>k</listItem>
+<listItem listIndent="0" listType="bulleted">
+	<$text italic="true">M</$text><$text bold="true" italic="true">ul</$text>
+<$text bold="true" italic="true" underline="true">tip</$text>
+<$text italic="true" underline="true">le</$text>
+</listItem>

+ 9 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/styled/model.word2016.html

@@ -0,0 +1,9 @@
+<paragraph>List:</paragraph>
+
+<listItem listIndent="0" listType="bulleted">B<$text bold="true">old</$text></listItem>
+<listItem listIndent="0" listType="bulleted"><$text linkHref="https://cksource.com">Lin</$text>k</listItem>
+<listItem listIndent="0" listType="bulleted">
+	<$text italic="true">M</$text><$text bold="true" italic="true">ul</$text>
+	<$text bold="true" italic="true" underline="true">tip</$text>
+	<$text italic="true" underline="true">le</$text>
+</listItem>

+ 23 - 0
packages/ckeditor5-paste-from-office/tests/_data/list/styled/normalized.safari.word2016.html

@@ -0,0 +1,23 @@
+<p class="MsoNormal" style="margin: 0cm 0cm 8pt; line-height: 15.693333625793457px; font-size: 11pt; font-family: Calibri, sans-serif; caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;">
+	<span>List:<o:p></o:p></span>
+</p>
+
+<ul>
+	<li class="MsoListParagraphCxSpFirst" style="text-indent:-18.0pt;mso-list:l0 level1 lfo1">
+		<!--[if !supportLists]--><span style="font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family:
+	Symbol;mso-ansi-language:PL"></span><!--[endif]-->
+		<span>B<b>old</b><o:p></o:p></span>
+	</li>
+
+	<li class="MsoListParagraphCxSpMiddle" style="text-indent:-18.0pt;mso-list:l0 level1 lfo1">
+		<!--[if !supportLists]--><span style="font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family:
+	Symbol;mso-ansi-language:PL"></span><!--[endif]-->
+		<span class="MsoHyperlink" style="color: rgb(5, 99, 193); text-decoration: underline;"><span><a href="https://cksource.com/" style="color: rgb(149, 79, 114); text-decoration: underline;">Lin</a></span></span><span>k<o:p></o:p></span>
+	</li>
+
+	<li class="MsoListParagraphCxSpLast" style="text-indent:-18.0pt;mso-list:l0 level1 lfo1">
+		<!--[if !supportLists]--><span style="font-family:Symbol;mso-fareast-font-family:Symbol;mso-bidi-font-family:
+	Symbol;mso-ansi-language:PL"></span><!--[endif]-->
+		<i><span>M<b>ul<u>tip</u></b><u>le</u><o:p></o:p></span></i>
+	</li>
+</ul>

+ 64 - 0
packages/ckeditor5-paste-from-office/tests/_data/spacing/index.js

@@ -0,0 +1,64 @@
+/**
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+// Default.
+import simple from './simple/input.word2016.html';
+import singleLine from './single-line/input.word2016.html';
+import multiLine from './multi-line/input.word2016.html';
+
+import simpleNormalized from './simple/normalized.word2016.html';
+import singleLineNormalized from './single-line/normalized.word2016.html';
+import multiLineNormalized from './multi-line/normalized.word2016.html';
+
+import simpleModel from './simple/model.word2016.html';
+import singleLineModel from './single-line/model.word2016.html';
+import multiLineModel from './multi-line/model.word2016.html';
+
+export const fixtures = {
+	input: {
+		simple,
+		singleLine,
+		multiLine
+	},
+	normalized: {
+		simple: simpleNormalized,
+		singleLine: singleLineNormalized,
+		multiLine: multiLineNormalized
+	},
+	model: {
+		simple: simpleModel,
+		singleLine: singleLineModel,
+		multiLine: multiLineModel
+	}
+};
+
+// Safari.
+import simpleSafari from './simple/input.safari.word2016.html';
+import singleLineSafari from './single-line/input.safari.word2016.html';
+import multiLineSafari from './multi-line/input.safari.word2016.html';
+
+import simpleNormalizedSafari from './simple/normalized.safari.word2016.html';
+import singleLineNormalizedSafari from './single-line/normalized.safari.word2016.html';
+import multiLineNormalizedSafari from './multi-line/normalized.safari.word2016.html';
+
+export const browserFixtures = {
+	safari: {
+		input: {
+			simple: simpleSafari,
+			singleLine: singleLineSafari,
+			multiLine: multiLineSafari
+		},
+		normalized: {
+			simple: simpleNormalizedSafari,
+			singleLine: singleLineNormalizedSafari,
+			multiLine: multiLineNormalizedSafari
+		},
+		model: {
+			simple: simpleModel,
+			singleLine: singleLineModel,
+			multiLine: multiLineModel
+		}
+	}
+};

File diff suppressed because it is too large
+ 4 - 0
packages/ckeditor5-paste-from-office/tests/_data/spacing/multi-line/input.safari.word2016.html


+ 3 - 0
packages/ckeditor5-paste-from-office/tests/_data/spacing/multi-line/model.word2016.html

@@ -0,0 +1,3 @@
+<paragraph>2Foo   3Bar4    </paragraph>
+<paragraph>03   </paragraph>
+<paragraph>  21 </paragraph>

+ 11 - 0
packages/ckeditor5-paste-from-office/tests/_data/spacing/multi-line/normalized.safari.word2016.html

@@ -0,0 +1,11 @@
+<p class="MsoNormal" style="margin: 0cm 0cm 8pt; line-height: 15.693333625793457px; font-size: 11pt; font-family: Calibri, sans-serif; caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; text-indent: 5.25pt;">
+	<span>2Foo &nbsp; 3Bar4 &nbsp; &nbsp;<o:p></o:p></span>
+</p>
+
+<p class="MsoNormal" style="margin: 0cm 0cm 8pt; line-height: 15.693333625793457px; font-size: 11pt; font-family: Calibri, sans-serif; caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; text-indent: 5.25pt;">
+	<span>03 &nbsp;&nbsp;<o:p></o:p></span>
+</p>
+
+<p class="MsoNormal" style="margin: 0cm 0cm 8pt; line-height: 15.693333625793457px; font-size: 11pt; font-family: Calibri, sans-serif; caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; text-indent: 5.25pt;">
+	<span>&nbsp; 21&nbsp;<o:p></o:p></span>
+</p>

File diff suppressed because it is too large
+ 4 - 0
packages/ckeditor5-paste-from-office/tests/_data/spacing/simple/input.safari.word2016.html


+ 1 - 0
packages/ckeditor5-paste-from-office/tests/_data/spacing/simple/model.word2016.html

@@ -0,0 +1 @@
+<paragraph>Foo Bar </paragraph>

+ 3 - 0
packages/ckeditor5-paste-from-office/tests/_data/spacing/simple/normalized.safari.word2016.html

@@ -0,0 +1,3 @@
+<p class="MsoNormal" style="margin: 0cm 0cm 8pt; line-height: 15.693333625793457px; font-size: 11pt; font-family: Calibri, sans-serif; caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;">
+	<span>Foo Bar&nbsp;<o:p></o:p></span>
+</p>

File diff suppressed because it is too large
+ 4 - 0
packages/ckeditor5-paste-from-office/tests/_data/spacing/single-line/input.safari.word2016.html


+ 1 - 0
packages/ckeditor5-paste-from-office/tests/_data/spacing/single-line/model.word2016.html

@@ -0,0 +1 @@
+<paragraph>  2Foo   3Bar4    </paragraph>

+ 3 - 0
packages/ckeditor5-paste-from-office/tests/_data/spacing/single-line/normalized.safari.word2016.html

@@ -0,0 +1,3 @@
+<p class="MsoNormal" style="margin: 0cm 0cm 8pt; line-height: 15.693333625793457px; font-size: 11pt; font-family: Calibri, sans-serif; caret-color: rgb(0, 0, 0); color: rgb(0, 0, 0); font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;">
+	<span>&nbsp; 2Foo &nbsp; 3Bar4 &nbsp; &nbsp;<o:p></o:p></span>
+</p>

+ 26 - 0
packages/ckeditor5-paste-from-office/tests/_utils/fixtures.js

@@ -0,0 +1,26 @@
+/**
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+// Import fixtures.
+import { fixtures as basicStyles, browserFixtures as basicStylesBrowser } from '../_data/basic-styles/index.js';
+import { fixtures as link, browserFixtures as linkBrowser } from '../_data/link/index.js';
+import { fixtures as list, browserFixtures as listBrowser } from '../_data/list/index.js';
+import { fixtures as spacing, browserFixtures as spacingBrowser } from '../_data/spacing/index.js';
+
+// Generic fixtures.
+export const fixtures = {
+	'basic-styles': basicStyles,
+	link,
+	list,
+	spacing
+};
+
+// Browser specific fixtures.
+export const browserFixtures = {
+	'basic-styles': basicStylesBrowser,
+	link: linkBrowser,
+	list: listBrowser,
+	spacing: spacingBrowser
+};

+ 245 - 59
packages/ckeditor5-paste-from-office/tests/_utils/utils.js

@@ -3,46 +3,21 @@
  * For licensing, see LICENSE.md.
  */
 
-import normalizeHtml from '@ckeditor/ckeditor5-utils/tests/_utils/normalizehtml';
+/* globals document */
 
-import { getData as getModelData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
-import { stringify, getData as getViewData } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';
+import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
+import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
 
-/**
- * Checks whether for a given editor instance pasting specific content (input) gives expected result (output).
- *
- * @param {module:core/editor/editor~Editor} editor
- * @param {String} input Data to paste.
- * @param {String} expectedModel Expected model.
- * @param {String} [expectedView=null] Expected view.
- */
-export function expectPaste( editor, input, expectedModel, expectedView = null ) {
-	pasteHtml( editor, input );
+import normalizeHtml from '@ckeditor/ckeditor5-utils/tests/_utils/normalizehtml';
+import { setData, stringify as stringifyModel } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
+import { stringify as stringifyView } from '@ckeditor/ckeditor5-engine/src/dev-utils/view';
 
-	expect( getModelData( editor.model ) ).to.equal( expectedModel );
-
-	if ( expectedView ) {
-		expect( getViewData( editor.editing.view ) ).to.equal( expectedView );
-	}
-}
-
-/**
- * Fires paste event on a given editor instance with a specific HTML data.
- *
- * @param {module:core/editor/editor~Editor} editor Editor instance on which paste event will be fired.
- * @param {String} html The HTML data with which paste event will be fired.
- */
-export function pasteHtml( editor, html ) {
-	editor.editing.view.document.fire( 'paste', {
-		dataTransfer: createDataTransfer( { 'text/html': html } ),
-		preventDefault() {}
-	} );
-}
+import { fixtures, browserFixtures } from './fixtures';
 
 /**
  * Mocks dataTransfer object which can be used for simulating paste.
  *
- * @param {Object} data Object containing "mime type - data" pairs.
+ * @param {Object} data Object containing 'mime type - data' pairs.
  * @returns {Object} DataTransfer mock object.
  */
 export function createDataTransfer( data ) {
@@ -54,40 +29,251 @@ export function createDataTransfer( data ) {
 }
 
 /**
- * Compares two HTML strings.
- *
- * This function is designed for comparing normalized data so expected input is preprocessed before comparing:
- *
- *		* Tabs on the lines beginning are removed.
- *		* Line breaks and empty lines are removed.
- *
- * The expected input should be prepared in the above in mind which means every element containing text nodes must start
- * and end in the same line. So expected input may be formatted like:
- *
- * 		<span lang=PL style='mso-ansi-language:PL'>	03<span style='mso-spacerun:yes'>   </span><o:p></o:p></span>
+ * Generates test groups based on provided parameters. Generated tests are specifically designed
+ * to test pasted content transformations.
  *
- * 	but not like:
+ * This function generates test groups based on available fixtures:
  *
- * 		<span lang=PL style='mso-ansi-language:PL'>
- * 			03<span style='mso-spacerun:yes'>   </span>
- * 			<o:p></o:p>
- * 		</span>
+ * 1. If only generic fixtures are available they will be used for all listed browsers and combined into one test group.
+ * 2. If there are browser-specific fixtures available they will be used for matching browser resulting in a separate
+ * test group. All unmatched browsers will use generic fixtures combined into one separate test group.
+ * 3. If some fixtures are marked to be skipped for a specific browser, the separate test group will be created for this browser.
  *
- * 	because tabulator preceding `03` text will be treated as formatting character and will be removed.
+ * @param {Object} config
+ * @param {String} config.type Type of tests to generate, could be 'normalization' or 'integration'.
+ * @param {String} config.input Name of the fixtures group. Usually stored in `/tests/_data/groupname/`.
+ * @param {Array.<String>} config.browsers List of all browsers for which to generate tests.
+ * @param {Object} [config.editorConfig] Editor config which is passed to editor `create()` method.
+ * @param {Object} [config.skip] List of fixtures for any browser to skip. The supported format is:
  *
- * @param {String} actual
- * @param {String} expected
+ *		{
+ *			browserName: [ fixtureName1, fixtureName2 ]
+ *		}
  */
-export function expectNormalized( actual, expected ) {
-	const expectedInlined = expected
+export function generateTests( config ) {
+	if ( [ 'normalization', 'integration' ].indexOf( config.type ) === -1 ) {
+		throw new Error( `Invalid tests type - \`config.type\`: '${ config.type }'.` );
+	}
+
+	if ( !config.input ) {
+		throw new Error( 'No `config.input` option provided.' );
+	}
+
+	if ( !config.browsers || !config.browsers.length ) {
+		throw new Error( 'No or empty `config.browsers` option provided.' );
+	}
+
+	const groups = groupFixturesByBrowsers( config.browsers, config.input, config.skip );
+	const generateSuiteFn = config.type === 'normalization' ? generateNormalizationTests : generateIntegrationTests;
+
+	describe( config.type, () => {
+		describe( config.input, () => {
+			const editorConfig = config.editorConfig || {};
+
+			for ( const group of Object.keys( groups ) ) {
+				const skip = config.skip && config.skip[ group ] ? config.skip[ group ] : [];
+
+				if ( groups[ group ] ) {
+					generateSuiteFn( group, groups[ group ], editorConfig, skip );
+				}
+			}
+		} );
+	} );
+}
+
+// Creates browser groups combining all browsers using same fixtures. Each browser which have
+// some fixtures marked to be skipped automatically create separate groups.
+//
+// @param {Array.<String>} browsers List of all browsers for which fixture groups will be created.
+// @param {String} fixturesGroup Fixtures group name.
+// @returns {Object} Object containing browsers groups where key is the name of the group and value is fixtures object:
+//
+//		{
+// 			'safari': { ... }
+//			'edge': { ... }
+//			'chrome, firefox': { ... }
+// 		}
+function groupFixturesByBrowsers( browsers, fixturesGroup, skipBrowsers ) {
+	const browsersGroups = {};
+	const browsersGeneric = browsers.slice( 0 );
+
+	// Create separate groups for browsers with browser-specific fixtures available.
+	for ( const browser of browsers ) {
+		if ( browserFixtures[ fixturesGroup ] && browserFixtures[ fixturesGroup ][ browser ] ) {
+			browsersGroups[ browser ] = browserFixtures[ fixturesGroup ][ browser ];
+			browsersGeneric.splice( browsersGeneric.indexOf( browser ), 1 );
+		}
+	}
+
+	// Create separate groups for browsers with skipped tests.
+	if ( skipBrowsers ) {
+		for ( const browser of Object.keys( skipBrowsers ) ) {
+			if ( browsersGeneric.indexOf( browser ) !== -1 ) {
+				browsersGroups[ browser ] = fixtures[ fixturesGroup ] ? fixtures[ fixturesGroup ] : null;
+				browsersGeneric.splice( browsersGeneric.indexOf( browser ), 1 );
+			}
+		}
+	}
+
+	// Use generic fixtures (if available) for browsers left.
+	if ( browsersGeneric.length ) {
+		browsersGroups[ browsersGeneric.join( ', ' ) ] = fixtures[ fixturesGroup ] ? fixtures[ fixturesGroup ] : null;
+	}
+
+	return browsersGroups;
+}
+
+// Generates normalization tests based on a provided fixtures. For each input fixture one test is generated.
+//
+// @param {String} title Tests group title.
+// @param {Object} fixtures Object containing fixtures.
+// @param {Object} editorConfig Editor config with which test editor will be created.
+// @param {Array.<String>} skip Array of fixtures names which tests should be skipped.
+function generateNormalizationTests( title, fixtures, editorConfig, skip ) {
+	describe( title, () => {
+		let editor, pasteFromOfficePlugin;
+
+		beforeEach( () => {
+			return VirtualTestEditor
+				.create( editorConfig )
+				.then( newEditor => {
+					editor = newEditor;
+
+					pasteFromOfficePlugin = editor.plugins.get( 'PasteFromOffice' );
+				} );
+		} );
+
+		for ( const name of Object.keys( fixtures.input ) ) {
+			( skip.indexOf( name ) !== -1 ? it.skip : it )( name, () => {
+				expectNormalized(
+					pasteFromOfficePlugin._normalizeWordInput( fixtures.input[ name ], editor ),
+					fixtures.normalized[ name ]
+				);
+			} );
+		}
+	} );
+}
+
+// Generates integration tests based on a provided fixtures. For each input fixture one test is generated.
+//
+// @param {String} title Tests group title.
+// @param {Object} fixtures Object containing fixtures.
+// @param {Object} editorConfig Editor config with which test editor will be created.
+// @param {Array.<String>} skip Array of fixtures names which tests should be skipped.
+function generateIntegrationTests( title, fixtures, editorConfig, skip ) {
+	describe( title, () => {
+		let element, editor;
+
+		before( () => {
+			element = document.createElement( 'div' );
+
+			document.body.appendChild( element );
+
+			return ClassicTestEditor
+				.create( element, editorConfig )
+				.then( editorInstance => {
+					editor = editorInstance;
+				} );
+		} );
+
+		beforeEach( () => {
+			setData( editor.model, '<paragraph>[]</paragraph>' );
+		} );
+
+		after( () => {
+			editor.destroy();
+
+			element.remove();
+		} );
+
+		for ( const name of Object.keys( fixtures.input ) ) {
+			( skip.indexOf( name ) !== -1 ? it.skip : it )( name, () => {
+				expectModel( editor, fixtures.input[ name ], fixtures.model[ name ] );
+			} );
+		}
+	} );
+}
+
+// Checks if provided view element instance equals expected HTML. The element is stringified
+// by before comparing so its entire structure can be compared.
+//
+// This function is designed for comparing normalized data so expected input is preprocessed before comparing:
+//
+//		* Tabs on the lines beginnings are removed.
+//		* Line breaks and empty lines are removed.
+//
+// The expected input should be prepared in the above in mind which means every element containing text nodes must start
+// and end in the same line. So expected input may be formatted like:
+//
+// 		<span lang=PL style='mso-ansi-language:PL'>	03<span style='mso-spacerun:yes'>   </span><o:p></o:p></span>
+//
+// 	but not like:
+//
+// 		<span lang=PL style='mso-ansi-language:PL'>
+// 			03<span style='mso-spacerun:yes'>   </span>
+// 			<o:p></o:p>
+// 		</span>
+//
+// 	because tab preceding `03` text will be treated as formatting character and will be removed.
+//
+// @param {module:engine/view/text~Text|module:engine/view/element~Element|module:engine/view/documentfragment~DocumentFragment}
+// actual Actual HTML.
+// @param {String} expected Expected HTML.
+function expectNormalized( actual, expected ) {
+	const expectedInlined = inlineData( expected );
+
+	// We are ok with both spaces and non-breaking spaces in the actual content.
+	// Replace `&nbsp;` with regular spaces to align with expected content.
+	const actualNormalized = stringifyView( actual ).replace( /\u00A0/g, ' ' );
+
+	expect( actualNormalized ).to.equal( normalizeHtml( expectedInlined ) );
+}
+
+// Compares two models string representations. The input HTML is processed through paste
+// pipeline where it is transformed into model. This function hooks into {@link module:engine/model/model~Model#insertContent}
+// to get the model representation before it is inserted.
+//
+// @param {module:core/editor/editor~Editor} editor Editor instance.
+// @param {String} input Input HTML which will be pasted into the editor.
+// @param {String} expected Expected model.
+function expectModel( editor, input, expected ) {
+	const editorModel = editor.model;
+	const insertContent = editorModel.insertContent;
+
+	let actual = '';
+
+	sinon.stub( editorModel, 'insertContent' ).callsFake( ( content, selection ) => {
+		// Save model string representation now as it may change after `insertContent()` function call
+		// so accessing it later may not work as it may have emptied/changed structure.
+		actual = stringifyModel( content );
+		insertContent.call( editorModel, content, selection );
+	} );
+
+	firePasteEvent( editor, input );
+
+	sinon.restore();
+
+	expect( actual ).to.equal( inlineData( expected ) );
+}
+
+// Inlines given HTML / model representation string by removing preceding tabs and line breaks.
+//
+// @param {String} data Data to be inlined.
+function inlineData( data ) {
+	return data
 		// Replace tabs on the lines beginning as normalized input files are formatted.
 		.replace( /^\t*</gm, '<' )
 		// Replace line breaks (after closing tags) too.
 		.replace( /[\r\n]/gm, '' );
+}
 
-	// We are ok with both spaces and non-breaking spaces in the actual content.
-	// Replace `&nbsp;` with regular spaces to align with expected content (where regular spaces are only used).
-	const actualNormalized = stringify( actual ).replace( /\u00A0/g, ' ' );
-
-	expect( actualNormalized ).to.equal( normalizeHtml( expectedInlined ) );
+// Fires paste event on a given editor instance with a specific HTML data.
+//
+// @param {module:core/editor/editor~Editor} editor Editor instance on which paste event will be fired.
+// @param {String} html The HTML data with which paste event will be fired.
+function firePasteEvent( editor, html ) {
+	editor.editing.view.document.fire( 'paste', {
+		dataTransfer: createDataTransfer( { 'text/html': html } ),
+		preventDefault() {}
+	} );
 }

+ 65 - 0
packages/ckeditor5-paste-from-office/tests/data/integration.js

@@ -0,0 +1,65 @@
+/**
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
+import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
+import ShiftEnter from '@ckeditor/ckeditor5-enter/src/shiftenter';
+import Heading from '@ckeditor/ckeditor5-heading/src/heading';
+import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
+import Underline from '@ckeditor/ckeditor5-basic-styles/src/underline';
+import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
+import Link from '@ckeditor/ckeditor5-link/src/link';
+import Strikethrough from '@ckeditor/ckeditor5-basic-styles/src/strikethrough';
+import List from '@ckeditor/ckeditor5-list/src/list';
+import PasteFromOffice from '../../src/pastefromoffice';
+
+import { generateTests } from '../_utils/utils';
+
+const browsers = [ 'chrome', 'firefox', 'safari', 'edge' ];
+
+generateTests( {
+	input: 'basic-styles',
+	type: 'integration',
+	browsers,
+	editorConfig: {
+		plugins: [ Clipboard, Paragraph, Heading, Bold, Italic, Underline, Strikethrough, PasteFromOffice ]
+	},
+	skip: {
+		safari: [ 'italicStartingText', 'multipleStylesSingleLine', 'multipleStylesMultiline' ] // Skip due to spacing issue (#13).
+	}
+} );
+
+generateTests( {
+	input: 'link',
+	type: 'integration',
+	browsers,
+	editorConfig: {
+		plugins: [ Clipboard, Paragraph, Heading, Bold, Link, ShiftEnter, PasteFromOffice ]
+	},
+	skip: {
+		safari: [ 'combined' ] // Skip due to spacing issue (#13).
+	}
+} );
+
+generateTests( {
+	input: 'list',
+	type: 'integration',
+	browsers,
+	editorConfig: {
+		plugins: [ Clipboard, Paragraph, Heading, Bold, Italic, Underline, Link, List, PasteFromOffice ]
+	},
+	skip: {
+		safari: [ 'heading3Styled' ] // Skip due to spacing issue (#13).
+	}
+} );
+
+generateTests( {
+	input: 'spacing',
+	type: 'integration',
+	browsers,
+	editorConfig: {
+		plugins: [ Clipboard, Paragraph, Bold, Italic, Underline, PasteFromOffice ]
+	}
+} );

+ 0 - 286
packages/ckeditor5-paste-from-office/tests/data/integration/basic-styles.js

@@ -1,286 +0,0 @@
-/**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* globals document */
-
-import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
-import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
-import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
-import Heading from '@ckeditor/ckeditor5-heading/src/heading';
-import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
-import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
-import Underline from '@ckeditor/ckeditor5-basic-styles/src/underline';
-import Strikethrough from '@ckeditor/ckeditor5-basic-styles/src/strikethrough';
-import PasteFromOffice from '../../../src/pastefromoffice';
-
-import { setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
-import { expectPaste } from '../../_utils/utils';
-
-import boldWithinText from '../../_data/basic-styles/bold-within-text/input.word2016.html';
-import italicStartingText from '../../_data/basic-styles/italic-starting-text/input.word2016.html';
-import underlinedText from '../../_data/basic-styles/underlined-text/input.word2016.html';
-import strikethroughEndingText from '../../_data/basic-styles/strikethrough-ending-text/input.word2016.html';
-import multipleStylesSingleLine from '../../_data/basic-styles/multiple-styles-single-line/input.word2016.html';
-import multipleStylesMultiline from '../../_data/basic-styles/multiple-styles-multiline/input.word2016.html';
-
-describe( 'Basic Styles – integration', () => {
-	let element, editor;
-
-	before( () => {
-		element = document.createElement( 'div' );
-
-		document.body.appendChild( element );
-
-		return ClassicTestEditor
-			.create( element, { plugins: [ Clipboard, Paragraph, Heading, Bold, Italic, Underline, Strikethrough, PasteFromOffice ] } )
-			.then( editorInstance => {
-				editor = editorInstance;
-			} );
-	} );
-
-	beforeEach( () => {
-		setData( editor.model, '<paragraph>[]</paragraph>' );
-	} );
-
-	after( () => {
-		editor.destroy();
-
-		element.remove();
-	} );
-
-	// Pastes: 'Some text <b>with bold</b>.'
-	// Input same for: Chrome, Firefox and Edge.
-	describe( 'bold within text', () => {
-		it( 'pastes in the empty editor', () => {
-			expectPaste( editor, boldWithinText, '<paragraph>Some text <$text bold="true">with bold</$text>.[]</paragraph>' );
-		} );
-
-		it( 'pastes in the paragraph', () => {
-			setData( editor.model, '<paragraph>More [] text</paragraph>' );
-
-			expectPaste( editor, boldWithinText, '<paragraph>More Some text <$text bold="true">with bold</$text>.[] text</paragraph>' );
-		} );
-
-		it( 'pastes in the different block context', () => {
-			setData( editor.model, '<heading1>More [] text</heading1>' );
-
-			expectPaste( editor, boldWithinText, '<heading1>More Some text <$text bold="true">with bold</$text>.[] text</heading1>' );
-		} );
-
-		it( 'pastes in the inline styling context', () => {
-			setData( editor.model, '<paragraph><$text italic="true">Ita[]lic</$text></paragraph>' );
-
-			expectPaste( editor, boldWithinText, '<paragraph><$text italic="true">Ita</$text>Some text ' +
-				'<$text bold="true">with bold</$text>.[]<$text italic="true">lic</$text></paragraph>' );
-		} );
-
-		it( 'pastes inside another bold element', () => {
-			setData( editor.model, '<paragraph><$text bold="true">Ita[]lic</$text></paragraph>' );
-
-			expectPaste( editor, boldWithinText, '<paragraph><$text bold="true">Ita</$text>Some text ' +
-				'<$text bold="true">with bold</$text>.[]<$text bold="true">lic</$text></paragraph>' );
-		} );
-	} );
-
-	// Pastes: '<i>Italic</i> text.'
-	// Input same for: Chrome, Firefox and Edge.
-	describe( 'italic starting text', () => {
-		it( 'pastes in the empty editor', () => {
-			expectPaste( editor, italicStartingText, '<paragraph><$text italic="true">Italic</$text> text.[]</paragraph>' );
-		} );
-
-		it( 'pastes in the paragraph', () => {
-			setData( editor.model, '<paragraph>More [] text</paragraph>' );
-
-			expectPaste( editor, italicStartingText, '<paragraph>More <$text italic="true">Italic</$text> text.[] text</paragraph>' );
-		} );
-
-		it( 'pastes in the different block context', () => {
-			setData( editor.model, '<heading1>More [] text</heading1>' );
-
-			expectPaste( editor, italicStartingText, '<heading1>More <$text italic="true">Italic</$text> text.[] text</heading1>' );
-		} );
-
-		it( 'pastes in the inline styling context', () => {
-			setData( editor.model, '<paragraph><$text bold="true">Bol[]d</$text></paragraph>' );
-
-			expectPaste( editor, italicStartingText, '<paragraph><$text bold="true">Bol</$text><$text italic="true">' +
-				'Italic</$text> text.[]<$text bold="true">d</$text></paragraph>' );
-		} );
-
-		it( 'pastes inside another italic element', () => {
-			setData( editor.model, '<paragraph><$text italic="true">Italic[]</$text></paragraph>' );
-
-			expectPaste( editor, italicStartingText, '<paragraph><$text italic="true">ItalicItalic</$text> text.[]</paragraph>' );
-		} );
-	} );
-
-	// Pastes: '<u>Whole text underlined</u>'
-	// Input same for: Chrome, Firefox and Edge.
-	describe( 'underlined text', () => {
-		it( 'pastes in the empty editor', () => {
-			expectPaste( editor, underlinedText, '<paragraph><$text underline="true">Whole text underlined[]</$text></paragraph>' );
-		} );
-
-		it( 'pastes in the paragraph', () => {
-			setData( editor.model, '<paragraph>More [] text</paragraph>' );
-
-			expectPaste( editor, underlinedText, '<paragraph>More <$text underline="true">Whole text underlined[]' +
-				'</$text> text</paragraph>' );
-		} );
-
-		it( 'pastes in the different block context', () => {
-			setData( editor.model, '<heading1>More [] text</heading1>' );
-
-			expectPaste( editor, underlinedText, '<heading1>More <$text underline="true">Whole text underlined[]</$text> text</heading1>' );
-		} );
-
-		it( 'pastes in the inline styling context', () => {
-			setData( editor.model, '<paragraph><$text bold="true">Bol[]d</$text></paragraph>' );
-
-			expectPaste( editor, underlinedText, '<paragraph><$text bold="true">Bol</$text><$text underline="true">' +
-				'Whole text underlined[]</$text><$text bold="true">d</$text></paragraph>' );
-		} );
-
-		it( 'pastes inside another underlined element', () => {
-			setData( editor.model, '<paragraph><$text underline="true">Under []line</$text></paragraph>' );
-
-			expectPaste( editor, underlinedText, '<paragraph><$text underline="true">Under Whole text underlined[]' +
-				'line</$text></paragraph>' );
-		} );
-	} );
-
-	// Pastes: 'Text <s>incorrect</s>'
-	// Input same for: Chrome, Firefox and Edge.
-	describe( 'strikethrough ending text', () => {
-		it( 'pastes in the empty editor', () => {
-			expectPaste( editor, strikethroughEndingText, '<paragraph>Text <$text strikethrough="true">incorrect[]</$text></paragraph>' );
-		} );
-
-		it( 'pastes in the paragraph', () => {
-			setData( editor.model, '<paragraph>More [] text</paragraph>' );
-
-			expectPaste( editor, strikethroughEndingText, '<paragraph>More Text <$text strikethrough="true">incorrect[]' +
-				'</$text> text</paragraph>' );
-		} );
-
-		it( 'pastes in the different block context', () => {
-			setData( editor.model, '<heading1>More [] text</heading1>' );
-
-			expectPaste( editor, strikethroughEndingText, '<heading1>More Text <$text strikethrough="true">incorrect[]' +
-				'</$text> text</heading1>' );
-		} );
-
-		it( 'pastes in the inline styling context', () => {
-			setData( editor.model, '<paragraph><$text bold="true">Bol[]d</$text></paragraph>' );
-
-			expectPaste( editor, strikethroughEndingText, '<paragraph><$text bold="true">Bol</$text>' +
-				'Text <$text strikethrough="true">incorrect[]</$text><$text bold="true">d</$text></paragraph>' );
-		} );
-
-		it( 'pastes inside another strikethrough element', () => {
-			setData( editor.model, '<paragraph><$text strikethrough="true">[]Foo</$text></paragraph>' );
-
-			expectPaste( editor, strikethroughEndingText, '<paragraph>Text <$text strikethrough="true">incorrect[]Foo' +
-				'</$text></paragraph>' );
-		} );
-	} );
-
-	// Pastes: 'Text <b><u>containi<s>ng</s></u></b><s><u> multi</u>ple</s><i>styling</i>.'
-	// Input same for: Chrome, Firefox and Edge.
-	describe( 'mulitple styles single line', () => {
-		it( 'pastes in the empty editor', () => {
-			expectPaste( editor, multipleStylesSingleLine, '<paragraph>Text ' +
-				'<$text bold="true" underline="true">containi</$text>' +
-				'<$text bold="true" strikethrough="true" underline="true">ng</$text>' +
-				'<$text strikethrough="true" underline="true"> multi</$text>' +
-				'<$text strikethrough="true">ple </$text>' +
-				'<$text italic="true">styling</$text>.[]</paragraph>' );
-		} );
-
-		it( 'pastes in the paragraph', () => {
-			setData( editor.model, '<paragraph>More [] text</paragraph>' );
-
-			expectPaste( editor, multipleStylesSingleLine, '<paragraph>More Text ' +
-				'<$text bold="true" underline="true">containi</$text>' +
-				'<$text bold="true" strikethrough="true" underline="true">ng</$text>' +
-				'<$text strikethrough="true" underline="true"> multi</$text>' +
-				'<$text strikethrough="true">ple </$text>' +
-				'<$text italic="true">styling</$text>.[] text</paragraph>' );
-		} );
-
-		it( 'pastes in the different block context', () => {
-			setData( editor.model, '<heading1>More [] text</heading1>' );
-
-			expectPaste( editor, multipleStylesSingleLine, '<heading1>More Text ' +
-				'<$text bold="true" underline="true">containi</$text>' +
-				'<$text bold="true" strikethrough="true" underline="true">ng</$text>' +
-				'<$text strikethrough="true" underline="true"> multi</$text>' +
-				'<$text strikethrough="true">ple </$text>' +
-				'<$text italic="true">styling</$text>.[] text</heading1>' );
-		} );
-
-		it( 'pastes in the inline styling context', () => {
-			setData( editor.model, '<paragraph><$text bold="true">Bol[]d</$text></paragraph>' );
-
-			expectPaste( editor, multipleStylesSingleLine, '<paragraph><$text bold="true">Bol</$text>Text ' +
-				'<$text bold="true" underline="true">containi</$text>' +
-				'<$text bold="true" strikethrough="true" underline="true">ng</$text>' +
-				'<$text strikethrough="true" underline="true"> multi</$text>' +
-				'<$text strikethrough="true">ple </$text>' +
-				'<$text italic="true">styling</$text>.[]' +
-				'<$text bold="true">d</$text></paragraph>' );
-		} );
-	} );
-
-	// Pastes:
-	//		<p>Line <b>bold</b> and <i>italics</i></p>
-	//		<p>Line <b><u>foo</u></b><u> bar</u></p>
-	//		<p><s>Third</s> line <b>styling, <i>space on e</i>nd </b></p>
-	// Input same for: Chrome, Firefox and Edge.
-	describe( 'mulitple styles multiline', () => {
-		it.skip( 'pastes in the empty editor', () => {
-			expectPaste( editor, multipleStylesMultiline, '<paragraph>Line ' +
-				'<$text bold="true">bold</$text> and <$text italic="true">italics</$text></paragraph>' +
-				'<paragraph>Line <$text bold="true" underline="true">foo</$text><$text underline="true"> bar</$text></paragraph>' +
-				'<paragraph><$text strikethrough="true">Third</$text> line <$text bold="true">styling, </$text>' +
-				'<$text bold="true" italic="true">space on e</$text>' +
-				'<$text bold="true">nd []</$text></paragraph>' ); // The last space '...nd </b></p>' goes missing.
-		} );
-
-		it.skip( 'pastes in the paragraph', () => {
-			setData( editor.model, '<paragraph>More [] text</paragraph>' );
-
-			expectPaste( editor, multipleStylesMultiline, '<paragraph>More Line ' +
-				'<$text bold="true">bold</$text> and <$text italic="true">italics</$text></paragraph>' +
-				'<paragraph>Line <$text bold="true" underline="true">foo</$text><$text underline="true"> bar</$text></paragraph>' +
-				'<paragraph><$text strikethrough="true">Third</$text> line <$text bold="true">styling, </$text>' +
-				'<$text bold="true" italic="true">space on e</$text>' +
-				'<$text bold="true">nd []</$text> text</paragraph>' ); // The last space '...nd </b></p>' goes missing.
-		} );
-
-		it.skip( 'pastes in the different block context', () => {
-			setData( editor.model, '<heading1>More [] text</heading1>' );
-
-			expectPaste( editor, multipleStylesMultiline, '<heading1>More Line ' +
-				'<$text bold="true">bold</$text> and <$text italic="true">italics</$text></heading1>' +
-				'<paragraph>Line <$text bold="true" underline="true">foo</$text><$text underline="true"> bar</$text></paragraph>' +
-				'<paragraph><$text strikethrough="true">Third</$text> line <$text bold="true">styling, </$text>' +
-				'<$text bold="true" italic="true">space on e</$text>' +
-				'<$text bold="true">nd []</$text> text</paragraph>' ); // The last space '...nd </b></p>' goes missing.
-		} );
-
-		it.skip( 'pastes in the inline styling context', () => {
-			setData( editor.model, '<paragraph><$text bold="true">Bol[]d</$text></paragraph>' );
-
-			expectPaste( editor, multipleStylesMultiline, '<paragraph><$text bold="true">Bol</$text>Line ' +
-				'<$text bold="true">bold</$text> and <$text italic="true">italics</$text></paragraph>' +
-				'<paragraph>Line <$text bold="true" underline="true">foo</$text><$text underline="true"> bar</$text></paragraph>' +
-				'<paragraph><$text strikethrough="true">Third</$text> line <$text bold="true">styling, </$text>' +
-				'<$text bold="true" italic="true">space on e</$text>' +
-				'<$text bold="true">nd []d</$text></paragraph>' ); // The last space '...nd </b></p>' goes missing.
-		} );
-	} );
-} );

+ 0 - 166
packages/ckeditor5-paste-from-office/tests/data/integration/link.js

@@ -1,166 +0,0 @@
-/**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* globals document */
-
-import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
-import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
-import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
-import Heading from '@ckeditor/ckeditor5-heading/src/heading';
-import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
-import Link from '@ckeditor/ckeditor5-link/src/link';
-import ShiftEnter from '@ckeditor/ckeditor5-enter/src/shiftenter';
-
-import { setData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
-import { expectPaste } from '../../_utils/utils';
-
-import withinText from '../../_data/link/within-text/input.word2016.html';
-import combined from '../../_data/link/combined/input.word2016.html';
-import twoLine from '../../_data/link/two-line/input.word2016.html';
-
-describe( 'Link – integration', () => {
-	let element, editor;
-
-	before( () => {
-		element = document.createElement( 'div' );
-
-		document.body.appendChild( element );
-
-		return ClassicTestEditor
-			.create( element, { plugins: [ Clipboard, Paragraph, Heading, Bold, Link, ShiftEnter ] } )
-			.then( editorInstance => {
-				editor = editorInstance;
-			} );
-	} );
-
-	beforeEach( () => {
-		setData( editor.model, '<paragraph>[]</paragraph>' );
-	} );
-
-	after( () => {
-		editor.destroy();
-
-		element.remove();
-	} );
-
-	// Pastes: 'Regular <a href="https://ckeditor.com/">link</a>1'
-	// Input same for: Chrome, Firefox and Edge.
-	describe( 'within text', () => {
-		it( 'pastes in the empty editor', () => {
-			expectPaste( editor, withinText, '<paragraph>Regular ' +
-				'<$text linkHref="https://ckeditor.com/">link</$text>1[]</paragraph>' );
-		} );
-
-		it( 'pastes in the paragraph', () => {
-			setData( editor.model, '<paragraph>More [] text</paragraph>' );
-
-			expectPaste( editor, withinText, '<paragraph>More Regular ' +
-				'<$text linkHref="https://ckeditor.com/">link</$text>1[] text</paragraph>' );
-		} );
-
-		it( 'pastes in the different block context', () => {
-			setData( editor.model, '<heading1>More [] text</heading1>' );
-
-			expectPaste( editor, withinText, '<heading1>More Regular ' +
-				'<$text linkHref="https://ckeditor.com/">link</$text>1[] text</heading1>' );
-		} );
-
-		it( 'pastes in the inline styling context', () => {
-			setData( editor.model, '<paragraph><$text bold="true">Bo[]ld</$text></paragraph>' );
-
-			expectPaste( editor, withinText, '<paragraph><$text bold="true">Bo</$text>' +
-				'Regular <$text linkHref="https://ckeditor.com/">link</$text>1[]<$text bold="true">ld</$text></paragraph>' );
-		} );
-
-		it( 'pastes inside another link element', () => {
-			setData( editor.model, '<paragraph>1<$text linkHref="#test">tes[]t</$text>2</paragraph>' );
-
-			expectPaste( editor, withinText, '<paragraph>1<$text linkHref="#test">tes</$text>' +
-				'Regular <$text linkHref="https://ckeditor.com/">link</$text>1[]<$text linkHref="#test">t</$text>2</paragraph>' );
-		} );
-	} );
-
-	// Pastes: '<a href="https://ckeditor.com/">CKEditor</a><a href="https://cksource.com/">CKSource</a> 2'
-	// Input same for: Chrome, Firefox and Edge.
-	describe( 'combined', () => {
-		it( 'pastes in the empty editor', () => {
-			expectPaste( editor, combined, '<paragraph><$text linkHref="https://ckeditor.com/">CKEditor</$text>' +
-				'<$text linkHref="https://cksource.com/">CKSource</$text> 2[]</paragraph>' );
-		} );
-
-		it( 'pastes in the paragraph', () => {
-			setData( editor.model, '<paragraph>More [] text</paragraph>' );
-
-			expectPaste( editor, combined, '<paragraph>More <$text linkHref="https://ckeditor.com/">CKEditor</$text>' +
-				'<$text linkHref="https://cksource.com/">CKSource</$text> 2[] text</paragraph>' );
-		} );
-
-		it( 'pastes in the different block context', () => {
-			setData( editor.model, '<heading1>More [] text</heading1>' );
-
-			expectPaste( editor, combined, '<heading1>More <$text linkHref="https://ckeditor.com/">CKEditor</$text>' +
-				'<$text linkHref="https://cksource.com/">CKSource</$text> 2[] text</heading1>' );
-		} );
-
-		it( 'pastes in the inline styling context', () => {
-			setData( editor.model, '<paragraph><$text bold="true">Bo[]ld</$text></paragraph>' );
-
-			expectPaste( editor, combined, '<paragraph><$text bold="true">Bo</$text>' +
-				'<$text linkHref="https://ckeditor.com/">CKEditor</$text>' +
-				'<$text linkHref="https://cksource.com/">CKSource</$text> 2[]' +
-				'<$text bold="true">ld</$text></paragraph>' );
-		} );
-
-		it( 'pastes inside another link element', () => {
-			setData( editor.model, '<paragraph>1<$text linkHref="#test">tes[]t</$text>2</paragraph>' );
-
-			expectPaste( editor, combined, '<paragraph>1<$text linkHref="#test">tes</$text>' +
-				'<$text linkHref="https://ckeditor.com/">CKEditor</$text>' +
-				'<$text linkHref="https://cksource.com/">CKSource</$text> 2[]' +
-				'<$text linkHref="#test">t</$text>2</paragraph>' );
-		} );
-	} );
-
-	// Pastes: '<a href="https://cksource.com/">Long link <br> WITH spaces</a>'
-	// Input same for: Chrome, Firefox and Edge.
-	describe( 'two line', () => {
-		it( 'pastes in the empty editor', () => {
-			expectPaste( editor, twoLine, '<paragraph><$text linkHref="https://cksource.com/">Long link </$text><softBreak></softBreak>' +
-				'<$text linkHref="https://cksource.com/">WITH spaces[]</$text></paragraph>' );
-		} );
-
-		it( 'pastes in the paragraph', () => {
-			setData( editor.model, '<paragraph>More [] text</paragraph>' );
-
-			expectPaste( editor, twoLine, '<paragraph>More <$text linkHref="https://cksource.com/">Long link </$text>' +
-				'<softBreak></softBreak><$text linkHref="https://cksource.com/">WITH spaces[]</$text> text</paragraph>' );
-		} );
-
-		it( 'pastes in the different block context', () => {
-			setData( editor.model, '<heading1>More [] text</heading1>' );
-
-			expectPaste( editor, twoLine, '<heading1>More <$text linkHref="https://cksource.com/">Long link </$text>' +
-				'<softBreak></softBreak><$text linkHref="https://cksource.com/">WITH spaces[]</$text> text</heading1>' );
-		} );
-
-		it( 'pastes in the inline styling context', () => {
-			setData( editor.model, '<paragraph><$text bold="true">Bo[]ld</$text></paragraph>' );
-
-			expectPaste( editor, twoLine, '<paragraph><$text bold="true">Bo</$text>' +
-				'<$text linkHref="https://cksource.com/">Long link </$text>' +
-				'<softBreak></softBreak><$text linkHref="https://cksource.com/">WITH spaces[]</$text>' +
-				'<$text bold="true">ld</$text></paragraph>' );
-		} );
-
-		it( 'pastes inside another link element', () => {
-			setData( editor.model, '<paragraph>1<$text linkHref="#test">tes[]t</$text>2</paragraph>' );
-
-			expectPaste( editor, twoLine, '<paragraph>1<$text linkHref="#test">tes</$text>' +
-				'<$text linkHref="https://cksource.com/">Long link </$text>' +
-				'<softBreak></softBreak><$text linkHref="https://cksource.com/">WITH spaces[]</$text>' +
-				'<$text linkHref="#test">t</$text>2</paragraph>' );
-		} );
-	} );
-} );

+ 0 - 287
packages/ckeditor5-paste-from-office/tests/data/integration/list.js

@@ -1,287 +0,0 @@
-/**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* globals document */
-
-import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
-import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
-import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
-import Heading from '@ckeditor/ckeditor5-heading/src/heading';
-import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
-import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
-import Underline from '@ckeditor/ckeditor5-basic-styles/src/underline';
-import Link from '@ckeditor/ckeditor5-link/src/link';
-import List from '@ckeditor/ckeditor5-list/src/list';
-import PasteFromOffice from '../../../src/pastefromoffice';
-
-import { setData, stringify } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
-import { pasteHtml } from '../../_utils/utils';
-
-import simple from '../../_data/list/simple/input.word2016.html';
-import styled from '../../_data/list/styled/input.word2016.html';
-import multiple from '../../_data/list/multiple/input.word2016.html';
-import multipleCombined from '../../_data/list/multiple-combined/input.word2016.html';
-import manyOneItem from '../../_data/list/many-one-item/input.word2016.html';
-import heading1 from '../../_data/list/heading1/input.word2016.html';
-import heading3Styled from '../../_data/list/heading3-styled/input.word2016.html';
-import heading7 from '../../_data/list/heading7/input.word2016.html';
-
-describe( 'List – integration', () => {
-	let element, editor, insertedModel;
-
-	before( () => {
-		element = document.createElement( 'div' );
-
-		document.body.appendChild( element );
-
-		return ClassicTestEditor
-			.create( element, { plugins: [ Clipboard, Paragraph, Heading, Bold, Italic, Underline, Link, List, PasteFromOffice ] } )
-			.then( editorInstance => {
-				editor = editorInstance;
-
-				const model = editor.model;
-				const insertContent = model.insertContent;
-
-				sinon.stub( editor.model, 'insertContent' ).callsFake( ( content, selection ) => {
-					// Save model string representation now as it may change after `insertContent()` function call
-					// so accessing it later may not work as it may have empty/changed structure.
-					insertedModel = stringify( content );
-					insertContent.call( model, content, selection );
-				} );
-			} );
-	} );
-
-	beforeEach( () => {
-		setData( editor.model, '<paragraph>[]</paragraph>' );
-	} );
-
-	afterEach( () => {
-		insertedModel = null;
-	} );
-
-	after( () => {
-		sinon.restore();
-
-		editor.destroy();
-
-		element.remove();
-	} );
-
-	// Pastes (after cleaning up garbage markup):
-	//
-	//		<p><span>1.</span<span>Item1</span></p>
-	//		<p><span>2.</span>><span>Item 2</span></p>
-	//
-	// which should result in the same output as pasting:
-	//
-	//		<ol><li>Item1</li><li>Item2</li></ol>
-	it( 'pastes simple list', () => {
-		const expectedModel = '<listItem listIndent="0" listType="numbered">Item1</listItem>' +
-			'<listItem listIndent="0" listType="numbered">Item 2</listItem>';
-
-		expectContent( simple, expectedModel );
-	} );
-
-	// Pastes (after cleaning up garbage markup):
-	//
-	//		<p>List:</p>
-	//		<p><span>·</span><span>B<b>old</b></span></p>
-	//		<p><span>·</span><span><a href="https://cksource.com">Lin</a>k</span></p>
-	//		<p><span>·</span><span><i>M<b>ul<u>tip</u></b><u>le</u></span></i></p>
-	//
-	// which should result in the same output as pasting:
-	//
-	// 		<p>List:</p>
-	// 		<ul>
-	// 			<li>B<b>old</b></li>
-	// 			<li><a href="https://cksource.com">Lin</a>k</li>
-	// 			<li><i>M<b>ul<u>tip</u></b><u>le</u></i></li>
-	// 		</ul>
-	it( 'pastes list with styled items prepended by a paragraph', () => {
-		const expectedModel = '<paragraph>List:</paragraph>' +
-			'<listItem listIndent="0" listType="bulleted">B<$text bold="true">old</$text></listItem>' +
-			'<listItem listIndent="0" listType="bulleted"><$text linkHref="https://cksource.com">Lin</$text>k</listItem>' +
-			'<listItem listIndent="0" listType="bulleted"><$text italic="true">M</$text><$text bold="true" italic="true">ul</$text>' +
-			'<$text bold="true" italic="true" underline="true">tip</$text>' +
-			'<$text italic="true" underline="true">le</$text></listItem>';
-
-		expectContent( styled, expectedModel );
-	} );
-
-	// Pastes (after cleaning up garbage markup):
-	//
-	//		<p><span>1.</span><span>Item1</span></p>
-	//		<p><span>2.</span><span>Item 2</span></p>
-	//		<p>Some text</p>
-	//		<p><span>·</span><span>Bullet 1</span></p>
-	//
-	// which should result in the same output as pasting:
-	//
-	//		<ol>
-	//			<li>Item1</li>
-	//			<li>Item 2</li>
-	//		</ol>
-	//		<p>Some text</p>
-	//		<ul>
-	//			<li>Bullet 1</li>
-	//		</ul>
-	it( 'pastes multiple lists separated by the paragraph', () => {
-		const expectedModel = '<listItem listIndent="0" listType="numbered">Item1</listItem>' +
-			'<listItem listIndent="0" listType="numbered">Item 2</listItem>' +
-			'<paragraph>Some text</paragraph>' +
-			'<listItem listIndent="0" listType="bulleted">Bullet 1</listItem>';
-
-		expectContent( multiple, expectedModel );
-	} );
-
-	// Pastes (after cleaning up garbage markup):
-	//
-	//		<p><span>1.</span><span>Item1</span></p>
-	//		<p><span>2.</span><span>Item 2</span></p>
-	//		<p><span>1.</span><span>Item 1</span></p>
-	//		<p><span>2.</span><span>Item2</span></p>
-	//
-	// which should result in the same output as pasting:
-	//
-	// 		<ol>
-	// 			<li>Item1</li>
-	// 			<li>Item 2</li>
-	// 		</ol>
-	// 		<ol>
-	// 			<li>Item 1</li>
-	// 			<li>Item2</li>
-	// 		</ol>
-	//
-	// It will create one list, see https://github.com/ckeditor/ckeditor5-list/issues/99.
-	it( 'pastes multiple lists one right after another', () => {
-		const expectedModel = '<listItem listIndent="0" listType="numbered">Item1</listItem>' +
-			'<listItem listIndent="0" listType="numbered">Item 2</listItem>' +
-			'<listItem listIndent="0" listType="numbered">Item 1</listItem>' +
-			'<listItem listIndent="0" listType="numbered">Item2</listItem>';
-
-		expectContent( multipleCombined, expectedModel );
-	} );
-
-	// Pastes (after cleaning up garbage markup):
-	//
-	//		<p><span>1.</span><span>A</span></p>
-	//		<p><span>1)</span><span>B</span></p>
-	//		<p><span>I.</span><span>C</span></p>
-	//		<p><span>A.</span><span>D</span></p>
-	//		<p><span>a)</span><span>E</span></p>
-	//		<p><span>a.</span><span>F</span></p>
-	//		<p><span>i.</span><span>G</span></p>
-	//		<p></p>
-	//		<p><span>·</span><span>H</span></p>
-	//		<p><span>o</span><span>I</span></p>
-	//		<p></p>
-	//		<p><span>§</span><span>J</span></p>
-	//		<p><span><img... /></span><span>k</span></p>
-	//		<p></p>
-	//		<p><span>1.</span><span>h1</span></p>
-	//
-	// which should result in the same output as pasting:
-	//
-	//		<ol><li>A</li></ol>
-	//		<ol><li>B</li></ol>
-	//		<ol><li>C</li></ol>
-	//		<ol><li>D</li></ol>
-	//		<ol><li>E</li></ol>
-	//		<ol><li>F</li></ol>
-	//		<ol><li>G</li></ol>
-	//		<p></p>
-	//		<ul><li>H</li></ul>
-	//		<ul><li>I</li></ul>
-	//		<p></p>
-	//		<ul><li>J</li></ul>
-	//		<ul><li>k</li></ul>
-	//		<p></p>
-	//		<ol><li>h1</li></ol>
-	//
-	// It will create one list, for all lists not separated by any element - see https://github.com/ckeditor/ckeditor5-list/issues/99.
-	it( 'pastes many one item lists', () => {
-		const expectedModel = '<listItem listIndent="0" listType="numbered">A</listItem>' +
-			'<listItem listIndent="0" listType="numbered">B</listItem>' +
-			'<listItem listIndent="0" listType="numbered">C</listItem>' +
-			'<listItem listIndent="0" listType="numbered">D</listItem>' +
-			'<listItem listIndent="0" listType="numbered">E</listItem>' +
-			'<listItem listIndent="0" listType="numbered">F</listItem>' +
-			'<listItem listIndent="0" listType="numbered">G</listItem>' +
-			'<paragraph></paragraph>' +
-			'<listItem listIndent="0" listType="bulleted">H</listItem>' +
-			'<listItem listIndent="0" listType="bulleted">I</listItem>' +
-			'<paragraph></paragraph>' +
-			'<listItem listIndent="0" listType="bulleted">J</listItem>' +
-			'<listItem listIndent="0" listType="bulleted">k</listItem>' +
-			'<paragraph></paragraph>' +
-			'<listItem listIndent="0" listType="numbered">h1</listItem>';
-
-		expectContent( manyOneItem, expectedModel );
-	} );
-
-	// Pastes (after cleaning up garbage markup):
-	//
-	//		<h1><span>1.</span><span>H1 1</span></h1>
-	//		<h1><span>2.</span><span>H1 2</span></h1>
-	//
-	// which should result in the same output as pasting:
-	//
-	// 		<ol>
-	// 			<li>H1 1</li>
-	// 			<li>H1 2</li>
-	// 		</ol>
-	//
-	// Since headings cannot be used inside lists, they should be transformed to a regular text.
-	it( 'pastes list created from headings (h1)', () => {
-		const expectedModel = '<listItem listIndent="0" listType="numbered">H1 1</listItem>' +
-			'<listItem listIndent="0" listType="numbered">H1 2</listItem>';
-
-		expectContent( heading1, expectedModel );
-	} );
-
-	// Pastes (after cleaning up garbage markup):
-	//
-	//		<h3><span>·</span><span>H<b>2 1</b></span></h3>
-	//		<h3><span>·</span><span><i><u>H</u></i><u>2</u> 2</span></h3>
-	//
-	// which should result in the same output as pasting:
-	//
-	// 		<ul>
-	// 			<li>H<b>2 1</b></li>
-	// 			<li><i><u>H</u></i><u>2</u> 2</li>
-	// 		</ul>
-	//
-	// Since headings cannot be used inside lists, they should be transformed to a regular text.
-	it( 'pastes list created from styled headings (h3)', () => {
-		const expectedModel = '<listItem listIndent="0" listType="bulleted">H<$text bold="true">2 1</$text></listItem>' +
-			'<listItem listIndent="0" listType="bulleted"><$text italic="true" underline="true">H</$text>' +
-			'<$text underline="true">2</$text> 2</listItem>';
-
-		expectContent( heading3Styled, expectedModel );
-	} );
-
-	// Pastes (after cleaning up garbage markup):
-	//
-	//		<p><span>1.</span><span>H 7</span></p>
-	//
-	// which should result in the same output as pasting:
-	//
-	// 		<ol>
-	// 			<li>H 7</li>
-	// 		</ol>
-	//
-	// In Word `Heading 7` is represented as `<p class="MsoHeading7"...>`.
-	it( 'pastes list created from styled headings (h3)', () => {
-		const expectedModel = '<listItem listIndent="0" listType="numbered">H 7</listItem>';
-
-		expectContent( heading7, expectedModel );
-	} );
-
-	function expectContent( input, expectedModel ) {
-		pasteHtml( editor, input );
-
-		expect( insertedModel ).to.equal( expectedModel );
-	}
-} );

+ 0 - 119
packages/ckeditor5-paste-from-office/tests/data/integration/spacing.js

@@ -1,119 +0,0 @@
-/**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-/* globals document */
-
-import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
-import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
-import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
-import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
-import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
-import Underline from '@ckeditor/ckeditor5-basic-styles/src/underline';
-import PasteFromOffice from '../../../src/pastefromoffice';
-
-import { setData, stringify } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
-import { pasteHtml } from '../../_utils/utils';
-
-import simple from '../../_data/spacing/simple/input.word2016.html';
-import singleLine from '../../_data/spacing/single-line/input.word2016.html';
-import multiLine from '../../_data/spacing/multi-line/input.word2016.html';
-
-describe( 'Spacing – integration', () => {
-	let element, editor, insertedModel;
-
-	before( () => {
-		element = document.createElement( 'div' );
-
-		document.body.appendChild( element );
-
-		return ClassicTestEditor
-			.create( element, { plugins: [ Clipboard, Paragraph, Bold, Italic, Underline, PasteFromOffice ] } )
-			.then( editorInstance => {
-				editor = editorInstance;
-
-				const model = editor.model;
-				const insertContent = model.insertContent;
-
-				sinon.stub( editor.model, 'insertContent' ).callsFake( ( content, selection ) => {
-					// Save model string representation now as it may change after `insertContent()` function call
-					// so accessing it later may not work as it may have empty/changed structure.
-					insertedModel = stringify( content );
-					insertContent.call( model, content, selection );
-				} );
-			} );
-	} );
-
-	beforeEach( () => {
-		setData( editor.model, '<paragraph>[]</paragraph>' );
-	} );
-
-	afterEach( () => {
-		insertedModel = null;
-	} );
-
-	after( () => {
-		sinon.restore();
-
-		editor.destroy();
-
-		element.remove();
-	} );
-
-	// Pastes (after cleaning up garbage markup):
-	//
-	//		<p><span>Foo Bar </span></p>
-	//
-	// which should result in the same output as pasting:
-	//
-	//		<p>Foo Bar </p>
-	it( 'pastes line with single space', () => {
-		const expectedModel = '<paragraph>Foo Bar </paragraph>';
-
-		expectContent( simple, expectedModel );
-	} );
-
-	// Pastes (after cleaning up garbage markup):
-	//
-	//		<p><span>
-	//			<span style='mso-spacerun:yes'>  </span>
-	//			2Foo <span style='mso-spacerun:yes'>  </span>
-	//			3Bar4 <span style='mso-spacerun:yes'>   </span><o:p></o:p>
-	//		</span></p>
-	//
-	// which should result in the same output as pasting:
-	//
-	// 		<p>  2Foo   3Bar4    </p>
-	it( 'pastes single line with multiple spaces', () => {
-		const expectedModel = '<paragraph>  2Foo   3Bar4    </paragraph>';
-
-		expectContent( singleLine, expectedModel );
-	} );
-
-	// Pastes (after cleaning up garbage markup):
-	//
-	//		<p><span>2Foo   3Bar4    <o:p></o:p></span></p>
-	//		<p><span>03   <o:p></o:p></span></p>
-	// 		<p><span>  21 <o:p></o:p></span></p>
-	//
-	// which should result in the same output as pasting:
-	//
-	//		<p>2Foo   3Bar4    </p>
-	//		<p>03   </p>
-	//		<p>  21 </p>
-	it( 'pastes multiple lines with multiple spaces', () => {
-		const expectedModel = '<paragraph>2Foo   3Bar4    </paragraph>' +
-			'<paragraph>03   </paragraph>' +
-			'<paragraph>  21 </paragraph>';
-
-		expectContent( multiLine, expectedModel );
-	} );
-
-	function expectContent( input, expectedModel ) {
-		pasteHtml( editor, input );
-
-		expect( insertedModel.replace( /\u00A0/g, '#' ).replace( /&nbsp;/g, '#' ) )
-			.to.equal( expectedModel.replace( /\u00A0/g, '#' ).replace( /&nbsp;/g, '#' ) );
-	}
-} );

+ 43 - 0
packages/ckeditor5-paste-from-office/tests/data/normalization.js

@@ -0,0 +1,43 @@
+/**
+ * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md.
+ */
+
+import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
+import PasteFromOffice from '../../src/pastefromoffice';
+
+import { generateTests } from '../_utils/utils';
+
+const browsers = [ 'chrome', 'firefox', 'safari', 'edge' ];
+
+const editorConfig = {
+	plugins: [ Clipboard, PasteFromOffice ]
+};
+
+generateTests( {
+	input: 'basic-styles',
+	type: 'normalization',
+	browsers,
+	editorConfig
+} );
+
+generateTests( {
+	input: 'link',
+	type: 'normalization',
+	browsers,
+	editorConfig
+} );
+
+generateTests( {
+	input: 'list',
+	type: 'normalization',
+	browsers,
+	editorConfig
+} );
+
+generateTests( {
+	input: 'spacing',
+	type: 'normalization',
+	browsers,
+	editorConfig
+} );

+ 0 - 70
packages/ckeditor5-paste-from-office/tests/data/normalization/basic-styles.js

@@ -1,70 +0,0 @@
-/**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
-import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
-import PasteFromOffice from '../../../src/pastefromoffice';
-
-import { expectNormalized } from '../../_utils/utils';
-
-import boldWithinText from '../../_data/basic-styles/bold-within-text/input.word2016.html';
-import italicStartingText from '../../_data/basic-styles/italic-starting-text/input.word2016.html';
-import underlinedText from '../../_data/basic-styles/underlined-text/input.word2016.html';
-import strikethroughEndingText from '../../_data/basic-styles/strikethrough-ending-text/input.word2016.html';
-import multipleStylesSingleLine from '../../_data/basic-styles/multiple-styles-single-line/input.word2016.html';
-import multipleStylesMultiline from '../../_data/basic-styles/multiple-styles-multiline/input.word2016.html';
-
-import boldWithinTextNormalized from '../../_data/basic-styles/bold-within-text/normalized.word2016.html';
-import italicStartingTextNormalized from '../../_data/basic-styles/italic-starting-text/normalized.word2016.html';
-import underlinedTextNormalized from '../../_data/basic-styles/underlined-text/normalized.word2016.html';
-import strikethroughEndingTextNormalized from '../../_data/basic-styles/strikethrough-ending-text/normalized.word2016.html';
-import multipleStylesSingleLineNormalized from '../../_data/basic-styles/multiple-styles-single-line/normalized.word2016.html';
-import multipleStylesMultilineNormalized from '../../_data/basic-styles/multiple-styles-multiline/normalized.word2016.html';
-
-describe( 'Basic Styles – normalization', () => {
-	let editor, pasteFromOfficePlugin;
-
-	beforeEach( () => {
-		return VirtualTestEditor
-			.create( {
-				plugins: [ Clipboard, PasteFromOffice ]
-			} )
-			.then( newEditor => {
-				editor = newEditor;
-
-				pasteFromOfficePlugin = editor.plugins.get( 'PasteFromOffice' );
-			} );
-	} );
-
-	it( 'normalizes bold within text', () => {
-		expectNormalized(
-			pasteFromOfficePlugin._normalizeWordInput( boldWithinText, editor ), boldWithinTextNormalized );
-	} );
-
-	it( 'normalizes italic starting text', () => {
-		expectNormalized(
-			pasteFromOfficePlugin._normalizeWordInput( italicStartingText, editor ), italicStartingTextNormalized );
-	} );
-
-	it( 'normalizes underlined text', () => {
-		expectNormalized(
-			pasteFromOfficePlugin._normalizeWordInput( underlinedText, editor ), underlinedTextNormalized );
-	} );
-
-	it( 'normalizes strikethrough ending text', () => {
-		expectNormalized(
-			pasteFromOfficePlugin._normalizeWordInput( strikethroughEndingText, editor ), strikethroughEndingTextNormalized );
-	} );
-
-	it( 'normalizes mulitple styles single line', () => {
-		expectNormalized(
-			pasteFromOfficePlugin._normalizeWordInput( multipleStylesSingleLine, editor ), multipleStylesSingleLineNormalized );
-	} );
-
-	it( 'normalizes mulitple styles multiline', () => {
-		expectNormalized(
-			pasteFromOfficePlugin._normalizeWordInput( multipleStylesMultiline, editor ), multipleStylesMultilineNormalized );
-	} );
-} );

+ 0 - 46
packages/ckeditor5-paste-from-office/tests/data/normalization/link.js

@@ -1,46 +0,0 @@
-/**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
-import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
-import PasteFromOffice from '../../../src/pastefromoffice';
-
-import { expectNormalized } from '../../_utils/utils';
-
-import withinText from '../../_data/link/within-text/input.word2016.html';
-import combined from '../../_data/link/combined/input.word2016.html';
-import twoLine from '../../_data/link/two-line/input.word2016.html';
-
-import withinTextNormalized from '../../_data/link/within-text/normalized.word2016.html';
-import combinedNormalized from '../../_data/link/combined/normalized.word2016.html';
-import twoLineNormalized from '../../_data/link/two-line/normalized.word2016.html';
-
-describe( 'Link – normalization', () => {
-	let editor, pasteFromOfficePlugin;
-
-	beforeEach( () => {
-		return VirtualTestEditor
-			.create( {
-				plugins: [ Clipboard, PasteFromOffice ]
-			} )
-			.then( newEditor => {
-				editor = newEditor;
-
-				pasteFromOfficePlugin = editor.plugins.get( 'PasteFromOffice' );
-			} );
-	} );
-
-	it( 'normalizes link within text', () => {
-		expectNormalized( pasteFromOfficePlugin._normalizeWordInput( withinText, editor ), withinTextNormalized );
-	} );
-
-	it( 'normalizes combined links', () => {
-		expectNormalized( pasteFromOfficePlugin._normalizeWordInput( combined, editor ), combinedNormalized );
-	} );
-
-	it( 'normalizes two line links', () => {
-		expectNormalized( pasteFromOfficePlugin._normalizeWordInput( twoLine, editor ), twoLineNormalized );
-	} );
-} );

+ 0 - 76
packages/ckeditor5-paste-from-office/tests/data/normalization/list.js

@@ -1,76 +0,0 @@
-/**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
-import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
-import PasteFromOffice from '../../../src/pastefromoffice';
-
-import { expectNormalized } from '../../_utils/utils';
-
-import simple from '../../_data/list/simple/input.word2016.html';
-import styled from '../../_data/list/styled/input.word2016.html';
-import multiple from '../../_data/list/multiple/input.word2016.html';
-import multipleCombined from '../../_data/list/multiple-combined/input.word2016.html';
-import manyOneItem from '../../_data/list/many-one-item/input.word2016.html';
-import heading1 from '../../_data/list/heading1/input.word2016.html';
-import heading3Styled from '../../_data/list/heading3-styled/input.word2016.html';
-import heading7 from '../../_data/list/heading7/input.word2016.html';
-
-import simpleNormalized from '../../_data/list/simple/normalized.word2016.html';
-import styledNormalized from '../../_data/list/styled/normalized.word2016.html';
-import multipleNormalized from '../../_data/list/multiple/normalized.word2016.html';
-import multipleCombinedNormalized from '../../_data/list/multiple-combined/normalized.word2016.html';
-import manyOneItemNormalized from '../../_data/list/many-one-item/normalized.word2016.html';
-import heading1Normalized from '../../_data/list/heading1/normalized.word2016.html';
-import heading3StyledNormalized from '../../_data/list/heading3-styled/normalized.word2016.html';
-import heading7Normalized from '../../_data/list/heading7/normalized.word2016.html';
-
-describe( 'List – normalization', () => {
-	let editor, pasteFromOfficePlugin;
-
-	beforeEach( () => {
-		return VirtualTestEditor
-			.create( {
-				plugins: [ Clipboard, PasteFromOffice ]
-			} )
-			.then( newEditor => {
-				editor = newEditor;
-
-				pasteFromOfficePlugin = editor.plugins.get( 'PasteFromOffice' );
-			} );
-	} );
-
-	it( 'normalizes simple list', () => {
-		expectNormalized( pasteFromOfficePlugin._normalizeWordInput( simple, editor ), simpleNormalized );
-	} );
-
-	it( 'normalizes list with styled items prepended by a paragraph', () => {
-		expectNormalized( pasteFromOfficePlugin._normalizeWordInput( styled, editor ), styledNormalized );
-	} );
-
-	it( 'normalizes multiple lists separated by the paragraph', () => {
-		expectNormalized( pasteFromOfficePlugin._normalizeWordInput( multiple, editor ), multipleNormalized );
-	} );
-
-	it( 'normalizes multiple lists one right after another', () => {
-		expectNormalized( pasteFromOfficePlugin._normalizeWordInput( multipleCombined, editor ), multipleCombinedNormalized );
-	} );
-
-	it( 'normalizes many one item lists', () => {
-		expectNormalized( pasteFromOfficePlugin._normalizeWordInput( manyOneItem, editor ), manyOneItemNormalized );
-	} );
-
-	it( 'normalizes list created from headings (h1)', () => {
-		expectNormalized( pasteFromOfficePlugin._normalizeWordInput( heading1, editor ), heading1Normalized );
-	} );
-
-	it( 'normalizes list created from styled headings (h3)', () => {
-		expectNormalized( pasteFromOfficePlugin._normalizeWordInput( heading3Styled, editor ), heading3StyledNormalized );
-	} );
-
-	it( 'normalizes list created from heading (h7)', () => {
-		expectNormalized( pasteFromOfficePlugin._normalizeWordInput( heading7, editor ), heading7Normalized );
-	} );
-} );

+ 0 - 46
packages/ckeditor5-paste-from-office/tests/data/normalization/spacing.js

@@ -1,46 +0,0 @@
-/**
- * @license Copyright (c) 2003-2018, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
-
-import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
-import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
-import PasteFromOffice from '../../../src/pastefromoffice';
-
-import { expectNormalized } from '../../_utils/utils';
-
-import simple from '../../_data/spacing/simple/input.word2016.html';
-import singleLine from '../../_data/spacing/single-line/input.word2016.html';
-import multiLine from '../../_data/spacing/multi-line/input.word2016.html';
-
-import simpleNormalized from '../../_data/spacing/simple/normalized.word2016.html';
-import singleLineNormalized from '../../_data/spacing/single-line/normalized.word2016.html';
-import multiLineNormalized from '../../_data/spacing/multi-line/normalized.word2016.html';
-
-describe( 'Spacing – normalization', () => {
-	let editor, pasteFromOfficePlugin;
-
-	beforeEach( () => {
-		return VirtualTestEditor
-			.create( {
-				plugins: [ Clipboard, PasteFromOffice ]
-			} )
-			.then( newEditor => {
-				editor = newEditor;
-
-				pasteFromOfficePlugin = editor.plugins.get( 'PasteFromOffice' );
-			} );
-	} );
-
-	it( 'normalizes simple single spacing', () => {
-		expectNormalized( pasteFromOfficePlugin._normalizeWordInput( simple, editor ), simpleNormalized );
-	} );
-
-	it( 'normalizes multiple spacing in a single line', () => {
-		expectNormalized( pasteFromOfficePlugin._normalizeWordInput( singleLine, editor ), singleLineNormalized );
-	} );
-
-	it( 'normalizes multiple spacing in multiple lines', () => {
-		expectNormalized( pasteFromOfficePlugin._normalizeWordInput( multiLine, editor ), multiLineNormalized );
-	} );
-} );

+ 41 - 39
packages/ckeditor5-paste-from-office/tests/filters/list.js

@@ -9,60 +9,62 @@ import View from '@ckeditor/ckeditor5-engine/src/view/view';
 
 import { transformListItemLikeElementsIntoLists } from '../../src/filters/list';
 
-describe( 'Filters – list', () => {
-	const htmlDataProcessor = new HtmlDataProcessor();
+describe( 'Filters', () => {
+	describe( 'List', () => {
+		const htmlDataProcessor = new HtmlDataProcessor();
 
-	describe( 'transformListItemLikeElementsIntoLists', () => {
-		it( 'replaces list-like elements with semantic lists', () => {
-			const html = '<p style="mso-list:l0 level1 lfo0"><span style="mso-list:Ignore">1.</span>Item 1</p>';
-			const view = htmlDataProcessor.toView( html );
+		describe( 'transformListItemLikeElementsIntoLists', () => {
+			it( 'replaces list-like elements with semantic lists', () => {
+				const html = '<p style="mso-list:l0 level1 lfo0"><span style="mso-list:Ignore">1.</span>Item 1</p>';
+				const view = htmlDataProcessor.toView( html );
 
-			transformListItemLikeElementsIntoLists( view, '', new View() );
+				transformListItemLikeElementsIntoLists( view, '', new View() );
 
-			expect( view.childCount ).to.equal( 1 );
-			expect( view.getChild( 0 ).name ).to.equal( 'ol' );
-			expect( stringify( view ) ).to.equal( '<ol><li style="mso-list:l0 level1 lfo0">Item 1</li></ol>' );
-		} );
+				expect( view.childCount ).to.equal( 1 );
+				expect( view.getChild( 0 ).name ).to.equal( 'ol' );
+				expect( stringify( view ) ).to.equal( '<ol><li style="mso-list:l0 level1 lfo0">Item 1</li></ol>' );
+			} );
 
-		it( 'replaces list-like elements with semantic lists with proper bullet type based on styles', () => {
-			const html = '<p style="mso-list:l0 level1 lfo0"><span style="mso-list:Ignore">1.</span>Item 1</p>';
-			const view = htmlDataProcessor.toView( html );
+			it( 'replaces list-like elements with semantic lists with proper bullet type based on styles', () => {
+				const html = '<p style="mso-list:l0 level1 lfo0"><span style="mso-list:Ignore">1.</span>Item 1</p>';
+				const view = htmlDataProcessor.toView( html );
 
-			transformListItemLikeElementsIntoLists( view, '@list l0:level1 { mso-level-number-format: bullet; }', new View() );
+				transformListItemLikeElementsIntoLists( view, '@list l0:level1 { mso-level-number-format: bullet; }', new View() );
 
-			expect( view.childCount ).to.equal( 1 );
-			expect( view.getChild( 0 ).name ).to.equal( 'ul' );
-			expect( stringify( view ) ).to.equal( '<ul><li style="mso-list:l0 level1 lfo0">Item 1</li></ul>' );
-		} );
+				expect( view.childCount ).to.equal( 1 );
+				expect( view.getChild( 0 ).name ).to.equal( 'ul' );
+				expect( stringify( view ) ).to.equal( '<ul><li style="mso-list:l0 level1 lfo0">Item 1</li></ul>' );
+			} );
 
-		it( 'does not modify the view if there are no list-like elements', () => {
-			const html = '<h1>H1</h1><p>Foo Bar</p>';
-			const view = htmlDataProcessor.toView( html );
+			it( 'does not modify the view if there are no list-like elements', () => {
+				const html = '<h1>H1</h1><p>Foo Bar</p>';
+				const view = htmlDataProcessor.toView( html );
 
-			transformListItemLikeElementsIntoLists( view, '', new View() );
+				transformListItemLikeElementsIntoLists( view, '', new View() );
 
-			expect( view.childCount ).to.equal( 2 );
-			expect( stringify( view ) ).to.equal( html );
-		} );
+				expect( view.childCount ).to.equal( 2 );
+				expect( stringify( view ) ).to.equal( html );
+			} );
 
-		it( 'handles empty `mso-list` style correctly', () => {
-			const html = '<p style="mso-list:"><span style="mso-list:Ignore">1.</span>Item 1</p>';
-			const view = htmlDataProcessor.toView( html );
+			it( 'handles empty `mso-list` style correctly', () => {
+				const html = '<p style="mso-list:"><span style="mso-list:Ignore">1.</span>Item 1</p>';
+				const view = htmlDataProcessor.toView( html );
 
-			transformListItemLikeElementsIntoLists( view, '', new View() );
+				transformListItemLikeElementsIntoLists( view, '', new View() );
 
-			expect( view.childCount ).to.equal( 1 );
-			expect( view.getChild( 0 ).name ).to.equal( 'ol' );
-			expect( stringify( view ) ).to.equal( '<ol><li style="mso-list:">Item 1</li></ol>' );
-		} );
+				expect( view.childCount ).to.equal( 1 );
+				expect( view.getChild( 0 ).name ).to.equal( 'ol' );
+				expect( stringify( view ) ).to.equal( '<ol><li style="mso-list:">Item 1</li></ol>' );
+			} );
 
-		it( 'handles empty body correctly', () => {
-			const view = htmlDataProcessor.toView( '' );
+			it( 'handles empty body correctly', () => {
+				const view = htmlDataProcessor.toView( '' );
 
-			transformListItemLikeElementsIntoLists( view, '', new View() );
+				transformListItemLikeElementsIntoLists( view, '', new View() );
 
-			expect( view.childCount ).to.equal( 0 );
-			expect( stringify( view ) ).to.equal( '' );
+				expect( view.childCount ).to.equal( 0 );
+				expect( stringify( view ) ).to.equal( '' );
+			} );
 		} );
 	} );
 } );

+ 18 - 4
packages/ckeditor5-paste-from-office/tests/filters/space.js

@@ -5,23 +5,37 @@
 
 /* globals DOMParser */
 
-import { normalizeEndTagsPrecedingSpace, normalizeSpacerunSpans } from '../../src/filters/space';
+import { normalizeSpacing, normalizeSpacerunSpans } from '../../src/filters/space';
 
 describe( 'Filters', () => {
 	describe( 'space', () => {
-		describe( 'normalizeEndTagsPrecedingSpace', () => {
+		describe( 'normalizeSpacing', () => {
 			it( 'should replace last space before closing tag with NBSP', () => {
 				const input = '<p>Foo </p><p><span> Bar  </span> Baz </p>';
 				const expected = '<p>Foo\u00A0</p><p><span> Bar \u00A0</span> Baz\u00A0</p>';
 
-				expect( normalizeEndTagsPrecedingSpace( input ) ).to.equal( expected );
+				expect( normalizeSpacing( input ) ).to.equal( expected );
 			} );
 
 			it( 'should replace last space before special "o:p" tag with NBSP', () => {
 				const input = '<p>Foo  <o:p></o:p><span> <o:p></o:p> Bar</span></p>';
 				const expected = '<p>Foo \u00A0<o:p></o:p><span>\u00A0<o:p></o:p> Bar</span></p>';
 
-				expect( normalizeEndTagsPrecedingSpace( input ) ).to.equal( expected );
+				expect( normalizeSpacing( input ) ).to.equal( expected );
+			} );
+
+			it( 'should normalize Safari "space spans"', () => {
+				const input = '<p>Foo <span class="Apple-converted-space">   </span> Baz <span>  </span></p>';
+				const expected = '<p>Foo \u00A0 \u00A0 Baz \u00A0\u00A0</p>';
+
+				expect( normalizeSpacing( input ) ).to.equal( expected );
+			} );
+
+			it( 'should normalize nested Safari "space spans"', () => {
+				const input = '<p> Foo <span class="Apple-converted-space"> <span class="Apple-converted-space">    </span></span> Baz</p>';
+				const expected = '<p> Foo \u00A0 \u00A0 \u00A0 Baz</p>';
+
+				expect( normalizeSpacing( input ) ).to.equal( expected );
 			} );
 		} );