From 4b86ac6a197b38e529409456b3c5b1bf1e8ce453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Thu, 14 Feb 2019 17:44:35 +0100 Subject: [PATCH 1/9] Handling lists indentation on paste (PoC). --- src/filters/list.js | 71 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 5 deletions(-) diff --git a/src/filters/list.js b/src/filters/list.js index bd4e2bc..3d1c1aa 100644 --- a/src/filters/list.js +++ b/src/filters/list.js @@ -38,8 +38,17 @@ export function transformListItemLikeElementsIntoLists( documentFragment, styles itemLikeElements.forEach( ( itemLikeElement, i ) => { if ( !currentList || isNewListNeeded( itemLikeElements[ i - 1 ], itemLikeElement ) ) { const listStyle = detectListStyle( itemLikeElement, stylesString ); - - currentList = insertNewEmptyList( listStyle, itemLikeElement.element, writer ); + const indentationDifference = getIndentationDifference( itemLikeElements[ i - 1 ], itemLikeElement ); + + if ( indentationDifference < 0 ) { + currentList = findParentListAtLevel( currentList, indentationDifference ); + } else if ( indentationDifference > 0 ) { + const lastListItem = currentList.getChild( currentList.childCount - 1 ); + const lastListItemChild = lastListItem.getChild( lastListItem.childCount - 1 ); + currentList = insertNewEmptyList( listStyle, lastListItemChild, writer, indentationDifference ); + } else { + currentList = insertNewEmptyList( listStyle, itemLikeElement.element, writer ); + } } const listItem = transformElementIntoListItem( itemLikeElement.element, writer ); @@ -158,11 +167,25 @@ function detectListStyle( listLikeItem, stylesString ) { // @param {module:engine/view/element~Element} element Element before which list is inserted. // @param {module:engine/view/upcastwriter~UpcastWriter} writer // @returns {module:engine/view/element~Element} Newly created list element. -function insertNewEmptyList( listStyle, element, writer ) { +function insertNewEmptyList( listStyle, element, writer, indentLevel = 0 ) { + const parent = element.parent; const list = writer.createElement( listStyle.type ); - const position = element.parent.getChildIndex( element ); + const position = parent.getChildIndex( element ) + 1; + + let currentList = list; + + // Wrap new list into li's depending on indentation level. + if ( indentLevel > 1 ) { + for ( let i = 1; i < indentLevel; i++ ) { + const parentList = new Element( listStyle.type ); + const parentLi = new Element( 'li' ); + writer.appendChild( currentList, parentLi ); + writer.appendChild( parentLi, parentList ); + currentList = parentList; + } + } - writer.insertChild( position, list, element.parent ); + writer.insertChild( position, currentList, parent ); return list; } @@ -253,6 +276,10 @@ function isNewListNeeded( previousItem, currentItem ) { return true; } + if ( getIndentationDifference( previousItem, currentItem ) !== 0 ) { + return true; + } + // Even with the same id the list does not have to be continuous (#43). return !isList( previousSibling ); } @@ -260,3 +287,37 @@ function isNewListNeeded( previousItem, currentItem ) { function isList( element ) { return element.is( 'ol' ) || element.is( 'ul' ); } + +// Calculates the indentation difference between two given list items. +// +// @param {Object} previousItem +// @param {Object} currentItem +// @returns {Number} +function getIndentationDifference( previousItem, currentItem ) { + return previousItem ? currentItem.indent - previousItem.indent : 0; +} + +// Finds parent list of a given list with indentation level lower by a given value. +// +// @param {module:engine/view/element~Element} currentList List element from which to start looking for a parent list. +// @param {Number} levelDifference Level difference between lists. +// @returns {module:engine/view/element~Element} Found list. +function findParentListAtLevel( currentList, levelDifference ) { + const ancestors = currentList.getAncestors( { parentFirst: true } ); + + let parentList = null; + let levelChange = 0; + + for ( const ancestor of ancestors ) { + if ( ancestor.name === 'ul' || ancestor.name === 'ol' ) { + levelChange--; + } + + if ( levelChange === levelDifference ) { + parentList = ancestor; + break; + } + } + + return parentList; +} From 03922eef1d5f6f3db365e836d11e7914d93c3482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Fri, 15 Feb 2019 14:48:44 +0100 Subject: [PATCH 2/9] Handle more complex nesting scenarios. --- src/filters/list.js | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/src/filters/list.js b/src/filters/list.js index 3d1c1aa..1dd2844 100644 --- a/src/filters/list.js +++ b/src/filters/list.js @@ -36,16 +36,32 @@ export function transformListItemLikeElementsIntoLists( documentFragment, styles let currentList = null; itemLikeElements.forEach( ( itemLikeElement, i ) => { - if ( !currentList || isNewListNeeded( itemLikeElements[ i - 1 ], itemLikeElement ) ) { + const isDifferentList = isNewListNeeded( itemLikeElements[ i - 1 ], itemLikeElement ); + const previousListItem = isDifferentList ? null : itemLikeElements[ i - 1 ]; + const indentationDifference = getIndentationDifference( previousListItem, itemLikeElement ); + + if ( isDifferentList ) { + currentList = null; + } + + if ( !currentList || isDifferentList || indentationDifference !== 0 ) { const listStyle = detectListStyle( itemLikeElement, stylesString ); - const indentationDifference = getIndentationDifference( itemLikeElements[ i - 1 ], itemLikeElement ); if ( indentationDifference < 0 ) { currentList = findParentListAtLevel( currentList, indentationDifference ); + + if ( !currentList.is( listStyle.type ) ) { + currentList = writer.rename( listStyle.type, currentList ); + } } else if ( indentationDifference > 0 ) { - const lastListItem = currentList.getChild( currentList.childCount - 1 ); - const lastListItemChild = lastListItem.getChild( lastListItem.childCount - 1 ); - currentList = insertNewEmptyList( listStyle, lastListItemChild, writer, indentationDifference ); + if ( currentList ) { + const lastListItem = currentList.getChild( currentList.childCount - 1 ); + const lastListItemChild = lastListItem.getChild( lastListItem.childCount - 1 ); + currentList = insertNewEmptyList( listStyle, lastListItemChild, writer, indentationDifference ); + } else { + // First item in the list has indentation. + currentList = insertNewEmptyList( listStyle, itemLikeElement.element, writer, indentationDifference + 1 ); + } } else { currentList = insertNewEmptyList( listStyle, itemLikeElement.element, writer ); } @@ -266,6 +282,10 @@ function removeBulletElement( element, writer ) { // @param {Object} currentItem // @returns {Boolean} function isNewListNeeded( previousItem, currentItem ) { + if ( !previousItem ) { + return true; + } + if ( previousItem.id !== currentItem.id ) { return true; } @@ -276,10 +296,6 @@ function isNewListNeeded( previousItem, currentItem ) { return true; } - if ( getIndentationDifference( previousItem, currentItem ) !== 0 ) { - return true; - } - // Even with the same id the list does not have to be continuous (#43). return !isList( previousSibling ); } @@ -294,7 +310,7 @@ function isList( element ) { // @param {Object} currentItem // @returns {Number} function getIndentationDifference( previousItem, currentItem ) { - return previousItem ? currentItem.indent - previousItem.indent : 0; + return previousItem ? currentItem.indent - previousItem.indent : currentItem.indent - 1; } // Finds parent list of a given list with indentation level lower by a given value. From 8a338c47513b5d8fd4f8e808491cc61740b71620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Fri, 15 Feb 2019 14:49:50 +0100 Subject: [PATCH 3/9] Tests: Added unit and integration tests for pasting nested lists. --- tests/_data/list/index.js | 24 +- .../list/nested-mixed/input.word2016.html | 942 +++++++++++++++ .../list/nested-mixed/model.word2016.html | 7 + .../nested-mixed/normalized.word2016.html | 32 + .../list/nested-multiple/input.word2016.html | 1017 +++++++++++++++++ .../list/nested-multiple/model.word2016.html | 19 + .../nested-multiple/normalized.word2016.html | 58 + tests/_data/list/nested/input.word2016.html | 928 +++++++++++++++ tests/_data/list/nested/model.word2016.html | 8 + .../list/nested/normalized.word2016.html | 36 + tests/filters/list.js | 96 ++ 11 files changed, 3164 insertions(+), 3 deletions(-) create mode 100644 tests/_data/list/nested-mixed/input.word2016.html create mode 100644 tests/_data/list/nested-mixed/model.word2016.html create mode 100644 tests/_data/list/nested-mixed/normalized.word2016.html create mode 100644 tests/_data/list/nested-multiple/input.word2016.html create mode 100644 tests/_data/list/nested-multiple/model.word2016.html create mode 100644 tests/_data/list/nested-multiple/normalized.word2016.html create mode 100644 tests/_data/list/nested/input.word2016.html create mode 100644 tests/_data/list/nested/model.word2016.html create mode 100644 tests/_data/list/nested/normalized.word2016.html diff --git a/tests/_data/list/index.js b/tests/_data/list/index.js index a4cef47..302ee46 100644 --- a/tests/_data/list/index.js +++ b/tests/_data/list/index.js @@ -13,6 +13,9 @@ import heading1 from './heading1/input.word2016.html'; import heading3Styled from './heading3-styled/input.word2016.html'; import heading7 from './heading7/input.word2016.html'; import resumeTemplate from './resume-template/input.word2016.html'; +import nested from './nested/input.word2016.html'; +import nestedMixed from './nested-mixed/input.word2016.html'; +import nestedMultiple from './nested-multiple/input.word2016.html'; import simpleNormalized from './simple/normalized.word2016.html'; import styledNormalized from './styled/normalized.word2016.html'; @@ -23,6 +26,9 @@ import heading1Normalized from './heading1/normalized.word2016.html'; import heading3StyledNormalized from './heading3-styled/normalized.word2016.html'; import heading7Normalized from './heading7/normalized.word2016.html'; import resumeTemplateNormalized from './resume-template/normalized.word2016.html'; +import nestedNormalized from './nested/normalized.word2016.html'; +import nestedMixedNormalized from './nested-mixed/normalized.word2016.html'; +import nestedMultipleNormalized from './nested-multiple/normalized.word2016.html'; import simpleModel from './simple/model.word2016.html'; import styledModel from './styled/model.word2016.html'; @@ -33,6 +39,9 @@ import heading1Model from './heading1/model.word2016.html'; import heading3StyledModel from './heading3-styled/model.word2016.html'; import heading7Model from './heading7/model.word2016.html'; import resumeTemplateModel from './resume-template/model.word2016.html'; +import nestedModel from './nested/model.word2016.html'; +import nestedMixedModel from './nested-mixed/model.word2016.html'; +import nestedMultipleModel from './nested-multiple/model.word2016.html'; export const fixtures = { input: { @@ -44,7 +53,10 @@ export const fixtures = { heading1, heading3Styled, heading7, - resumeTemplate + resumeTemplate, + nested, + nestedMixed, + nestedMultiple }, normalized: { simple: simpleNormalized, @@ -55,7 +67,10 @@ export const fixtures = { heading1: heading1Normalized, heading3Styled: heading3StyledNormalized, heading7: heading7Normalized, - resumeTemplate: resumeTemplateNormalized + resumeTemplate: resumeTemplateNormalized, + nested: nestedNormalized, + nestedMixed: nestedMixedNormalized, + nestedMultiple: nestedMultipleNormalized }, model: { simple: simpleModel, @@ -66,7 +81,10 @@ export const fixtures = { heading1: heading1Model, heading3Styled: heading3StyledModel, heading7: heading7Model, - resumeTemplate: resumeTemplateModel + resumeTemplate: resumeTemplateModel, + nested: nestedModel, + nestedMixed: nestedMixedModel, + nestedMultiple: nestedMultipleModel } }; diff --git a/tests/_data/list/nested-mixed/input.word2016.html b/tests/_data/list/nested-mixed/input.word2016.html new file mode 100644 index 0000000..79a19cb --- /dev/null +++ b/tests/_data/list/nested-mixed/input.word2016.html @@ -0,0 +1,942 @@ + + + + + + + + + + + + + + + + + + + +

·      +A1

+ +

1)    +B2

+ +

·      +C4

+ +

2.     +D3

+ +

·      +E1

+ +

1)    +F2

+ + + + + diff --git a/tests/_data/list/nested-mixed/model.word2016.html b/tests/_data/list/nested-mixed/model.word2016.html new file mode 100644 index 0000000..ec1b85d --- /dev/null +++ b/tests/_data/list/nested-mixed/model.word2016.html @@ -0,0 +1,7 @@ +A1 +B2 + +C4 +D3 +E1 +F2 diff --git a/tests/_data/list/nested-mixed/normalized.word2016.html b/tests/_data/list/nested-mixed/normalized.word2016.html new file mode 100644 index 0000000..22566d0 --- /dev/null +++ b/tests/_data/list/nested-mixed/normalized.word2016.html @@ -0,0 +1,32 @@ +
    +
  • + A1 +
      +
    1. + B2 +
        +
      1. +
          +
        • + C4 +
        • +
        +
      2. + +
      3. + D3 +
      4. +
      +
    2. +
    +
  • + +
  • + E1 +
      +
    1. + F2 +
    2. +
    +
  • +
diff --git a/tests/_data/list/nested-multiple/input.word2016.html b/tests/_data/list/nested-multiple/input.word2016.html new file mode 100644 index 0000000..3eb8f8a --- /dev/null +++ b/tests/_data/list/nested-multiple/input.word2016.html @@ -0,0 +1,1017 @@ + + + + + + + + + + + + + + + + + + + +

·      +A1

+ +

§  +B3

+ +

2)    +C2

+ +

 

+ +

Foo Bar...

+ +

 

+ +

a.     +A2

+ +

2.     +B1

+ +

a.     +C2

+ +

 

+ +

·      +A1

+ +

1)    +B2

+ +

·      +C1

+ + + + + diff --git a/tests/_data/list/nested-multiple/model.word2016.html b/tests/_data/list/nested-multiple/model.word2016.html new file mode 100644 index 0000000..8322a73 --- /dev/null +++ b/tests/_data/list/nested-multiple/model.word2016.html @@ -0,0 +1,19 @@ +A1 + +B3 +C2 + + +Foo Bar... + + + +A2 +B1 +C2 + + + +A1 +B2 +C1 diff --git a/tests/_data/list/nested-multiple/normalized.word2016.html b/tests/_data/list/nested-multiple/normalized.word2016.html new file mode 100644 index 0000000..7e7b477 --- /dev/null +++ b/tests/_data/list/nested-multiple/normalized.word2016.html @@ -0,0 +1,58 @@ +
    +
  • + A1 +
      +
    1. +
        +
      • + B3 +
      • +
      +
    2. + +
    3. + C2 +
    4. +
    +
  • +
+ +

+

Foo Bar...

+

+ +
    +
  1. +
      +
    1. + A2 +
    2. +
    +
  2. + +
  3. + B1 +
      +
    1. + C2 +
    2. +
    +
  4. +
+ +

+ +
    +
  • + A1 +
      +
    1. + B2 +
    2. +
    +
  • + +
  • + C1 +
  • +
diff --git a/tests/_data/list/nested/input.word2016.html b/tests/_data/list/nested/input.word2016.html new file mode 100644 index 0000000..a468d93 --- /dev/null +++ b/tests/_data/list/nested/input.word2016.html @@ -0,0 +1,928 @@ + + + + + + + + + + + + + + + + + + + +

1.     +A1

+ +

2.     +B1

+ +

a.     +C2

+ +

1.     +D4

+ +

b.     +E2

+ +

                                               +i.     F3

+ +

3.     +G1

+ + + + + diff --git a/tests/_data/list/nested/model.word2016.html b/tests/_data/list/nested/model.word2016.html new file mode 100644 index 0000000..c0c8c14 --- /dev/null +++ b/tests/_data/list/nested/model.word2016.html @@ -0,0 +1,8 @@ +A1 +B1 +C2 + +D4 +E2 +F3 +G1 diff --git a/tests/_data/list/nested/normalized.word2016.html b/tests/_data/list/nested/normalized.word2016.html new file mode 100644 index 0000000..07fb217 --- /dev/null +++ b/tests/_data/list/nested/normalized.word2016.html @@ -0,0 +1,36 @@ +
    +
  1. + A1 +
  2. + +
  3. + B1 +
      +
    1. + C2 +
        +
      1. +
          +
        1. + D4 +
        2. +
        +
      2. +
      +
    2. + +
    3. + E2 +
        +
      1. + F3 +
      2. +
      +
    4. +
    +
  4. + +
  5. + G1 +
  6. +
diff --git a/tests/filters/list.js b/tests/filters/list.js index eee5334..73e924d 100644 --- a/tests/filters/list.js +++ b/tests/filters/list.js @@ -81,6 +81,102 @@ describe( 'PasteFromOffice - filters', () => { expect( view.childCount ).to.equal( 0 ); expect( stringify( view ) ).to.equal( '' ); } ); + + describe( 'Nesting', () => { + const level1 = 'style="mso-list:l0 level1 lfo0"'; + const level2 = 'style="mso-list:l0 level2 lfo0"'; + const level3 = 'style="mso-list:l0 level3 lfo0"'; + const level4 = 'style="mso-list:l0 level4 lfo0"'; + + it( 'handles simple indentation', () => { + const html = `

Foo

Bar

Baz

`; + const view = htmlDataProcessor.toView( html ); + + transformListItemLikeElementsIntoLists( view, '' ); + + expect( view.childCount ).to.equal( 1 ); + expect( stringify( view ) ).to.equal( + `
  1. Foo` + + `
    1. Bar` + + `
      1. Baz
` ); + } ); + + it( 'handles non-linear indentation', () => { + const html = `

Foo

Bar

Baz

`; + const view = htmlDataProcessor.toView( html ); + + transformListItemLikeElementsIntoLists( view, '' ); + + expect( view.childCount ).to.equal( 1 ); + expect( stringify( view ) ).to.equal( + `
  1. Foo` + + '
    1. ' + + `
      1. Bar` + + `
        1. Baz
` ); + } ); + + it( 'handles indentation in both directions', () => { + const html = `

Foo

Bar

Baz

` + + `

Bax

123

`; + const view = htmlDataProcessor.toView( html ); + + transformListItemLikeElementsIntoLists( view, '' ); + + expect( view.childCount ).to.equal( 1 ); + expect( stringify( view ) ).to.equal( + `
  1. Foo` + + '
    1. ' + + `
      1. Bar` + + `
        1. Baz
        ` + + '
      ' + + `
    2. Bax
    ` + + `
  2. 123
` ); + } ); + + it( 'handles different list styles #1', () => { + const html = `

Foo

Bar

Baz

`; + const view = htmlDataProcessor.toView( html ); + + transformListItemLikeElementsIntoLists( view, '@list l0:level1 { mso-level-number-format: bullet; }' + + '@list l0:level3 { mso-level-number-format: bullet; }' ); + + expect( view.childCount ).to.equal( 1 ); + expect( stringify( view ) ).to.equal( + `
  • Foo` + + `
    1. Bar` + + `
      • Baz
` ); + } ); + + it( 'handles different list styles #2', () => { + const html = `

Foo

Bar

Baz

`; + const view = htmlDataProcessor.toView( html ); + + transformListItemLikeElementsIntoLists( view, '@list l0:level1 { mso-level-number-format: bullet; }' + + '@list l0:level2 { mso-level-number-format: bullet; }' ); + + expect( view.childCount ).to.equal( 1 ); + expect( stringify( view ) ).to.equal( + `
  • Foo` + + '
    • ' + + `
      1. Bar
      ` + + `
    • Baz
    ` + + '
' ); + } ); + + it( 'handles indentation in the first list element', () => { + const html = `

Foo

Bar

Baz

`; + const view = htmlDataProcessor.toView( html ); + + transformListItemLikeElementsIntoLists( view, '' ); + + expect( view.childCount ).to.equal( 1 ); + expect( stringify( view ) ).to.equal( + '
  1. ' + + `
    1. Foo
    ` + + `
  2. Bar` + + `
    1. Baz
` ); + } ); + } ); } ); } ); From ac4c7511ede5dec2590974ab007791a6773aacaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Fri, 15 Feb 2019 16:09:29 +0100 Subject: [PATCH 4/9] Tests: Added Safari fixtures. --- tests/_data/list/index.js | 19 +- .../nested-mixed/input.safari.word2016.html | 206 ++++++++++++++ .../input.safari.word2016.html | 259 ++++++++++++++++++ .../normalized.safari.word2016.html | 58 ++++ .../list/nested/input.safari.word2016.html | 191 +++++++++++++ 5 files changed, 730 insertions(+), 3 deletions(-) create mode 100644 tests/_data/list/nested-mixed/input.safari.word2016.html create mode 100644 tests/_data/list/nested-multiple/input.safari.word2016.html create mode 100644 tests/_data/list/nested-multiple/normalized.safari.word2016.html create mode 100644 tests/_data/list/nested/input.safari.word2016.html diff --git a/tests/_data/list/index.js b/tests/_data/list/index.js index 302ee46..370a5eb 100644 --- a/tests/_data/list/index.js +++ b/tests/_data/list/index.js @@ -98,6 +98,9 @@ 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 resumeTemplateSafari from './resume-template/input.safari.word2016.html'; +import nestedSafari from './nested/input.safari.word2016.html'; +import nestedMixedSafari from './nested-mixed/input.safari.word2016.html'; +import nestedMultipleSafari from './nested-multiple/input.safari.word2016.html'; import simpleNormalizedSafari from './simple/normalized.safari.word2016.html'; import styledNormalizedSafari from './styled/normalized.safari.word2016.html'; @@ -108,6 +111,7 @@ 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 resumeTemplateNormalizedSafari from './resume-template/normalized.safari.word2016.html'; +import nestedMultipleNormalizedSafari from './nested-multiple/normalized.safari.word2016.html'; import styledSafariModel from './styled/model.safari.word2016.html'; import resumeTemplateSafariModel from './resume-template/model.safari.word2016.html'; @@ -123,7 +127,10 @@ export const browserFixtures = { heading1: heading1Safari, heading3Styled: heading3StyledSafari, heading7: heading7Safari, - resumeTemplate: resumeTemplateSafari + resumeTemplate: resumeTemplateSafari, + nested: nestedSafari, + nestedMixed: nestedMixedSafari, + nestedMultiple: nestedMultipleSafari }, normalized: { simple: simpleNormalizedSafari, @@ -134,7 +141,10 @@ export const browserFixtures = { heading1: heading1NormalizedSafari, heading3Styled: heading3StyledNormalizedSafari, heading7: heading7NormalizedSafari, - resumeTemplate: resumeTemplateNormalizedSafari + resumeTemplate: resumeTemplateNormalizedSafari, + nested: nestedNormalized, + nestedMixed: nestedMixedNormalized, + nestedMultiple: nestedMultipleNormalizedSafari }, model: { simple: simpleModel, @@ -145,7 +155,10 @@ export const browserFixtures = { heading1: heading1Model, heading3Styled: heading3StyledModel, heading7: heading7Model, - resumeTemplate: resumeTemplateSafariModel + resumeTemplate: resumeTemplateSafariModel, + nested: nestedModel, + nestedMixed: nestedMixedModel, + nestedMultiple: nestedMultipleModel } } }; diff --git a/tests/_data/list/nested-mixed/input.safari.word2016.html b/tests/_data/list/nested-mixed/input.safari.word2016.html new file mode 100644 index 0000000..858e1f3 --- /dev/null +++ b/tests/_data/list/nested-mixed/input.safari.word2016.html @@ -0,0 +1,206 @@ +

· A1

1) B2

· C4

2. D3

· E1

1) F2

diff --git a/tests/_data/list/nested-multiple/input.safari.word2016.html b/tests/_data/list/nested-multiple/input.safari.word2016.html new file mode 100644 index 0000000..285c507 --- /dev/null +++ b/tests/_data/list/nested-multiple/input.safari.word2016.html @@ -0,0 +1,259 @@ +

· A1

§ B3

2) C2

Foo Bar...

a. A2

2. B1

a. C2

· A1

1) B2

· C1

diff --git a/tests/_data/list/nested-multiple/normalized.safari.word2016.html b/tests/_data/list/nested-multiple/normalized.safari.word2016.html new file mode 100644 index 0000000..d7d9e0d --- /dev/null +++ b/tests/_data/list/nested-multiple/normalized.safari.word2016.html @@ -0,0 +1,58 @@ +
    +
  • + A1 +
      +
    1. +
        +
      • + B3 +
      • +
      +
    2. + +
    3. + C2 +
    4. +
    +
  • +
+ +

+

Foo Bar...

+

+ +
    +
  1. +
      +
    1. + A2 +
    2. +
    +
  2. + +
  3. + B1 +
      +
    1. + C2 +
    2. +
    +
  4. +
+ +

+ +
    +
  • + A1 +
      +
    1. + B2 +
    2. +
    +
  • + +
  • + C1 +
  • +
diff --git a/tests/_data/list/nested/input.safari.word2016.html b/tests/_data/list/nested/input.safari.word2016.html new file mode 100644 index 0000000..b92631b --- /dev/null +++ b/tests/_data/list/nested/input.safari.word2016.html @@ -0,0 +1,191 @@ +

1. A1

2. B1

a. C2

1. D4

b. E2

i. F3

3. G1

From ba2cdfd4d4a73e80127e8a50b34aa6ccb2734f39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Fri, 15 Feb 2019 16:11:31 +0100 Subject: [PATCH 5/9] Tests: Added original '.docx' fixture files. --- tests/_data/list/nested-mixed/nested-mixed.docx | Bin 0 -> 13234 bytes .../list/nested-multiple/nested-multiple.docx | Bin 0 -> 13586 bytes tests/_data/list/nested/nested.docx | Bin 0 -> 14068 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/_data/list/nested-mixed/nested-mixed.docx create mode 100644 tests/_data/list/nested-multiple/nested-multiple.docx create mode 100644 tests/_data/list/nested/nested.docx diff --git a/tests/_data/list/nested-mixed/nested-mixed.docx b/tests/_data/list/nested-mixed/nested-mixed.docx new file mode 100644 index 0000000000000000000000000000000000000000..77e8ff0b610218d61e1a5cb24f55e714d1b24dcf GIT binary patch literal 13234 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 QKyZK`FhE1o7=E7pKNy&x&j0`b literal 0 HcmV?d00001 diff --git a/tests/_data/list/nested-multiple/nested-multiple.docx b/tests/_data/list/nested-multiple/nested-multiple.docx new file mode 100644 index 0000000000000000000000000000000000000000..60cbb087e278adf8978d43b9f445be2d4a7b716f GIT binary patch literal 13586 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 Jk>$72{{yq1M2P?Z literal 0 HcmV?d00001 diff --git a/tests/_data/list/nested/nested.docx b/tests/_data/list/nested/nested.docx new file mode 100644 index 0000000000000000000000000000000000000000..6b45eab22dabe321a59606f35a087ada455963de GIT binary patch literal 14068 zcmeIZgMVg8(?1;BwllGvOeVH%+xEo9#I|kQwrx9^7?aE|yZ7$1yR-NE{sYf*uFt8y z&guU4>8npwbzN1}vJ$``C;(sp5C8xGgaC{&HY&z|000G`0077U5I`CNHr9?t){Z)g zZnj1aTC}cKmIS#VK;+o~Kp*Y@@AzLl1NHG^=6&=CLXUy({xgls;;rNb{Uf(1iQsO&iP`{Xg5V{D!y!F0IogOMjqXE42nu>uaEAts5uwrsxi{`Pr!8A$6yPh@O% zE^gZ0Azj#MJ6`J=D^UqHtOIiKS-Vf;wcQmUA+WuG!FADg7bflS!T4>ISd3!SKU@tp zYzhl3<|!n3q8s^uQt;uR2-=K@Vrt%iq%JShPHE{e*^4PVg<)aQTvWpYyp&t0GYGeJ z64MLHn5QO*i6%O#ce7TjU-2}qnem%B#XU8aB|RN!dW?QK6xMb7%&B``SJ6OdAT?wT zWGLP1S7S{i_4lK&LrfmlD?+t;ogEwObS=Kyk45U=@=@0rjtlxx(+CUzfCB&l=wf4U zNcSHhF|;voviexbep|x+6d1sdb?l?{|L&taZsIpR9&i=d>A&nj!(}A^8RJ0VtEuq_ zXz1}KaBq+=rQYQ!B#smeHs>G7q;Jw0xZr+Ufy$MA+ra`k|@+Z%oL(o+|$-|iD>s%m#x2G?*GiaQ;UG{{LqA-Z(Kr<_$Q z)G0bg>M{p2T*bIjiMH*0Ph72!bIr5TX!Zi7W7V)^dMph3D2l>*OQ_I_Ce}S7#*cQr z1`%Ei!AzMBgmbUyiB`9H?i5OE`IV4e!vSF|83D!kJCJRBmoe+mHBMYkO%Rk?Ddf;f zs=sR(GnbS0B)iQOm6%8)B(rD%&GDLSH(_>Pp$$MdV#(GSm~ z_c1C7cMnP>>ZgAGrpSf7^bmr>o&J|+12?8dcX0!}Z9!Yk8aPEYox&`h4HGYd;Yhhk z51;MPDS5^kq6&qrM$}O9zSG13K`7G3mqZBT@C(*Y^OFHEmP>rn?+N03#qtPOh_~Fz z%Av$n7pA`bnC#fPTb~dUQ#%)792pFCw^sH(4PO8N1=5=5wuj3JtQjr<+;jO7l!2K| zf4d86)?*;>f28vY(+9iL!@561 zB$GvmPf>GPK&b?pAmWU3T^N1QWbwN~9$5_)jC|*_5pVMz^Q4%*&g zm)maeA5V^G2w%hYhy$8E!D8p5*-{C5GLP!nVVtx+QP-oD(~>!Q=zk-JBVVr)k@h08 z4xA<%ur0dP$BYaSPq}k6HL^0I`<*iUro7M9B*L*p5IVtc@Pk^$+$WCp%2{Sb zZ!DHrHyiw;I^-=1D>BVyHdY(xgLJd(Awklk1z=hZ5cpvj`uAh;4XVY`@ncT$#F%LA z`=hk{A=~_vcsfhpTT5G8nH_d^-;y~+lA(KJBQ>~H>~PZ~mXk^JhB`dysT(v!MB^h6 zjUX?Zp{duyxw5>S0W*>iBWr+fLfNA@tw|2fzqU{d(?|4ku=YWYOJPLC1kl2d8AL|% z*+`Bxh!@C3B8q8}@i7#4Fr-8yI>W__yO#R~V5a2f$nk#)lf<~0R z#35X@)5~Ds`qKSaa3)JaBI&pu_UGz>L)+tw38iX-spSxQs(?rSABc_U69OeRQ|fbgiZ13DXW% zAY}v1g9DZV>yTZ4Vzcw6-L}MbZy~#CX}Ob@V7+C5@^<9JW;qUbaz5h%8K} zv17G`&1xax8bo=NOO+sFC|5pkjJGEMV0uI(h9p93?CK}%1C2l$oX*}x5|+PHR48??e2?&fqLJSi%(>+9X?*ie+t zmlvm&hsJfI_yD&SHXhI0sX4lgF7Max6LB^dt}#Ph?+0Z|-anpoP7CT8Cm;s)^z=x)5%d9MExKU0f%ki}PGPP$-=xC_H zwS0Y}`^CSRj5UET05+A4q8TTUy=PX=!7{8y=$w`?Nb7MpgsJD#Y>PxX9+7e!PP71V zDr3$V30N1kB}mU!kk!K_JGZda>Fd+5VDAd=d?AuTUqsThX72JR#sG8Fx)5V+%(~8X zjGirF&m3XlIA%l*0&5EPSH0;DFtfqS2kzDoDUu{ZbAd~u!JFYPX<&$9Cd!i}p*PD^ z`cQ;n>1mScV)VBG#b2HPNdqrC1*&&0o3bv}qJz!>bBzzzok{4KruO`#5gIA3Zk9!B zw4}>tX3~O%O|SGNXBe;y&euEj`|48kZX@m%AZkaAEbAte33OjTqK-QuJCWvjFZH+?=4Zcrwda z>o2925V3NWsgRH{M#*9XZnQ8xpk zz10N6PRsUWd2>uAegrkFsv3E;KpDf2of79h! z;JhHM8JZ@+>0h@q8(?zLLu6=3=;&vnxDN7yQC$x_C}WZxvdk-vZSLGxG6_l5-1P z1_v4LBj3Q4JKqGnctRo%xtmj!y!rEnd&$}B{b_fV@=M360DV}*ZfRB}cL4sYW6f8a zs-dRMjiEC6*Y%JAqr$W8TC~Nh%d&=Dmq$3jvCpRSK^N|AOXLk_8+s#WkLm@^)5i%f z-?CTmAAq|S@V+=^5W_yS-gjHTs22#cK!|JSmCxZG5f(pH-27006W?|IPSxFmiM>vo>+~Z2_!Tma!DfxB)% z2w6oI>Ak}Ntcl)Ea__wRwL`1bz=Qy`R6@}08`&hF#L?SAmUsJF5fT-swLJhzgQOaR zowGR0i7k0JuCb{0HP{k>vL=20wt{6aOlVu99rPqtzNj?0T(I7@8*x$54ssEy)2c#q z1d5-8HU)0%O(_xR<JFRRS`pE zB1S;TcSah_JHQa$1c>Y|&GaV<<6*oThmv@TS#X&O+4~BzHGAr)#cWzy(8@~Z;2d88 zs58?qoOHGBQXxzLA6Zt*U{gaSnmYg za_wGY)_p*kvl{^_R6t?k!>!_N70_*UlXnncI}g)qB;p1BwN3IAjucYTiByQ50V%EC z@^&>wc_md|AfURYAUh(zE2*q12Fe{H*SvOmy`Mfz#|-U(3>|591?+8Kn7NMcuQKve ze(s#G_q{5Mw>|Z?xI5mX)p%nXX%%2`6M5kX?P*KM#OUJC`VDZ9z{J^daEC{|+=*OA3<(IxeiHj}{O&Z(= z^t_{dBdr(8eN4VGRd2agUuRpCX}*+yK=0iewhu4dwM`86tOimknymk=H% zCn<6}K3xb_@I-w4!7k1SB*-LXV4LFIU5Y~yvypJ@WF1vZu8=QqXmUlgJghcVjE`9L z573pyqPw+2mZs~0UieaR^tW*-Tw{kx)<{C3T=%;%Tryvu*d9CF=zlgP1-;F9-v9Ui zvmNu_y2w5p9Z?@{LzF-5Y8NAYg}-T)_}K|_AO-}0ZI7HQ1pB3O`2y-neu_kG@th0b z{`2x6V@5*cw$&n=b#w3QU2XnPBVR`XQfQoy`@sbp_o+Cr(BysC6g9dk_t(zsZK*)X zE-WsF1xO#e?HRf{QyYw+%g{wBvJ7KTr$|%9t>vK#&&VKg%}bP7PE-%Oa5I;BvpNWH^ zU1V9zxA3c`N0|FTZG4yT{;421{$QWc?K&Y!tk5f@M3_sAdQdUk*eZv4Ru-Op_Itz3 zj}LA9Z(ThWcJ$fyV`6tcCKmC--}K=lkhQn5b)Yk_u{Zi7Sn_{PrVoybh}Dttr$-ss zlKKIceBMezBIFYGYD;P1@w7O~KB%9iZy|<>JOCRcSeX*J8;H@c*O(!jMiOYvA zHwqF%Ac!ZbY){w(={}bD&V3V65Iff%ADxW_qn_Wy#-M;m#ZvB6!m9x|=s;pdREShx zr!0hl-RSR^+Rc%V%vL~K>{PL-FSL?r4Jgxl4Tr8vQIxm~c3kEgGATLF^yAeVQ_k*x%aGLM{p}83!Am|JO?&-U%l+& zhOP)MF1w5LH?0<`4T$Y1r=PxE{Cf+wC=(i@CKU#zdk)nb^4;9%qVoewR9ACFN0y

r1nD<0d-aqF0-)!1uEsuTTP`) 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 Date: Mon, 18 Feb 2019 13:25:31 +0100 Subject: [PATCH 6/9] Refactoring. --- src/filters/list.js | 50 ++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/src/filters/list.js b/src/filters/list.js index 1dd2844..42819f5 100644 --- a/src/filters/list.js +++ b/src/filters/list.js @@ -36,32 +36,42 @@ export function transformListItemLikeElementsIntoLists( documentFragment, styles let currentList = null; itemLikeElements.forEach( ( itemLikeElement, i ) => { - const isDifferentList = isNewListNeeded( itemLikeElements[ i - 1 ], itemLikeElement ); - const previousListItem = isDifferentList ? null : itemLikeElements[ i - 1 ]; - const indentationDifference = getIndentationDifference( previousListItem, itemLikeElement ); + const isDifferentList = belongsToTheSameList( itemLikeElements[ i - 1 ], itemLikeElement ); + const previousItemLikeElement = isDifferentList ? null : itemLikeElements[ i - 1 ]; + const indentationDifference = getIndentationDifference( previousItemLikeElement, itemLikeElement ); + // If item from a new list is encountered, reset "currentList" which points to a previous list element. if ( isDifferentList ) { currentList = null; } - if ( !currentList || isDifferentList || indentationDifference !== 0 ) { + if ( !currentList || indentationDifference !== 0 ) { const listStyle = detectListStyle( itemLikeElement, stylesString ); + // Current list item has indentation level lower than the previous item. + // Find the list element with correct indentation level where current list item should be inserted. if ( indentationDifference < 0 ) { currentList = findParentListAtLevel( currentList, indentationDifference ); + // List might have been inserted with different list style (triggered by the item nested inside + // it with different list style) so it should be adjusted to the current list item style. if ( !currentList.is( listStyle.type ) ) { currentList = writer.rename( listStyle.type, currentList ); } + // Current list item has indentation level greater than the previous item. Insert correctly nested new list. } else if ( indentationDifference > 0 ) { if ( currentList ) { const lastListItem = currentList.getChild( currentList.childCount - 1 ); const lastListItemChild = lastListItem.getChild( lastListItem.childCount - 1 ); - currentList = insertNewEmptyList( listStyle, lastListItemChild, writer, indentationDifference ); + + // Insert new list element on the end of the last list item in the current list. Since new list element + // will be inserted inside list item we need one level less of nesting ("indentationDifference - 1"). + currentList = insertNewEmptyList( listStyle, lastListItemChild, writer, indentationDifference - 1 ); } else { // First item in the list has indentation. - currentList = insertNewEmptyList( listStyle, itemLikeElement.element, writer, indentationDifference + 1 ); + currentList = insertNewEmptyList( listStyle, itemLikeElement.element, writer, indentationDifference ); } + // Current list item (itemLikeElement) has indentation level the same as previous item. } else { currentList = insertNewEmptyList( listStyle, itemLikeElement.element, writer ); } @@ -180,10 +190,11 @@ function detectListStyle( listLikeItem, stylesString ) { // // @param {Object} listStyle List style object which determines the type of newly created list. // Usually a result of `detectListStyle()` function. -// @param {module:engine/view/element~Element} element Element before which list is inserted. +// @param {module:engine/view/element~Element} element Element after which list is inserted. // @param {module:engine/view/upcastwriter~UpcastWriter} writer +// @param {Number} [wrap=0] How many times new empty list element should be wrapped into another list to created nested structure. // @returns {module:engine/view/element~Element} Newly created list element. -function insertNewEmptyList( listStyle, element, writer, indentLevel = 0 ) { +function insertNewEmptyList( listStyle, element, writer, wrap = 0 ) { const parent = element.parent; const list = writer.createElement( listStyle.type ); const position = parent.getChildIndex( element ) + 1; @@ -191,8 +202,8 @@ function insertNewEmptyList( listStyle, element, writer, indentLevel = 0 ) { let currentList = list; // Wrap new list into li's depending on indentation level. - if ( indentLevel > 1 ) { - for ( let i = 1; i < indentLevel; i++ ) { + if ( wrap > 0 ) { + for ( let i = 0; i < wrap; i++ ) { const parentList = new Element( listStyle.type ); const parentLi = new Element( 'li' ); writer.appendChild( currentList, parentLi ); @@ -281,7 +292,7 @@ function removeBulletElement( element, writer ) { // @param {Object} previousItem // @param {Object} currentItem // @returns {Boolean} -function isNewListNeeded( previousItem, currentItem ) { +function belongsToTheSameList( previousItem, currentItem ) { if ( !previousItem ) { return true; } @@ -304,7 +315,8 @@ function isList( element ) { return element.is( 'ol' ) || element.is( 'ul' ); } -// Calculates the indentation difference between two given list items. +// Calculates the indentation difference between two given list items (based on indent attribute +// extracted from `mso-list` style, see #getListItemData). // // @param {Object} previousItem // @param {Object} currentItem @@ -313,13 +325,13 @@ function getIndentationDifference( previousItem, currentItem ) { return previousItem ? currentItem.indent - previousItem.indent : currentItem.indent - 1; } -// Finds parent list of a given list with indentation level lower by a given value. +// Finds parent list element (ul/ol) of a given list element with indentation level lower by a given value. // -// @param {module:engine/view/element~Element} currentList List element from which to start looking for a parent list. -// @param {Number} levelDifference Level difference between lists. -// @returns {module:engine/view/element~Element} Found list. -function findParentListAtLevel( currentList, levelDifference ) { - const ancestors = currentList.getAncestors( { parentFirst: true } ); +// @param {module:engine/view/element~Element} listElement List element from which to start looking for a parent list. +// @param {Number} indentationDifference Indentation difference between lists. +// @returns {module:engine/view/element~Element} Found list element with indentation level lower by a given value. +function findParentListAtLevel( listElement, indentationDifference ) { + const ancestors = listElement.getAncestors( { parentFirst: true } ); let parentList = null; let levelChange = 0; @@ -329,7 +341,7 @@ function findParentListAtLevel( currentList, levelDifference ) { levelChange--; } - if ( levelChange === levelDifference ) { + if ( levelChange === indentationDifference ) { parentList = ancestor; break; } From dd106069404d861b52814530c228f1df03c768a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20Krzto=C5=84?= Date: Mon, 18 Feb 2019 13:29:08 +0100 Subject: [PATCH 7/9] Docs: Rewording. [skip ci] --- src/filters/list.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/filters/list.js b/src/filters/list.js index 42819f5..3185a3e 100644 --- a/src/filters/list.js +++ b/src/filters/list.js @@ -53,7 +53,7 @@ export function transformListItemLikeElementsIntoLists( documentFragment, styles if ( indentationDifference < 0 ) { currentList = findParentListAtLevel( currentList, indentationDifference ); - // List might have been inserted with different list style (triggered by the item nested inside + // List might have been inserted with a different list style (triggered by the item nested inside // it with different list style) so it should be adjusted to the current list item style. if ( !currentList.is( listStyle.type ) ) { currentList = writer.rename( listStyle.type, currentList ); @@ -71,7 +71,7 @@ export function transformListItemLikeElementsIntoLists( documentFragment, styles // First item in the list has indentation. currentList = insertNewEmptyList( listStyle, itemLikeElement.element, writer, indentationDifference ); } - // Current list item (itemLikeElement) has indentation level the same as previous item. + // Current list item has indentation level at the same level as previous item. } else { currentList = insertNewEmptyList( listStyle, itemLikeElement.element, writer ); } From 167b47e62a2f0d80d908e8bc2f256e390572e160 Mon Sep 17 00:00:00 2001 From: Guilherme Henrique Date: Wed, 26 Feb 2020 13:55:37 +0100 Subject: [PATCH 8/9] Support correct normalization of wrong indentation --- src/filters/list.js | 67 +++++++------------ .../list/nested-mixed/model.word2016.html | 3 +- .../nested-mixed/normalized.word2016.html | 9 +-- .../list/nested-multiple/model.word2016.html | 6 +- .../normalized.safari.word2016.html | 25 +++---- .../nested-multiple/normalized.word2016.html | 24 +++---- tests/_data/list/nested/model.word2016.html | 3 +- .../list/nested/normalized.word2016.html | 8 +-- tests/filters/list.js | 20 +++--- 9 files changed, 59 insertions(+), 106 deletions(-) diff --git a/src/filters/list.js b/src/filters/list.js index 3185a3e..6bd0c36 100644 --- a/src/filters/list.js +++ b/src/filters/list.js @@ -34,46 +34,42 @@ export function transformListItemLikeElementsIntoLists( documentFragment, styles } let currentList = null; + let currentIndentation = 1; itemLikeElements.forEach( ( itemLikeElement, i ) => { - const isDifferentList = belongsToTheSameList( itemLikeElements[ i - 1 ], itemLikeElement ); + const isDifferentList = isNewListNeeded( itemLikeElements[ i - 1 ], itemLikeElement ); const previousItemLikeElement = isDifferentList ? null : itemLikeElements[ i - 1 ]; const indentationDifference = getIndentationDifference( previousItemLikeElement, itemLikeElement ); - // If item from a new list is encountered, reset "currentList" which points to a previous list element. if ( isDifferentList ) { currentList = null; + currentIndentation = 1; } if ( !currentList || indentationDifference !== 0 ) { const listStyle = detectListStyle( itemLikeElement, stylesString ); - // Current list item has indentation level lower than the previous item. - // Find the list element with correct indentation level where current list item should be inserted. - if ( indentationDifference < 0 ) { - currentList = findParentListAtLevel( currentList, indentationDifference ); + if ( !currentList ) { + currentList = insertNewEmptyList( listStyle, itemLikeElement.element, writer ); + } else if ( itemLikeElement.indent > currentIndentation ) { + const lastListItem = currentList.getChild( currentList.childCount - 1 ); + const lastListItemChild = lastListItem.getChild( lastListItem.childCount - 1 ); + + currentList = insertNewEmptyList( listStyle, lastListItemChild, writer ); + + currentIndentation += 1; + } else if ( itemLikeElement.indent < currentIndentation ) { + const differentIndentation = currentIndentation - itemLikeElement.indent; + + currentList = findParentListAtLevel( currentList, differentIndentation ); - // List might have been inserted with a different list style (triggered by the item nested inside - // it with different list style) so it should be adjusted to the current list item style. + currentIndentation = parseInt( itemLikeElement.indent ); + } + + if ( itemLikeElement.indent <= currentIndentation ) { if ( !currentList.is( listStyle.type ) ) { currentList = writer.rename( listStyle.type, currentList ); } - // Current list item has indentation level greater than the previous item. Insert correctly nested new list. - } else if ( indentationDifference > 0 ) { - if ( currentList ) { - const lastListItem = currentList.getChild( currentList.childCount - 1 ); - const lastListItemChild = lastListItem.getChild( lastListItem.childCount - 1 ); - - // Insert new list element on the end of the last list item in the current list. Since new list element - // will be inserted inside list item we need one level less of nesting ("indentationDifference - 1"). - currentList = insertNewEmptyList( listStyle, lastListItemChild, writer, indentationDifference - 1 ); - } else { - // First item in the list has indentation. - currentList = insertNewEmptyList( listStyle, itemLikeElement.element, writer, indentationDifference ); - } - // Current list item has indentation level at the same level as previous item. - } else { - currentList = insertNewEmptyList( listStyle, itemLikeElement.element, writer ); } } @@ -192,27 +188,14 @@ function detectListStyle( listLikeItem, stylesString ) { // Usually a result of `detectListStyle()` function. // @param {module:engine/view/element~Element} element Element after which list is inserted. // @param {module:engine/view/upcastwriter~UpcastWriter} writer -// @param {Number} [wrap=0] How many times new empty list element should be wrapped into another list to created nested structure. // @returns {module:engine/view/element~Element} Newly created list element. -function insertNewEmptyList( listStyle, element, writer, wrap = 0 ) { + +function insertNewEmptyList( listStyle, element, writer ) { const parent = element.parent; const list = writer.createElement( listStyle.type ); const position = parent.getChildIndex( element ) + 1; - let currentList = list; - - // Wrap new list into li's depending on indentation level. - if ( wrap > 0 ) { - for ( let i = 0; i < wrap; i++ ) { - const parentList = new Element( listStyle.type ); - const parentLi = new Element( 'li' ); - writer.appendChild( currentList, parentLi ); - writer.appendChild( parentLi, parentList ); - currentList = parentList; - } - } - - writer.insertChild( position, currentList, parent ); + writer.insertChild( position, list, parent ); return list; } @@ -292,7 +275,7 @@ function removeBulletElement( element, writer ) { // @param {Object} previousItem // @param {Object} currentItem // @returns {Boolean} -function belongsToTheSameList( previousItem, currentItem ) { +function isNewListNeeded( previousItem, currentItem ) { if ( !previousItem ) { return true; } @@ -338,7 +321,7 @@ function findParentListAtLevel( listElement, indentationDifference ) { for ( const ancestor of ancestors ) { if ( ancestor.name === 'ul' || ancestor.name === 'ol' ) { - levelChange--; + levelChange++; } if ( levelChange === indentationDifference ) { diff --git a/tests/_data/list/nested-mixed/model.word2016.html b/tests/_data/list/nested-mixed/model.word2016.html index ec1b85d..3bae02f 100644 --- a/tests/_data/list/nested-mixed/model.word2016.html +++ b/tests/_data/list/nested-mixed/model.word2016.html @@ -1,7 +1,6 @@ A1 B2 - -C4 +C4 D3 E1 F2 diff --git a/tests/_data/list/nested-mixed/normalized.word2016.html b/tests/_data/list/nested-mixed/normalized.word2016.html index 22566d0..610ca67 100644 --- a/tests/_data/list/nested-mixed/normalized.word2016.html +++ b/tests/_data/list/nested-mixed/normalized.word2016.html @@ -5,12 +5,9 @@

  • B2
      -
    1. -
        -
      • - C4 -
      • -
      + +
    2. + C4
    3. diff --git a/tests/_data/list/nested-multiple/model.word2016.html b/tests/_data/list/nested-multiple/model.word2016.html index 8322a73..55cb156 100644 --- a/tests/_data/list/nested-multiple/model.word2016.html +++ b/tests/_data/list/nested-multiple/model.word2016.html @@ -1,14 +1,12 @@ A1 - -B3 +B3 C2 Foo Bar... - -A2 +A2 B1 C2 diff --git a/tests/_data/list/nested-multiple/normalized.safari.word2016.html b/tests/_data/list/nested-multiple/normalized.safari.word2016.html index d7d9e0d..384641c 100644 --- a/tests/_data/list/nested-multiple/normalized.safari.word2016.html +++ b/tests/_data/list/nested-multiple/normalized.safari.word2016.html @@ -2,15 +2,12 @@
    4. A1
        -
      1. -
          -
        • - B3 -
        • -
        -
      2. + +
      3. + B3 +
      4. -
      5. +
      6. C2
      @@ -22,15 +19,11 @@

        -
      1. -
          -
        1. - A2 -
        2. -
        -
      2. +
      3. + A2 +
      4. -
      5. +
      6. B1
        1. diff --git a/tests/_data/list/nested-multiple/normalized.word2016.html b/tests/_data/list/nested-multiple/normalized.word2016.html index 7e7b477..4fa2b52 100644 --- a/tests/_data/list/nested-multiple/normalized.word2016.html +++ b/tests/_data/list/nested-multiple/normalized.word2016.html @@ -2,15 +2,11 @@
        2. A1
            -
          1. -
              -
            • - B3 -
            • -
            -
          2. +
          3. + B3 +
          4. -
          5. +
          6. C2
          @@ -22,15 +18,11 @@

            -
          1. -
              -
            1. - A2 -
            2. -
            -
          2. +
          3. + A2 +
          4. -
          5. +
          6. B1
            1. diff --git a/tests/_data/list/nested/model.word2016.html b/tests/_data/list/nested/model.word2016.html index c0c8c14..002aee3 100644 --- a/tests/_data/list/nested/model.word2016.html +++ b/tests/_data/list/nested/model.word2016.html @@ -1,8 +1,7 @@ A1 B1 C2 - -D4 +D4 E2 F3 G1 diff --git a/tests/_data/list/nested/normalized.word2016.html b/tests/_data/list/nested/normalized.word2016.html index 07fb217..aeb4b50 100644 --- a/tests/_data/list/nested/normalized.word2016.html +++ b/tests/_data/list/nested/normalized.word2016.html @@ -9,12 +9,8 @@
            2. C2
                -
              1. -
                  -
                1. - D4 -
                2. -
                +
              2. + D4
            3. diff --git a/tests/filters/list.js b/tests/filters/list.js index 73e924d..1618709 100644 --- a/tests/filters/list.js +++ b/tests/filters/list.js @@ -110,9 +110,8 @@ describe( 'PasteFromOffice - filters', () => { expect( view.childCount ).to.equal( 1 ); expect( stringify( view ) ).to.equal( `
              1. Foo` + - '
                1. ' + - `
                  1. Bar` + - `
                    1. Baz
              ` ); + `
              1. Bar` + + `
                1. Baz
            ` ); } ); it( 'handles indentation in both directions', () => { @@ -125,10 +124,8 @@ describe( 'PasteFromOffice - filters', () => { expect( view.childCount ).to.equal( 1 ); expect( stringify( view ) ).to.equal( `
            1. Foo` + - '
              1. ' + - `
                1. Bar` + - `
                  1. Baz
                  ` + - '
                ' + + `
                1. Bar` + + `
                  1. Baz
                  ` + `
                2. Bax
                ` + `
              2. 123
              ` ); } ); @@ -155,11 +152,11 @@ describe( 'PasteFromOffice - filters', () => { '@list l0:level2 { mso-level-number-format: bullet; }' ); expect( view.childCount ).to.equal( 1 ); + expect( stringify( view ) ).to.equal( `
              • Foo` + - '
                • ' + - `
                  1. Bar
                  ` + - `
                • Baz
                ` + + `
                • Bar
                • ` + + `
                • Baz
                ` + '
              ' ); } ); @@ -171,8 +168,7 @@ describe( 'PasteFromOffice - filters', () => { expect( view.childCount ).to.equal( 1 ); expect( stringify( view ) ).to.equal( - '
              1. ' + - `
                1. Foo
                ` + + `
                1. Foo` + `
                2. Bar` + `
                  1. Baz
                ` ); } ); From af4cbccb23ffba9a9f5d125eb2f8e27e6f8f5c86 Mon Sep 17 00:00:00 2001 From: Guilherme Henrique Date: Thu, 27 Feb 2020 09:21:07 +0100 Subject: [PATCH 9/9] Fix spacing failed test --- .../list/nested-multiple/normalized.safari.word2016.html | 6 +++--- tests/_data/list/nested-multiple/normalized.word2016.html | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/_data/list/nested-multiple/normalized.safari.word2016.html b/tests/_data/list/nested-multiple/normalized.safari.word2016.html index 384641c..9a3efa3 100644 --- a/tests/_data/list/nested-multiple/normalized.safari.word2016.html +++ b/tests/_data/list/nested-multiple/normalized.safari.word2016.html @@ -14,9 +14,9 @@
              2. -

                +

                Foo Bar...

                -

                +

                1. @@ -33,7 +33,7 @@
                -

                +

                • diff --git a/tests/_data/list/nested-multiple/normalized.word2016.html b/tests/_data/list/nested-multiple/normalized.word2016.html index 4fa2b52..d7cc3bb 100644 --- a/tests/_data/list/nested-multiple/normalized.word2016.html +++ b/tests/_data/list/nested-multiple/normalized.word2016.html @@ -13,9 +13,9 @@
                -

                +

                Foo Bar...

                -

                +

                1. @@ -32,7 +32,7 @@
                -

                +