8
0
Просмотр исходного кода

Implemented support for RTL content in the IntentBlock plugin.

Aleksander Nowodzinski 6 лет назад
Родитель
Сommit
f9d33482e8

+ 27 - 17
packages/ckeditor5-indent/src/indentblock.js

@@ -96,16 +96,18 @@ export default class IndentBlock extends Plugin {
 	 */
 	_setupConversionUsingOffset() {
 		const conversion = this.editor.conversion;
+		const locale = this.editor.locale;
+		const marginProperty = locale.contentLanguageDirection === 'rtl' ? 'margin-right' : 'margin-left';
 
 		conversion.for( 'upcast' ).attributeToAttribute( {
 			view: {
 				styles: {
-					'margin-left': /[\s\S]+/
+					[ marginProperty ]: /[\s\S]+/
 				}
 			},
 			model: {
 				key: 'blockIndent',
-				value: viewElement => viewElement.getStyle( 'margin-left' )
+				value: viewElement => viewElement.getStyle( marginProperty )
 			}
 		} );
 
@@ -118,7 +120,7 @@ export default class IndentBlock extends Plugin {
 			},
 			model: {
 				key: 'blockIndent',
-				value: viewElement => normalizeToMarginLeftStyle( viewElement.getStyle( 'margin' ) )
+				value: viewElement => normalizeToMarginSideStyle( viewElement.getStyle( 'margin' ), marginProperty )
 			}
 		} );
 
@@ -128,7 +130,7 @@ export default class IndentBlock extends Plugin {
 				return {
 					key: 'style',
 					value: {
-						'margin-left': modelAttributeValue
+						[ marginProperty ]: modelAttributeValue
 					}
 				};
 			}
@@ -162,36 +164,44 @@ export default class IndentBlock extends Plugin {
 	}
 }
 
-// Normalizes the margin shorthand value to the value of `margin-left` CSS property.
+// Normalizes the margin shorthand value to the value of margin-left or margin-right CSS property.
 //
 // As such it will return:
-// - '1em' for '1em'
-// - '1em' for '2px 1em'
-// - '1em' for '2px 1em 3px'
-// - '1em' for '2px 10px 3px 1em'
 //
-// @param {String} Margin style value.
-// @returns {String} Extracted value of margin-left.
-function normalizeToMarginLeftStyle( marginStyleValue ) {
+// - '1em' -> '1em'
+// - '2px 1em' -> '1em'
+// - '2px 1em 3px' -> '1em'
+// - '2px 10px 3px 1em'
+//		-> '1em' (side "margin-left")
+//		-> '10px' (side "margin-right")
+//
+// @param {String} marginStyleValue Margin style value.
+// @param {String} side "margin-left" or "margin-right" depending on which margin should be returned.
+// @returns {String} Extracted value of margin-left or margin-right.
+function normalizeToMarginSideStyle( marginStyleValue, side ) {
 	// Splits the margin shorthand, ie margin: 2em 4em.
 	const marginEntries = marginStyleValue.split( ' ' );
 
-	let left;
+	let marginValue;
 
 	// If only one value defined, ie: `margin: 1px`.
-	left = marginEntries[ 0 ];
+	marginValue = marginEntries[ 0 ];
 
 	// If only two values defined, ie: `margin: 1px 2px`.
 	if ( marginEntries[ 1 ] ) {
-		left = marginEntries[ 1 ];
+		marginValue = marginEntries[ 1 ];
 	}
 
 	// If four values defined, ie: `margin: 1px 2px 3px 4px`.
 	if ( marginEntries[ 3 ] ) {
-		left = marginEntries[ 3 ];
+		if ( side === 'margin-left' ) {
+			marginValue = marginEntries[ 3 ];
+		} else {
+			marginValue = marginEntries[ 1 ];
+		}
 	}
 
-	return left;
+	return marginValue;
 }
 
 /**

+ 164 - 62
packages/ckeditor5-indent/tests/indentblock.js

@@ -68,104 +68,206 @@ describe( 'IndentBlock', () => {
 
 	describe( 'conversion', () => {
 		describe( 'using offset', () => {
-			beforeEach( () => {
-				return createTestEditor( { indentBlock: { offset: 50, unit: 'px' } } )
-					.then( newEditor => {
+			describe( 'left–to–right content', () => {
+				beforeEach( () => {
+					return createTestEditor( {
+						indentBlock: { offset: 50, unit: 'px' }
+					} ).then( newEditor => {
 						editor = newEditor;
 						model = editor.model;
 						doc = model.document;
 					} );
-			} );
+				} );
 
-			it( 'should convert margin-left to indent attribute (known offset)', () => {
-				editor.setData( '<p style="margin-left:50px">foo</p>' );
+				it( 'should convert margin-left to indent attribute (known offset)', () => {
+					editor.setData( '<p style="margin-left:50px">foo</p>' );
 
-				const paragraph = doc.getRoot().getChild( 0 );
+					const paragraph = doc.getRoot().getChild( 0 );
 
-				expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.true;
-				expect( paragraph.getAttribute( 'blockIndent' ) ).to.equal( '50px' );
+					expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.true;
+					expect( paragraph.getAttribute( 'blockIndent' ) ).to.equal( '50px' );
 
-				expect( editor.getData() ).to.equal( '<p style="margin-left:50px;">foo</p>' );
-				expect( getViewData( editor.editing.view, { withoutSelection: true } ) )
-					.to.equal( '<p style="margin-left:50px">foo</p>' );
-			} );
+					expect( editor.getData() ).to.equal( '<p style="margin-left:50px;">foo</p>' );
+					expect( getViewData( editor.editing.view, { withoutSelection: true } ) )
+						.to.equal( '<p style="margin-left:50px">foo</p>' );
+				} );
 
-			it( 'should convert margin-left to indent attribute (any offset)', () => {
-				editor.setData( '<p style="margin-left:42em">foo</p>' );
+				it( 'should convert margin-left to indent attribute (any offset)', () => {
+					editor.setData( '<p style="margin-left:42em">foo</p>' );
 
-				const paragraph = doc.getRoot().getChild( 0 );
+					const paragraph = doc.getRoot().getChild( 0 );
 
-				expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.true;
-				expect( paragraph.getAttribute( 'blockIndent' ) ).to.equal( '42em' );
+					expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.true;
+					expect( paragraph.getAttribute( 'blockIndent' ) ).to.equal( '42em' );
 
-				expect( editor.getData() ).to.equal( '<p style="margin-left:42em;">foo</p>' );
-				expect( getViewData( editor.editing.view, { withoutSelection: true } ) )
-					.to.equal( '<p style="margin-left:42em">foo</p>' );
-			} );
+					expect( editor.getData() ).to.equal( '<p style="margin-left:42em;">foo</p>' );
+					expect( getViewData( editor.editing.view, { withoutSelection: true } ) )
+						.to.equal( '<p style="margin-left:42em">foo</p>' );
+				} );
 
-			it( 'should convert margin shortcut to indent attribute (one entry)', () => {
-				editor.setData( '<p style="margin:42em">foo</p>' );
+				it( 'should convert margin shortcut to indent attribute (one entry)', () => {
+					editor.setData( '<p style="margin:42em">foo</p>' );
 
-				const paragraph = doc.getRoot().getChild( 0 );
+					const paragraph = doc.getRoot().getChild( 0 );
 
-				expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.true;
-				expect( paragraph.getAttribute( 'blockIndent' ) ).to.equal( '42em' );
+					expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.true;
+					expect( paragraph.getAttribute( 'blockIndent' ) ).to.equal( '42em' );
 
-				expect( editor.getData() ).to.equal( '<p style="margin-left:42em;">foo</p>' );
-				expect( getViewData( editor.editing.view, { withoutSelection: true } ) )
-					.to.equal( '<p style="margin-left:42em">foo</p>' );
-			} );
+					expect( editor.getData() ).to.equal( '<p style="margin-left:42em;">foo</p>' );
+					expect( getViewData( editor.editing.view, { withoutSelection: true } ) )
+						.to.equal( '<p style="margin-left:42em">foo</p>' );
+				} );
 
-			it( 'should convert margin shortcut to indent attribute (two entries)', () => {
-				editor.setData( '<p style="margin:24em 42em">foo</p>' );
+				it( 'should convert margin shortcut to indent attribute (two entries)', () => {
+					editor.setData( '<p style="margin:24em 42em">foo</p>' );
 
-				const paragraph = doc.getRoot().getChild( 0 );
+					const paragraph = doc.getRoot().getChild( 0 );
 
-				expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.true;
-				expect( paragraph.getAttribute( 'blockIndent' ) ).to.equal( '42em' );
+					expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.true;
+					expect( paragraph.getAttribute( 'blockIndent' ) ).to.equal( '42em' );
 
-				expect( editor.getData() ).to.equal( '<p style="margin-left:42em;">foo</p>' );
-				expect( getViewData( editor.editing.view, { withoutSelection: true } ) )
-					.to.equal( '<p style="margin-left:42em">foo</p>' );
-			} );
+					expect( editor.getData() ).to.equal( '<p style="margin-left:42em;">foo</p>' );
+					expect( getViewData( editor.editing.view, { withoutSelection: true } ) )
+						.to.equal( '<p style="margin-left:42em">foo</p>' );
+				} );
 
-			it( 'should convert margin shortcut to indent attribute (three entries)', () => {
-				editor.setData( '<p style="margin:24em 42em 20em">foo</p>' );
+				it( 'should convert margin shortcut to indent attribute (three entries)', () => {
+					editor.setData( '<p style="margin:24em 42em 20em">foo</p>' );
 
-				const paragraph = doc.getRoot().getChild( 0 );
+					const paragraph = doc.getRoot().getChild( 0 );
 
-				expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.true;
-				expect( paragraph.getAttribute( 'blockIndent' ) ).to.equal( '42em' );
+					expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.true;
+					expect( paragraph.getAttribute( 'blockIndent' ) ).to.equal( '42em' );
+
+					expect( editor.getData() ).to.equal( '<p style="margin-left:42em;">foo</p>' );
+					expect( getViewData( editor.editing.view, { withoutSelection: true } ) )
+						.to.equal( '<p style="margin-left:42em">foo</p>' );
+				} );
 
-				expect( editor.getData() ).to.equal( '<p style="margin-left:42em;">foo</p>' );
-				expect( getViewData( editor.editing.view, { withoutSelection: true } ) )
-					.to.equal( '<p style="margin-left:42em">foo</p>' );
+				it( 'should convert margin shortcut to indent attribute (four entries)', () => {
+					editor.setData( '<p style="margin:24em 40em 24em 42em">foo</p>' );
+
+					const paragraph = doc.getRoot().getChild( 0 );
+
+					expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.true;
+					expect( paragraph.getAttribute( 'blockIndent' ) ).to.equal( '42em' );
+
+					expect( editor.getData() ).to.equal( '<p style="margin-left:42em;">foo</p>' );
+					expect( getViewData( editor.editing.view, { withoutSelection: true } ) )
+						.to.equal( '<p style="margin-left:42em">foo</p>' );
+				} );
 			} );
 
-			it( 'should convert margin shortcut to indent attribute (four entries)', () => {
-				editor.setData( '<p style="margin:24em 40em 24em 42em">foo</p>' );
+			describe( 'right–to–left content', () => {
+				beforeEach( () => {
+					return createTestEditor( {
+						indentBlock: { offset: 50, unit: 'px' },
+						contentLanguage: 'ar'
+					} ).then( newEditor => {
+						editor = newEditor;
+						model = editor.model;
+						doc = model.document;
+					} );
+				} );
 
-				const paragraph = doc.getRoot().getChild( 0 );
+				it( 'should convert margin-right to indent attribute (known offset)', () => {
+					editor.setData( '<p style="margin-right:50px">foo</p>' );
 
-				expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.true;
-				expect( paragraph.getAttribute( 'blockIndent' ) ).to.equal( '42em' );
+					const paragraph = doc.getRoot().getChild( 0 );
+
+					expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.true;
+					expect( paragraph.getAttribute( 'blockIndent' ) ).to.equal( '50px' );
+
+					expect( editor.getData() ).to.equal( '<p style="margin-right:50px;">foo</p>' );
+					expect( getViewData( editor.editing.view, { withoutSelection: true } ) )
+						.to.equal( '<p style="margin-right:50px">foo</p>' );
+				} );
 
-				expect( editor.getData() ).to.equal( '<p style="margin-left:42em;">foo</p>' );
-				expect( getViewData( editor.editing.view, { withoutSelection: true } ) )
-					.to.equal( '<p style="margin-left:42em">foo</p>' );
+				it( 'should convert margin-right to indent attribute (any offset)', () => {
+					editor.setData( '<p style="margin-right:42em">foo</p>' );
+
+					const paragraph = doc.getRoot().getChild( 0 );
+
+					expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.true;
+					expect( paragraph.getAttribute( 'blockIndent' ) ).to.equal( '42em' );
+
+					expect( editor.getData() ).to.equal( '<p style="margin-right:42em;">foo</p>' );
+					expect( getViewData( editor.editing.view, { withoutSelection: true } ) )
+						.to.equal( '<p style="margin-right:42em">foo</p>' );
+				} );
+
+				it( 'should convert margin shortcut to indent attribute (one entry)', () => {
+					editor.setData( '<p style="margin:42em">foo</p>' );
+
+					const paragraph = doc.getRoot().getChild( 0 );
+
+					expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.true;
+					expect( paragraph.getAttribute( 'blockIndent' ) ).to.equal( '42em' );
+
+					expect( editor.getData() ).to.equal( '<p style="margin-right:42em;">foo</p>' );
+					expect( getViewData( editor.editing.view, { withoutSelection: true } ) )
+						.to.equal( '<p style="margin-right:42em">foo</p>' );
+				} );
+
+				it( 'should convert margin shortcut to indent attribute (two entries)', () => {
+					editor.setData( '<p style="margin:24em 42em">foo</p>' );
+
+					const paragraph = doc.getRoot().getChild( 0 );
+
+					expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.true;
+					expect( paragraph.getAttribute( 'blockIndent' ) ).to.equal( '42em' );
+
+					expect( editor.getData() ).to.equal( '<p style="margin-right:42em;">foo</p>' );
+					expect( getViewData( editor.editing.view, { withoutSelection: true } ) )
+						.to.equal( '<p style="margin-right:42em">foo</p>' );
+				} );
+
+				it( 'should convert margin shortcut to indent attribute (three entries)', () => {
+					editor.setData( '<p style="margin:24em 42em 20em">foo</p>' );
+
+					const paragraph = doc.getRoot().getChild( 0 );
+
+					expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.true;
+					expect( paragraph.getAttribute( 'blockIndent' ) ).to.equal( '42em' );
+
+					expect( editor.getData() ).to.equal( '<p style="margin-right:42em;">foo</p>' );
+					expect( getViewData( editor.editing.view, { withoutSelection: true } ) )
+						.to.equal( '<p style="margin-right:42em">foo</p>' );
+				} );
+
+				it( 'should convert margin shortcut to indent attribute (four entries)', () => {
+					editor.setData( '<p style="margin:24em 40em 24em 42em">foo</p>' );
+
+					const paragraph = doc.getRoot().getChild( 0 );
+
+					expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.true;
+					expect( paragraph.getAttribute( 'blockIndent' ) ).to.equal( '40em' );
+
+					expect( editor.getData() ).to.equal( '<p style="margin-right:40em;">foo</p>' );
+					expect( getViewData( editor.editing.view, { withoutSelection: true } ) )
+						.to.equal( '<p style="margin-right:40em">foo</p>' );
+				} );
 			} );
 
 			it( 'should not convert class to indent attribute', () => {
-				editor.setData( '<p class="indent-1">foo</p>' );
+				return createTestEditor( {
+					indentBlock: { offset: 50, unit: 'px' }
+				} ).then( newEditor => {
+					editor = newEditor;
+					model = editor.model;
+					doc = model.document;
 
-				const paragraph = doc.getRoot().getChild( 0 );
+					editor.setData( '<p class="indent-1">foo</p>' );
 
-				expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.false;
+					const paragraph = doc.getRoot().getChild( 0 );
 
-				const expectedView = '<p>foo</p>';
+					expect( paragraph.hasAttribute( 'blockIndent' ) ).to.be.false;
 
-				expect( editor.getData() ).to.equal( expectedView );
-				expect( getViewData( editor.editing.view, { withoutSelection: true } ) ).to.equal( expectedView );
+					const expectedView = '<p>foo</p>';
+
+					expect( editor.getData() ).to.equal( expectedView );
+					expect( getViewData( editor.editing.view, { withoutSelection: true } ) ).to.equal( expectedView );
+				} );
 			} );
 		} );