8
0
Эх сурвалжийг харах

Merge pull request #27 from ckeditor/t/5

Fix: The Autoformat should not require other features. Closes #5 #17.

NOTE: The Autoformat feature doesn't require Bold, Italic, Heading, etc. any longer. In order to make the most of the plugin, please make sure that relevant features are loaded in your editor.
Aleksander Nowodzinski 8 жил өмнө
parent
commit
53a499a666

+ 4 - 5
packages/ckeditor5-autoformat/package.json

@@ -4,17 +4,16 @@
   "description": "Replaces predefined characters with corresponding structures.",
   "description": "Replaces predefined characters with corresponding structures.",
   "keywords": [],
   "keywords": [],
   "dependencies": {
   "dependencies": {
-    "@ckeditor/ckeditor5-basic-styles": "^0.8.1",
     "@ckeditor/ckeditor5-core": "^0.8.1",
     "@ckeditor/ckeditor5-core": "^0.8.1",
-    "@ckeditor/ckeditor5-engine": "^0.10.0",
-    "@ckeditor/ckeditor5-heading": "^0.9.1",
-    "@ckeditor/ckeditor5-list": "^0.6.1"
+    "@ckeditor/ckeditor5-engine": "^0.10.0"
   },
   },
   "devDependencies": {
   "devDependencies": {
+    "@ckeditor/ckeditor5-basic-styles": "^0.8.1",
     "@ckeditor/ckeditor5-dev-lint": "^3.0.0",
     "@ckeditor/ckeditor5-dev-lint": "^3.0.0",
     "@ckeditor/ckeditor5-editor-classic": "^0.7.3",
     "@ckeditor/ckeditor5-editor-classic": "^0.7.3",
     "@ckeditor/ckeditor5-enter": "^0.9.1",
     "@ckeditor/ckeditor5-enter": "^0.9.1",
-    "@ckeditor/ckeditor5-list": "*",
+    "@ckeditor/ckeditor5-heading": "^0.9.1",
+    "@ckeditor/ckeditor5-list": "^0.6.1",
     "@ckeditor/ckeditor5-paragraph": "^0.8.0",
     "@ckeditor/ckeditor5-paragraph": "^0.8.0",
     "@ckeditor/ckeditor5-typing": "^0.9.1",
     "@ckeditor/ckeditor5-typing": "^0.9.1",
     "@ckeditor/ckeditor5-undo": "^0.8.1",
     "@ckeditor/ckeditor5-undo": "^0.8.1",

+ 73 - 43
packages/ckeditor5-autoformat/src/autoformat.js

@@ -10,10 +10,6 @@
 import BlockAutoformatEngine from './blockautoformatengine';
 import BlockAutoformatEngine from './blockautoformatengine';
 import InlineAutoformatEngine from './inlineautoformatengine';
 import InlineAutoformatEngine from './inlineautoformatengine';
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
-import HeadingEngine from '@ckeditor/ckeditor5-heading/src/headingengine';
-import ListEngine from '@ckeditor/ckeditor5-list/src/listengine';
-import BoldEngine from '@ckeditor/ckeditor5-basic-styles/src/boldengine';
-import ItalicEngine from '@ckeditor/ckeditor5-basic-styles/src/italicengine';
 
 
 /**
 /**
  * Includes a set of predefined autoformatting actions.
  * Includes a set of predefined autoformatting actions.
@@ -47,16 +43,13 @@ import ItalicEngine from '@ckeditor/ckeditor5-basic-styles/src/italicengine';
  * * `**foo bar**` or `__foo bar__` – will bold the text,
  * * `**foo bar**` or `__foo bar__` – will bold the text,
  * * `*foo bar*` or `_foo bar_` – will italicize the text,
  * * `*foo bar*` or `_foo bar_` – will italicize the text,
  *
  *
+ * NOTE: Remember to add proper features to the editor configuration. Autoformatting will be enabled only for those
+ * commands that are included in the actual configuration. For example: `bold` autoformatting will not work if there is no
+ * `bold` command registered in the editor.
+ *
  * @extends module:core/plugin~Plugin
  * @extends module:core/plugin~Plugin
  */
  */
 export default class Autoformat extends Plugin {
 export default class Autoformat extends Plugin {
-	/**
-	 * @inheritDoc
-	 */
-	static get requires() {
-		return [ HeadingEngine, ListEngine, BoldEngine, ItalicEngine ];
-	}
-
 	/**
 	/**
 	 * @inheritDoc
 	 * @inheritDoc
 	 */
 	 */
@@ -67,44 +60,38 @@ export default class Autoformat extends Plugin {
 	/**
 	/**
 	 * @inheritDoc
 	 * @inheritDoc
 	 */
 	 */
-	init() {
+	afterInit() {
 		this._addListAutoformats();
 		this._addListAutoformats();
+		this._addBasicStylesAutoformats();
 		this._addHeadingAutoformats();
 		this._addHeadingAutoformats();
-		this._addInlineAutoformats();
 	}
 	}
 
 
 	/**
 	/**
-	 * Adds autoformatting related to ListEngine commands.
+	 * Adds autoformatting related to the {@link module:list/list~List}.
 	 *
 	 *
 	 * When typed:
 	 * When typed:
-	 * - `* ` or `- ` - paragraph will be changed to a bulleted list,
-	 * - `1. ` or `1) ` - paragraph will be changed to a numbered list (1 can be any digit or list of digits).
+	 * - `* ` or `- ` - a paragraph will be changed to a bulleted list,
+	 * - `1. ` or `1) ` - a paragraph will be changed to a numbered list ("1" can be any digit or list of digits).
 	 *
 	 *
 	 * @private
 	 * @private
 	 */
 	 */
 	_addListAutoformats() {
 	_addListAutoformats() {
-		new BlockAutoformatEngine( this.editor, /^[*-]\s$/, 'bulletedList' ); // eslint-disable-line no-new
-		new BlockAutoformatEngine( this.editor, /^\d+[.|)]?\s$/, 'numberedList' ); // eslint-disable-line no-new
-	}
+		const commands = this.editor.commands;
 
 
-	/**
-	 * Adds autoformatting related to HeadingEngine commands.
-	 * When typed `# ` or `## ` or `### ` paragraph will be changed to a corresponding heading level.
-	 *
-	 * @private
-	 */
-	_addHeadingAutoformats() {
-		// eslint-disable-next-line no-new
-		new BlockAutoformatEngine( this.editor, /^(#{1,3})\s$/, context => {
-			const { batch, match } = context;
-			const headingLevel = match[ 1 ].length;
+		if ( commands.has( 'bulletedList' ) ) {
+			// eslint-disable-next-line no-new
+			new BlockAutoformatEngine( this.editor, /^[*-]\s$/, 'bulletedList' );
+		}
 
 
-			this.editor.execute( `heading${ headingLevel }`, { batch } );
-		} );
+		if ( commands.has( 'numberedList' ) ) {
+			// eslint-disable-next-line no-new
+			new BlockAutoformatEngine( this.editor, /^\d+[.|)]?\s$/, 'numberedList' );
+		}
 	}
 	}
 
 
 	/**
 	/**
-	 * Adds inline autoformatting capabilities to the editor.
+	 * Adds autoformatting related to the {@link module:basic-styles/bold~Bold} and
+	 * {@link module:basic-styles/italic~Italic}.
 	 *
 	 *
 	 * When typed:
 	 * When typed:
 	 * - `**foobar**`: `**` characters are removed, and `foobar` is set to bold,
 	 * - `**foobar**`: `**` characters are removed, and `foobar` is set to bold,
@@ -114,15 +101,58 @@ export default class Autoformat extends Plugin {
 	 *
 	 *
 	 * @private
 	 * @private
 	 */
 	 */
-	_addInlineAutoformats() {
-		/* eslint-disable no-new */
-		new InlineAutoformatEngine( this.editor, /(\*\*)([^*]+)(\*\*)$/g, 'bold' );
-		new InlineAutoformatEngine( this.editor, /(__)([^_]+)(__)$/g, 'bold' );
-
-		// The italic autoformatter cannot be triggered by the bold markers, so we need to check the
-		// text before the pattern (e.g. `(?:^|[^\*])`).
-		new InlineAutoformatEngine( this.editor, /(?:^|[^*])(\*)([^*_]+)(\*)$/g, 'italic' );
-		new InlineAutoformatEngine( this.editor, /(?:^|[^_])(_)([^_]+)(_)$/g, 'italic' );
-		/* eslint-enable no-new */
+	_addBasicStylesAutoformats() {
+		const commands = this.editor.commands;
+
+		if ( commands.has( 'bold' ) ) {
+			/* eslint-disable no-new */
+			new InlineAutoformatEngine( this.editor, /(\*\*)([^*]+)(\*\*)$/g, 'bold' );
+			new InlineAutoformatEngine( this.editor, /(__)([^_]+)(__)$/g, 'bold' );
+			/* eslint-enable no-new */
+		}
+
+		if ( commands.has( 'italic' ) ) {
+			// The italic autoformatter cannot be triggered by the bold markers, so we need to check the
+			// text before the pattern (e.g. `(?:^|[^\*])`).
+
+			/* eslint-disable no-new */
+			new InlineAutoformatEngine( this.editor, /(?:^|[^*])(\*)([^*_]+)(\*)$/g, 'italic' );
+			new InlineAutoformatEngine( this.editor, /(?:^|[^_])(_)([^_]+)(_)$/g, 'italic' );
+			/* eslint-enable no-new */
+		}
+	}
+
+	/**
+	 * Adds autoformatting related to {@link module:heading/heading~Heading}.
+	 *
+	 * It is using a number at the end of the command name to associate it with the proper trigger:
+	 * * `heading1` will be executed when typing `#`,
+	 * * `heading2` will be executed when typing `##`,
+	 * * `heading3` will be executed when typing `###`.
+	 *
+	 * @private
+	 */
+	_addHeadingAutoformats() {
+		const commands = this.editor.commands;
+		const options = this.editor.config.get( 'heading.options' );
+
+		if ( options ) {
+			for ( const option of options ) {
+				const commandName = option.modelElement;
+				let match;
+
+				if ( commands.has( commandName ) && ( match = commandName.match( /\d+$/ ) ) ) {
+					const level = match[ 0 ];
+					const regExp = new RegExp( `^(#{${ level }})\\s$` );
+
+					// eslint-disable-next-line no-new
+					new BlockAutoformatEngine( this.editor, regExp, context => {
+						const { batch } = context;
+
+						this.editor.execute( commandName, { batch } );
+					} );
+				}
+			}
+		}
 	}
 	}
 }
 }

+ 104 - 1
packages/ckeditor5-autoformat/tests/autoformat.js

@@ -5,6 +5,10 @@
 
 
 import Autoformat from '../src/autoformat';
 import Autoformat from '../src/autoformat';
 import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
 import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
+import ListEngine from '@ckeditor/ckeditor5-list/src/listengine';
+import HeadingEngine from '@ckeditor/ckeditor5-heading/src/headingengine';
+import BoldEngine from '@ckeditor/ckeditor5-basic-styles/src/boldengine';
+import ItalicEngine from '@ckeditor/ckeditor5-basic-styles/src/italicengine';
 import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
 import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
 import Enter from '@ckeditor/ckeditor5-enter/src/enter';
 import Enter from '@ckeditor/ckeditor5-enter/src/enter';
 import { setData, getData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
 import { setData, getData } from '@ckeditor/ckeditor5-engine/src/dev-utils/model';
@@ -17,7 +21,7 @@ describe( 'Autoformat', () => {
 
 
 	beforeEach( () => {
 	beforeEach( () => {
 		return VirtualTestEditor.create( {
 		return VirtualTestEditor.create( {
-			plugins: [ Enter, Paragraph, Autoformat ]
+			plugins: [ Enter, Paragraph, Autoformat, ListEngine, HeadingEngine, BoldEngine, ItalicEngine ]
 		} )
 		} )
 		.then( newEditor => {
 		.then( newEditor => {
 			editor = newEditor;
 			editor = newEditor;
@@ -141,4 +145,103 @@ describe( 'Autoformat', () => {
 			expect( getData( doc ) ).to.equal( '<paragraph>foo <$text bold="true">bar</$text>[] baz</paragraph>' );
 			expect( getData( doc ) ).to.equal( '<paragraph>foo <$text bold="true">bar</$text>[] baz</paragraph>' );
 		} );
 		} );
 	} );
 	} );
+
+	describe( 'without commands', () => {
+		beforeEach( () => {
+			return VirtualTestEditor.create( {
+				plugins: [ Enter, Paragraph, Autoformat ]
+			} )
+				.then( newEditor => {
+					editor = newEditor;
+					doc = editor.document;
+					batch = doc.batch();
+				} );
+		} );
+
+		it( 'should not replace asterisk with bulleted list item', () => {
+			setData( doc, '<paragraph>*[]</paragraph>' );
+			doc.enqueueChanges( () => {
+				batch.insert( doc.selection.getFirstPosition(), ' ' );
+			} );
+
+			expect( getData( doc ) ).to.equal( '<paragraph>* []</paragraph>' );
+		} );
+
+		it( 'should not replace minus character with bulleted list item', () => {
+			setData( doc, '<paragraph>-[]</paragraph>' );
+			doc.enqueueChanges( () => {
+				batch.insert( doc.selection.getFirstPosition(), ' ' );
+			} );
+
+			expect( getData( doc ) ).to.equal( '<paragraph>- []</paragraph>' );
+		} );
+
+		it( 'should not replace digit with numbered list item', () => {
+			setData( doc, '<paragraph>1.[]</paragraph>' );
+			doc.enqueueChanges( () => {
+				batch.insert( doc.selection.getFirstPosition(), ' ' );
+			} );
+
+			expect( getData( doc ) ).to.equal( '<paragraph>1. []</paragraph>' );
+		} );
+
+		it( 'should not replace hash character with heading', () => {
+			setData( doc, '<paragraph>#[]</paragraph>' );
+			doc.enqueueChanges( () => {
+				batch.insert( doc.selection.getFirstPosition(), ' ' );
+			} );
+
+			expect( getData( doc ) ).to.equal( '<paragraph># []</paragraph>' );
+		} );
+
+		it( 'should not replace two hash characters with heading level 2', () => {
+			setData( doc, '<paragraph>##[]</paragraph>' );
+			doc.enqueueChanges( () => {
+				batch.insert( doc.selection.getFirstPosition(), ' ' );
+			} );
+
+			expect( getData( doc ) ).to.equal( '<paragraph>## []</paragraph>' );
+		} );
+
+		it( 'should not replace both `**` with bold', () => {
+			setData( doc, '<paragraph>**foobar*[]</paragraph>' );
+			doc.enqueueChanges( () => {
+				batch.insert( doc.selection.getFirstPosition(), '*' );
+			} );
+
+			expect( getData( doc ) ).to.equal( '<paragraph>**foobar**[]</paragraph>' );
+		} );
+
+		it( 'should not replace both `*` with italic', () => {
+			setData( doc, '<paragraph>*foobar[]</paragraph>' );
+			doc.enqueueChanges( () => {
+				batch.insert( doc.selection.getFirstPosition(), '*' );
+			} );
+
+			expect( getData( doc ) ).to.equal( '<paragraph>*foobar*[]</paragraph>' );
+		} );
+
+		it( 'should use only configured headings', () => {
+			return VirtualTestEditor.create( {
+				plugins: [ Enter, Paragraph, Autoformat, ListEngine, HeadingEngine ],
+				heading: {
+					options: [
+						{ modelElement: 'paragraph' },
+						{ modelElement: 'heading1', viewElement: 'h2' }
+					]
+				}
+			} )
+			.then( editor => {
+				doc = editor.document;
+				batch = doc.batch();
+
+				setData( doc, '<paragraph>##[]</paragraph>' );
+				doc.enqueueChanges( () => {
+					batch.insert( doc.selection.getFirstPosition(), ' ' );
+				} );
+
+				expect( getData( doc ) ).to.equal( '<paragraph>## []</paragraph>' );
+			} );
+		} );
+	} );
 } );
 } );