77 * @module autoformat/inlineautoformatediting
88 */
99
10- import LiveRange from '@ckeditor/ckeditor5-engine/src/model/liverange ' ;
10+ import ModelRange from '@ckeditor/ckeditor5-engine/src/model/range ' ;
1111
1212/**
1313 * The inline autoformatting engine. It allows to format various inline patterns. For example,
@@ -141,74 +141,43 @@ export default class InlineAutoformatEditing {
141141 } ) ;
142142
143143 editor . model . document . on ( 'change' , ( ) => {
144- const changes = editor . model . document . differ . getChanges ( ) ;
144+ const selection = editor . model . document . selection ;
145145
146- for ( const entry of changes ) {
147- if ( entry . type != 'insert' || entry . name != '$text' ) {
148- continue ;
149- }
150-
151- const selection = editor . model . document . selection ;
146+ // Do nothing if selection is not collapsed.
147+ if ( ! selection . isCollapsed ) {
148+ return ;
149+ }
152150
153- if ( ! selection . isCollapsed || ! selection . focus || ! selection . focus . parent ) {
154- continue ;
155- }
151+ const changes = Array . from ( editor . model . document . differ . getChanges ( ) ) ;
152+ const entry = changes [ 0 ] ;
156153
157- const block = selection . focus . parent ;
158- const text = getText ( block ) . slice ( 0 , selection . focus . offset ) ;
159- const ranges = testCallback ( text ) ;
160- const rangesToFormat = [ ] ;
161-
162- // Apply format before deleting text.
163- ranges . format . forEach ( range => {
164- if ( range [ 0 ] === undefined || range [ 1 ] === undefined ) {
165- return ;
166- }
167-
168- rangesToFormat . push ( LiveRange . createFromParentsAndOffsets (
169- block , range [ 0 ] ,
170- block , range [ 1 ]
171- ) ) ;
172- } ) ;
173-
174- const rangesToRemove = [ ] ;
175-
176- // Reverse order to not mix the offsets while removing.
177- ranges . remove . slice ( ) . reverse ( ) . forEach ( range => {
178- if ( range [ 0 ] === undefined || range [ 1 ] === undefined ) {
179- return ;
180- }
181-
182- rangesToRemove . push ( LiveRange . createFromParentsAndOffsets (
183- block , range [ 0 ] ,
184- block , range [ 1 ]
185- ) ) ;
186- } ) ;
187-
188- if ( ! ( rangesToFormat . length && rangesToRemove . length ) ) {
189- continue ;
190- }
154+ // Typing is represented by only a single change.
155+ if ( changes . length != 1 || entry . type !== 'insert' || entry . name != '$text' || entry . length != 1 ) {
156+ return ;
157+ }
191158
192- // Use enqueueChange to create new batch to separate typing batch from the auto-format changes.
193- editor . model . enqueueChange ( writer => {
194- const validRanges = editor . model . schema . getValidRanges ( rangesToFormat , attributeKey ) ;
159+ const block = selection . focus . parent ;
160+ const text = getText ( block ) . slice ( 0 , selection . focus . offset ) ;
161+ const testOutput = testCallback ( text ) ;
162+ const rangesToFormat = testOutputToRanges ( block , testOutput . format ) ;
163+ const rangesToRemove = testOutputToRanges ( block , testOutput . remove ) ;
195164
196- // Apply format.
197- formatCallback ( writer , validRanges ) ;
165+ if ( ! ( rangesToFormat . length && rangesToRemove . length ) ) {
166+ return ;
167+ }
198168
199- // Detach ranges used to apply Autoformat. Prevents memory leaks. #39
200- rangesToFormat . forEach ( range => range . detach ( ) ) ;
169+ // Use enqueueChange to create new batch to separate typing batch from the auto-format changes.
170+ editor . model . enqueueChange ( writer => {
171+ const validRanges = editor . model . schema . getValidRanges ( rangesToFormat , attributeKey ) ;
201172
202- // Remove delimiters.
203- for ( const range of rangesToRemove ) {
204- writer . remove ( range ) ;
173+ // Apply format.
174+ formatCallback ( writer , validRanges ) ;
205175
206- // Prevents memory leaks.
207- // https://github.com/ckeditor/ckeditor5-autoformat/issues/39
208- range . detach ( ) ;
209- }
210- } ) ;
211- }
176+ // Remove delimiters - use reversed order to not mix the offsets while removing.
177+ for ( const range of rangesToRemove . reverse ( ) ) {
178+ writer . remove ( range ) ;
179+ }
180+ } ) ;
212181 } ) ;
213182 }
214183}
@@ -221,3 +190,15 @@ export default class InlineAutoformatEditing {
221190function getText ( element ) {
222191 return Array . from ( element . getChildren ( ) ) . reduce ( ( a , b ) => a + b . data , '' ) ;
223192}
193+
194+ // Converts output of the test function provided to the InlineAutoformatEditing and converts it to the model ranges
195+ // inside provided block.
196+ //
197+ // @private
198+ // @param {module:engine/model/element~Element } block
199+ // @param {Array.<Array> } arrays
200+ function testOutputToRanges ( block , arrays ) {
201+ return arrays
202+ . filter ( array => ( array [ 0 ] !== undefined && array [ 1 ] !== undefined ) )
203+ . map ( array => ModelRange . createFromParentsAndOffsets ( block , array [ 0 ] , block , array [ 1 ] ) ) ;
204+ }
0 commit comments