Bladeren bron

Autoformat only the text after the last code element,

as agreed at https://github.com/ckeditor/ckeditor5/issues/1239#issuecomment-635281777.
Tomek Wytrębowicz 5 jaren geleden
bovenliggende
commit
7d62a812e1

+ 25 - 3
packages/ckeditor5-autoformat/src/inlineautoformatediting.js

@@ -7,8 +7,6 @@
  * @module autoformat/inlineautoformatediting
  */
 
-import getLastTextLine from '@ckeditor/ckeditor5-typing/src/utils/getlasttextline';
-
 /**
  * The inline autoformatting engine. It allows to format various inline patterns. For example,
  * it can be configured to make "foo" bold when typed `**foo**` (the `**` markers will be removed).
@@ -174,7 +172,7 @@ export default class InlineAutoformatEditing {
 
 			const focus = selection.focus;
 			const block = focus.parent;
-			const { text, range } = getLastTextLine( model.createRange( model.createPositionAt( block, 0 ), focus ), model );
+			const { text, range } = getTextAfterCode( model.createRange( model.createPositionAt( block, 0 ), focus ), model );
 			const testOutput = testCallback( text );
 			const rangesToFormat = testOutputToRanges( range.start, testOutput.format, model );
 			const rangesToRemove = testOutputToRanges( range.start, testOutput.remove, model );
@@ -216,3 +214,27 @@ function testOutputToRanges( start, arrays, model ) {
 			return model.createRange( start.getShiftedBy( array[ 0 ] ), start.getShiftedBy( array[ 1 ] ) );
 		} );
 }
+
+// Returns the last text line after the last code element from the given range.
+// It is similar to {@link module:typing/utils/getlasttextline.getLastTextLine `getLastTextLine()`},
+// but it ignores any text before the last `code`.
+//
+// @param {module:engine/model/range~Range} range
+// @param {module:engine/model/model~Model} model
+// @returns {module:typing/utils/getlasttextline~LastTextLineData}
+function getTextAfterCode( range, model ) {
+	let start = range.start;
+
+	const text = Array.from( range.getItems() ).reduce( ( rangeText, node ) => {
+		// Trim text to a last occurrence of an inline element and update range start.
+		if ( !( node.is( 'text' ) || node.is( 'textProxy' ) ) || node.getAttribute( 'code' ) ) {
+			start = model.createPositionAfter( node );
+
+			return '';
+		}
+
+		return rangeText + node.data;
+	}, '' );
+
+	return { text, range: model.createRange( start, range.end ) };
+}

+ 128 - 0
packages/ckeditor5-autoformat/tests/autoformat.js

@@ -422,6 +422,134 @@ describe( 'Autoformat', () => {
 			expect( getData( model ) ).to.equal( '<paragraph>**foobar**[]</paragraph>' );
 		} );
 
+		describe( 'with code element', () => {
+			it( 'should not format inside', () => {
+				// Test *.
+				setData( model, '<paragraph><$text code="true">fo*obar[]</$text></paragraph>' );
+
+				model.change( writer => {
+					writer.insertText( '*', { code: true }, doc.selection.getFirstPosition() );
+				} );
+
+				expect( getData( model ) ).to
+					.equal( '<paragraph><$text code="true">fo*obar*[]</$text></paragraph>' );
+
+				// Test __.
+				setData( model, '<paragraph><$text code="true">fo__obar_[]</$text></paragraph>' );
+
+				model.change( writer => {
+					writer.insertText( '_', { code: true }, doc.selection.getFirstPosition() );
+				} );
+
+				expect( getData( model ) ).to
+					.equal( '<paragraph><$text code="true">fo__obar__[]</$text></paragraph>' );
+
+				// Test ~~.
+				setData( model, '<paragraph><$text code="true">fo~~obar~[]</$text></paragraph>' );
+
+				model.change( writer => {
+					writer.insertText( '~', { code: true }, doc.selection.getFirstPosition() );
+				} );
+
+				expect( getData( model ) ).to
+					.equal( '<paragraph><$text code="true">fo~~obar~~[]</$text></paragraph>' );
+
+				// Test `.
+				setData( model, '<paragraph><$text code="true">fo`obar[]</$text></paragraph>' );
+
+				model.change( writer => {
+					writer.insertText( '`', { code: true }, doc.selection.getFirstPosition() );
+				} );
+
+				expect( getData( model ) ).to
+					.equal( '<paragraph><$text code="true">fo`obar`[]</$text></paragraph>' );
+			} );
+
+			it( 'should not format across', () => {
+				// Test *.
+				setData( model, '<paragraph><$text code="true">fo*o</$text>bar[]</paragraph>' );
+
+				model.change( writer => {
+					writer.insertText( '*', doc.selection.getFirstPosition() );
+				} );
+
+				expect( getData( model ) ).to
+					.equal( '<paragraph><$text code="true">fo*o</$text>bar*[]</paragraph>' );
+
+				// Test __.
+				setData( model, '<paragraph><$text code="true">fo__o</$text>bar_[]</paragraph>' );
+
+				model.change( writer => {
+					writer.insertText( '_', doc.selection.getFirstPosition() );
+				} );
+
+				expect( getData( model ) ).to
+					.equal( '<paragraph><$text code="true">fo__o</$text>bar__[]</paragraph>' );
+
+				// Test ~~.
+				setData( model, '<paragraph><$text code="true">fo~~o</$text>bar~[]</paragraph>' );
+
+				model.change( writer => {
+					writer.insertText( '~', doc.selection.getFirstPosition() );
+				} );
+
+				expect( getData( model ) ).to
+					.equal( '<paragraph><$text code="true">fo~~o</$text>bar~~[]</paragraph>' );
+
+				// Test `.
+				setData( model, '<paragraph><$text code="true">fo`o</$text>bar[]</paragraph>' );
+
+				model.change( writer => {
+					writer.insertText( '`', doc.selection.getFirstPosition() );
+				} );
+
+				expect( getData( model ) ).to
+					.equal( '<paragraph><$text code="true">fo`o</$text>bar`[]</paragraph>' );
+			} );
+
+			it( 'should format after', () => {
+				// Test *.
+				setData( model, '<paragraph><$text code="true">fo*o</$text>b*ar[]</paragraph>' );
+
+				model.change( writer => {
+					writer.insertText( '*', doc.selection.getFirstPosition() );
+				} );
+
+				expect( getData( model ) ).to
+					.equal( '<paragraph><$text code="true">fo*o</$text>b<$text italic="true">ar</$text>[]</paragraph>' );
+
+				// Test __.
+				setData( model, '<paragraph><$text code="true">fo__o</$text>b__ar_[]</paragraph>' );
+
+				model.change( writer => {
+					writer.insertText( '_', doc.selection.getFirstPosition() );
+				} );
+
+				expect( getData( model ) ).to
+					.equal( '<paragraph><$text code="true">fo__o</$text>b<$text bold="true">ar</$text>[]</paragraph>' );
+
+				// Test ~~.
+				setData( model, '<paragraph><$text code="true">fo~~o</$text>b~~ar~[]</paragraph>' );
+
+				model.change( writer => {
+					writer.insertText( '~', doc.selection.getFirstPosition() );
+				} );
+
+				expect( getData( model ) ).to
+					.equal( '<paragraph><$text code="true">fo~~o</$text>b<$text strikethrough="true">ar</$text>[]</paragraph>' );
+
+				// Test `.
+				setData( model, '<paragraph><$text code="true">fo`o</$text>b`ar[]</paragraph>' );
+
+				model.change( writer => {
+					writer.insertText( '`', doc.selection.getFirstPosition() );
+				} );
+
+				expect( getData( model ) ).to
+					.equal( '<paragraph><$text code="true">fo`o</$text>b<$text code="true">ar</$text>[]</paragraph>' );
+			} );
+		} );
+
 		it( 'should work with <softBreak>s in paragraph', () => {
 			setData( model, '<paragraph>foo<softBreak></softBreak>**barbaz*[]</paragraph>' );
 			model.change( writer => {

+ 1 - 1
packages/ckeditor5-autoformat/tests/manual/autoformat.html

@@ -1,3 +1,3 @@
 <div id="editor">
-	<p>This is the editor instance.</p>
+	<p>This is the editor instance, with a <code>code_element*2;</code> inside.</p>
 </div>